View | Details | Raw Unified | Return to bug 983 | Differences between
and this patch

Collapse All | Expand All

(-)auth.c (-3 / +59 lines)
Lines 171-177 allowed_user(struct passwd * pw) Link Here
171
}
171
}
172
172
173
void
173
void
174
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
174
auth_log(Authctxt *authctxt, int authenticated, const char *method,
175
    const char *submethod, const char *info)
175
{
176
{
176
	void (*authlog) (const char *fmt,...) = verbose;
177
	void (*authlog) (const char *fmt,...) = verbose;
177
	char *authmsg;
178
	char *authmsg;
Lines 191-199 auth_log(Authctxt *authctxt, int authent Link Here
191
	else
192
	else
192
		authmsg = authenticated ? "Accepted" : "Failed";
193
		authmsg = authenticated ? "Accepted" : "Failed";
193
194
194
	authlog("%s %s for %s%.100s from %.200s port %d%s",
195
	authlog("%s %s%s%s for %s%.100s from %.200s port %d%s",
195
	    authmsg,
196
	    authmsg,
196
	    method,
197
	    method,
198
	    submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod,
197
	    authctxt->valid ? "" : "invalid user ",
199
	    authctxt->valid ? "" : "invalid user ",
198
	    authctxt->user,
200
	    authctxt->user,
199
	    get_remote_ipaddr(),
201
	    get_remote_ipaddr(),
Lines 205-211 auth_log(Authctxt *authctxt, int authent Link Here
205
 * Check whether root logins are disallowed.
207
 * Check whether root logins are disallowed.
206
 */
208
 */
207
int
209
int
208
auth_root_allowed(char *method)
210
auth_root_allowed(const char *method)
209
{
211
{
210
	switch (options.permit_root_login) {
212
	switch (options.permit_root_login) {
211
	case PERMIT_YES:
213
	case PERMIT_YES:
Lines 470-473 fakepw(void) Link Here
470
	fake.pw_shell = "/nonexist";
472
	fake.pw_shell = "/nonexist";
471
473
472
	return (&fake);
474
	return (&fake);
475
}
476
477
int
478
auth_method_in_list(const char *list, const char *method)
479
{
480
	char *cp;
481
482
	cp = match_list(method, list, NULL);
483
	if (cp != NULL) {
484
		xfree(cp);
485
		return 1;
486
	}
487
488
	return 0;
489
}
490
491
#define	DELIM	","
492
int
493
auth_remove_from_list(char **list, const char *method)
494
{
495
	char *oldlist, *cp, *newlist = NULL;
496
	u_int len = 0, ret = 0;
497
498
	if (list == NULL || *list == NULL)
499
		return (0);
500
501
	oldlist = *list;
502
	len = strlen(oldlist) + 1;
503
	newlist = xmalloc(len);
504
	memset(newlist, '\0', len);
505
506
	/* Remove method from list, if present */
507
	for (;;) {
508
		if ((cp = strsep(&oldlist, DELIM)) == NULL)
509
			break;
510
		if (*cp == '\0')
511
			continue;
512
		if (strcmp(cp, method) != 0) {
513
			if (*newlist != '\0')
514
				strlcat(newlist, DELIM, len);
515
			strlcat(newlist, cp, len);
516
		} else
517
			ret++;
518
	}
519
520
	/* Return NULL instead of empty list */
521
	if (*newlist == '\0') {
522
		xfree(newlist);
523
		newlist = NULL;
524
	}
525
	xfree(*list);
526
	*list = newlist;
527
	
528
	return (ret);
473
}
529
}
(-)auth.h (-3 / +8 lines)
Lines 119-127 void krb5_cleanup_proc(Authctxt *authctx Link Here
119
void	do_authentication(Authctxt *);
119
void	do_authentication(Authctxt *);
120
void	do_authentication2(Authctxt *);
120
void	do_authentication2(Authctxt *);
121
121
122
void	auth_log(Authctxt *, int, char *, char *);
122
void	auth_log(Authctxt *, int, const char *, const char *, const char *);
123
void	userauth_finish(Authctxt *, int, char *);
123
void	userauth_finish(Authctxt *, int, const char *, const char *);
124
int	auth_root_allowed(char *);
124
int	auth_root_allowed(const char *);
125
125
126
char	*auth2_read_banner(void);
126
char	*auth2_read_banner(void);
127
127
Lines 162-167 void auth_debug_send(void); Link Here
162
void	 auth_debug_reset(void);
162
void	 auth_debug_reset(void);
163
163
164
struct passwd *fakepw(void);
164
struct passwd *fakepw(void);
165
int	 auth_method_in_list(const char *, const char *);
166
int	 auth_remove_from_list(char **, const char *);
167
168
int	 auth1_check_required(const char *);
169
int	 auth2_check_required(const char *);
165
170
166
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
171
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
167
172
(-)auth1.c (-5 / +88 lines)
Lines 91-96 static const struct AuthMethod1 Link Here
91
	return (NULL);
91
	return (NULL);
92
}
92
}
93
93
94
static const struct AuthMethod1 *
95
lookup_authmethod1_by_name(const char *name)
96
{
97
	int i;
98
99
	for (i = 0; auth1_methods[i].name != NULL; i++)
100
		if (strcmp(auth1_methods[i].name, name) == 0)
101
			return (&(auth1_methods[i]));
102
103
	return NULL;
104
}
105
106
#define	DELIM	","
107
int
108
auth1_check_required(const char *list)
109
{
110
	char *orig_methods, *methods, *cp;
111
	static const struct AuthMethod1 *m;
112
	int ret = 0;
113
114
	orig_methods = methods = xstrdup(list);
115
	for(;;) { /* XXX maybe: while ((cp = ...) != NULL) ? */
116
		if ((cp = strsep(&methods, DELIM)) == NULL)
117
			break;
118
		debug2("auth1_check_required: method \"%s\"", cp);
119
		if (*cp == '\0') {
120
			debug("auth1_check_required: empty method");
121
			ret = -1;
122
		}
123
		if ((m = lookup_authmethod1_by_name(cp)) == NULL) {
124
			debug("auth1_check_required: unknown method "
125
			    "\"%s\"", cp);
126
			ret = -1;
127
		}
128
		if (*(m->enabled) == 0) {
129
			debug("auth1_check_required: method %s explicitly "
130
			    "disabled", cp);
131
			ret = -1;
132
		}
133
		/* Activate method if it isn't already */
134
		if (*(m->enabled) == -1)
135
			*(m->enabled) = 1;
136
        }
137
	xfree(orig_methods);
138
	return (ret);
139
}
140
94
static char *
141
static char *
95
get_authname(int type)
142
get_authname(int type)
96
{
143
{
Lines 232-237 do_authloop(Authctxt *authctxt) Link Here
232
{
279
{
233
	int authenticated = 0;
280
	int authenticated = 0;
234
	char info[1024];
281
	char info[1024];
282
	const char *meth_name;
235
	int type = 0;
283
	int type = 0;
236
	const struct AuthMethod1 *meth;
284
	const struct AuthMethod1 *meth;
237
285
Lines 239-250 do_authloop(Authctxt *authctxt) Link Here
239
	    authctxt->valid ? "" : "invalid user ", authctxt->user);
287
	    authctxt->valid ? "" : "invalid user ", authctxt->user);
240
288
241
	/* If the user has no password, accept authentication immediately. */
289
	/* If the user has no password, accept authentication immediately. */
242
	if (options.password_authentication &&
290
	if (options.required_auth1 == NULL && options.password_authentication &&
243
#ifdef KRB5
291
#ifdef KRB5
244
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
292
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
245
#endif
293
#endif
246
	    PRIVSEP(auth_password(authctxt, ""))) {
294
	    PRIVSEP(auth_password(authctxt, ""))) {
247
		auth_log(authctxt, 1, "without authentication", "");
295
		auth_log(authctxt, 1, "without authentication", NULL, "");
248
		return;
296
		return;
249
	}
297
	}
250
298
Lines 261-269 do_authloop(Authctxt *authctxt) Link Here
261
309
262
		/* Get a packet from the client. */
310
		/* Get a packet from the client. */
263
		type = packet_read();
311
		type = packet_read();
312
		meth_name = get_authname(type);
264
		if ((meth = lookup_authmethod1(type)) == NULL) {
313
		if ((meth = lookup_authmethod1(type)) == NULL) {
265
			logit("Unknown message during authentication: "
314
			logit("Unknown message during authentication: type %d",
266
			    "type %d", type);
315
			    type);
267
			goto skip;
316
			goto skip;
268
		}
317
		}
269
318
Lines 272-277 do_authloop(Authctxt *authctxt) Link Here
272
			goto skip;
321
			goto skip;
273
		}
322
		}
274
323
324
		/*
325
		 * Skip methods not in required list, until all the required
326
		 * ones are done
327
		 */
328
		if (options.required_auth1 != NULL &&
329
		    !auth_method_in_list(options.required_auth1, meth_name)) {
330
			debug("Skipping method \"%s\" until required "
331
			    "authentication completed", meth_name);
332
			goto skip;
333
		}
334
275
		authenticated = meth->method(authctxt, info, sizeof(info));
335
		authenticated = meth->method(authctxt, info, sizeof(info));
276
		if (authenticated == -1)
336
		if (authenticated == -1)
277
			continue; /* "postponed" */
337
			continue; /* "postponed" */
Lines 291-297 do_authloop(Authctxt *authctxt) Link Here
291
351
292
 skip:
352
 skip:
293
		/* Log before sending the reply */
353
		/* Log before sending the reply */
294
		auth_log(authctxt, authenticated, get_authname(type), info);
354
		auth_log(authctxt, authenticated, meth_name, NULL, info);
355
356
		/* Loop until the required authmethods are done */
357
		if (authenticated && options.required_auth1 != NULL) {
358
			if (auth_remove_from_list(&options.required_auth1,
359
			    meth_name) != 1)
360
				fatal("INTERNAL ERROR: authenticated method "
361
				    "\"%s\" not in required list \"%s\"",
362
				    meth_name, options.required_auth1);
363
			debug2("do_authloop: required list now: %s",
364
			    options.required_auth1 == NULL ?
365
			    "DONE" : options.required_auth1);
366
			if (options.required_auth1 == NULL)
367
				return;
368
			authenticated = 0;
369
			/*
370
			 * Disable method so client can't authenticate with it
371
			 * after the required authentications are complete.
372
			 */
373
			*(meth->enabled) = 0;
374
			packet_send_debug("Further authentication required");
375
			goto send_fail;
376
		}
295
377
296
		if (authenticated)
378
		if (authenticated)
297
			return;
379
			return;
Lines 299-304 do_authloop(Authctxt *authctxt) Link Here
299
		if (authctxt->failures++ > options.max_authtries)
381
		if (authctxt->failures++ > options.max_authtries)
300
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
382
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
301
383
384
 send_fail:
302
		packet_start(SSH_SMSG_FAILURE);
385
		packet_start(SSH_SMSG_FAILURE);
303
		packet_send();
386
		packet_send();
304
		packet_write_wait();
387
		packet_write_wait();
(-)auth2-chall.c (-10 / +4 lines)
Lines 236-244 input_userauth_info_response(int type, u Link Here
236
{
236
{
237
	Authctxt *authctxt = ctxt;
237
	Authctxt *authctxt = ctxt;
238
	KbdintAuthctxt *kbdintctxt;
238
	KbdintAuthctxt *kbdintctxt;
239
	int authenticated = 0, res, len;
239
	int authenticated = 0, res;
240
	u_int i, nresp;
240
	u_int i, nresp;
241
	char **response = NULL, *method;
241
	char **response = NULL;
242
242
243
	if (authctxt == NULL)
243
	if (authctxt == NULL)
244
		fatal("input_userauth_info_response: no authctxt");
244
		fatal("input_userauth_info_response: no authctxt");
Lines 285-296 input_userauth_info_response(int type, u Link Here
285
		break;
285
		break;
286
	}
286
	}
287
287
288
	len = strlen("keyboard-interactive") + 2 +
289
		strlen(kbdintctxt->device->name);
290
	method = xmalloc(len);
291
	snprintf(method, len, "keyboard-interactive/%s",
292
	    kbdintctxt->device->name);
293
294
	if (!authctxt->postponed) {
288
	if (!authctxt->postponed) {
295
		if (authenticated) {
289
		if (authenticated) {
296
			auth2_challenge_stop(authctxt);
290
			auth2_challenge_stop(authctxt);
Lines 300-307 input_userauth_info_response(int type, u Link Here
300
			auth2_challenge_start(authctxt);
294
			auth2_challenge_start(authctxt);
301
		}
295
		}
302
	}
296
	}
303
	userauth_finish(authctxt, authenticated, method);
297
	userauth_finish(authctxt, authenticated, "keyboard-interactive",
304
	xfree(method);
298
	    kbdintctxt->device->name);
305
}
299
}
306
300
307
void
301
void
(-)auth2-gss.c (-3 / +3 lines)
Lines 157-163 input_gssapi_token(int type, u_int32_t p Link Here
157
		}
157
		}
158
		authctxt->postponed = 0;
158
		authctxt->postponed = 0;
159
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
159
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
160
		userauth_finish(authctxt, 0, "gssapi-with-mic");
160
		userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
161
	} else {
161
	} else {
162
		if (send_tok.length != 0) {
162
		if (send_tok.length != 0) {
163
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
163
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
Lines 245-251 input_gssapi_exchange_complete(int type, Link Here
245
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
245
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
246
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
246
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
247
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
247
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
248
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
248
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
249
}
249
}
250
250
251
static void
251
static void
Lines 285-291 input_gssapi_mic(int type, u_int32_t ple Link Here
285
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
285
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
286
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
286
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
287
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
287
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
288
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
288
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
289
}
289
}
290
290
291
Authmethod method_gssapi = {
291
Authmethod method_gssapi = {
(-)auth2-none.c (-1 / +1 lines)
Lines 115-121 userauth_none(Authctxt *authctxt) Link Here
115
	none_enabled = 0;
115
	none_enabled = 0;
116
	packet_check_eom();
116
	packet_check_eom();
117
	userauth_banner();
117
	userauth_banner();
118
	if (options.password_authentication)
118
	if (options.password_authentication && options.required_auth2 == NULL)
119
		return (PRIVSEP(auth_password(authctxt, "")));
119
		return (PRIVSEP(auth_password(authctxt, "")));
120
	return (0);
120
	return (0);
121
}
121
}
(-)auth2.c (-10 / +84 lines)
Lines 136-142 input_userauth_request(int type, u_int32 Link Here
136
{
136
{
137
	Authctxt *authctxt = ctxt;
137
	Authctxt *authctxt = ctxt;
138
	Authmethod *m = NULL;
138
	Authmethod *m = NULL;
139
	char *user, *service, *method, *style = NULL;
139
	char *user, *service, *method, *active_methods, *style = NULL;
140
	int authenticated = 0;
140
	int authenticated = 0;
141
141
142
	if (authctxt == NULL)
142
	if (authctxt == NULL)
Lines 185-196 input_userauth_request(int type, u_int32 Link Here
185
	authctxt->postponed = 0;
185
	authctxt->postponed = 0;
186
186
187
	/* try to authenticate user */
187
	/* try to authenticate user */
188
	m = authmethod_lookup(method);
188
	active_methods = authmethods_get();
189
	if (m != NULL) {
189
	if (strcmp(method, "none") == 0 || 
190
		debug2("input_userauth_request: try method %s", method);
190
	    auth_method_in_list(active_methods, method)) {
191
		authenticated =	m->userauth(authctxt);
191
		m = authmethod_lookup(method);
192
		if (m != NULL) {
193
			debug2("input_userauth_request: try method %s", method);
194
			authenticated =	m->userauth(authctxt);
195
		}
192
	}
196
	}
193
	userauth_finish(authctxt, authenticated, method);
197
	xfree(active_methods);
198
	userauth_finish(authctxt, authenticated, method, NULL);
194
199
195
	xfree(service);
200
	xfree(service);
196
	xfree(user);
201
	xfree(user);
Lines 198-206 input_userauth_request(int type, u_int32 Link Here
198
}
203
}
199
204
200
void
205
void
201
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
206
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
207
    const char *submethod)
202
{
208
{
203
	char *methods;
209
	char *methods;
210
	Authmethod *m = NULL;
211
	u_int partial = 0;
204
212
205
	if (!authctxt->valid && authenticated)
213
	if (!authctxt->valid && authenticated)
206
		fatal("INTERNAL ERROR: authenticated invalid user %s",
214
		fatal("INTERNAL ERROR: authenticated invalid user %s",
Lines 212-223 userauth_finish(Authctxt *authctxt, int Link Here
212
		authenticated = 0;
220
		authenticated = 0;
213
221
214
	/* Log before sending the reply */
222
	/* Log before sending the reply */
215
	auth_log(authctxt, authenticated, method, " ssh2");
223
	auth_log(authctxt, authenticated, method, submethod, " ssh2");
216
224
217
	if (authctxt->postponed)
225
	if (authctxt->postponed)
218
		return;
226
		return;
219
227
220
	/* XXX todo: check if multiple auth methods are needed */
228
	/* Handle RequiredAuthentications2: loop until required methods done */
229
	if (authenticated && options.required_auth2 != NULL) {
230
		if ((m = authmethod_lookup(method)) == NULL)
231
			fatal("INTERNAL ERROR: authenticated method "
232
			    "\"%s\" unknown", method);
233
		if (auth_remove_from_list(&options.required_auth2, method) != 1)
234
			fatal("INTERNAL ERROR: authenticated method "
235
			    "\"%s\" not in required list \"%s\"", 
236
			    method, options.required_auth2);
237
		debug2("userauth_finish: required list now: %s",
238
		    options.required_auth2 == NULL ?
239
		    "DONE" : options.required_auth2);
240
		/*
241
		 * Disable method so client can't authenticate with it after
242
		 * the required authentications are complete.
243
		 */
244
		if (m->enabled != NULL)
245
			*(m->enabled) = 0;
246
		authenticated = 0;
247
		partial = 1;
248
		goto send_fail;
249
	}
250
221
	if (authenticated == 1) {
251
	if (authenticated == 1) {
222
		/* turn off userauth */
252
		/* turn off userauth */
223
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
253
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
Lines 229-238 userauth_finish(Authctxt *authctxt, int Link Here
229
	} else {
259
	} else {
230
		if (authctxt->failures++ > options.max_authtries)
260
		if (authctxt->failures++ > options.max_authtries)
231
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
261
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
262
 send_fail:
232
		methods = authmethods_get();
263
		methods = authmethods_get();
233
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
264
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
234
		packet_put_cstring(methods);
265
		packet_put_cstring(methods);
235
		packet_put_char(0);	/* XXX partial success, unused */
266
		packet_put_char(partial);
236
		packet_send();
267
		packet_send();
237
		packet_write_wait();
268
		packet_write_wait();
238
		xfree(methods);
269
		xfree(methods);
Lines 246-251 authmethods_get(void) Link Here
246
	char *list;
277
	char *list;
247
	int i;
278
	int i;
248
279
280
	if (options.required_auth2 != NULL)
281
		return xstrdup(options.required_auth2);
282
249
	buffer_init(&b);
283
	buffer_init(&b);
250
	for (i = 0; authmethods[i] != NULL; i++) {
284
	for (i = 0; authmethods[i] != NULL; i++) {
251
		if (strcmp(authmethods[i]->name, "none") == 0)
285
		if (strcmp(authmethods[i]->name, "none") == 0)
Lines 278-281 authmethod_lookup(const char *name) Link Here
278
	debug2("Unrecognized authentication method name: %s",
312
	debug2("Unrecognized authentication method name: %s",
279
	    name ? name : "NULL");
313
	    name ? name : "NULL");
280
	return NULL;
314
	return NULL;
315
}
316
317
#define DELIM ","
318
319
int
320
auth2_check_required(const char *list)
321
{
322
	char *orig_methods, *methods, *cp;
323
	struct Authmethod *m;
324
	int i, ret = 0;
325
326
	orig_methods = methods = xstrdup(list);
327
	for(;;) {
328
		if ((cp = strsep(&methods, DELIM)) == NULL)
329
			break;
330
		debug2("auth2_check_required: method \"%s\"", cp);
331
		if (*cp == '\0') {
332
			debug("auth2_check_required: empty method");
333
			ret = -1;
334
		}
335
		for (i = 0; authmethods[i] != NULL; i++)
336
			if (strcmp(cp, authmethods[i]->name) == 0)
337
				break;
338
		if ((m = authmethods[i]) == NULL) {
339
			debug("auth2_check_required: unknown method "
340
			    "\"%s\"", cp);
341
			ret = -1;
342
			break;
343
		}
344
		if (m->enabled == NULL || *(m->enabled) == 0) {
345
			debug("auth2_check_required: method %s explicitly "
346
			    "disabled", cp);
347
			ret = -1;
348
		}
349
		/* Activate method if it isn't already */
350
		if (*(m->enabled) == -1)
351
			*(m->enabled) = 1;
352
	}
353
	xfree(orig_methods);
354
	return (ret);
281
}
355
}
(-)monitor.c (-4 / +21 lines)
Lines 256-262 void Link Here
256
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
256
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
257
{
257
{
258
	struct mon_table *ent;
258
	struct mon_table *ent;
259
	int authenticated = 0;
259
	int no_increment, authenticated = 0;
260
	char **req_auth;
260
261
261
	debug3("preauth child monitor started");
262
	debug3("preauth child monitor started");
262
263
Lines 265-276 monitor_child_preauth(Authctxt *_authctx Link Here
265
266
266
	if (compat20) {
267
	if (compat20) {
267
		mon_dispatch = mon_dispatch_proto20;
268
		mon_dispatch = mon_dispatch_proto20;
269
		req_auth = &options.required_auth2;
268
270
269
		/* Permit requests for moduli and signatures */
271
		/* Permit requests for moduli and signatures */
270
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
272
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
271
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
273
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
272
	} else {
274
	} else {
273
		mon_dispatch = mon_dispatch_proto15;
275
		mon_dispatch = mon_dispatch_proto15;
276
		req_auth = &options.required_auth1;
274
277
275
		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
278
		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
276
	}
279
	}
Lines 278-283 monitor_child_preauth(Authctxt *_authctx Link Here
278
	/* The first few requests do not require asynchronous access */
281
	/* The first few requests do not require asynchronous access */
279
	while (!authenticated) {
282
	while (!authenticated) {
280
		auth_method = "unknown";
283
		auth_method = "unknown";
284
		no_increment = 1;
281
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
285
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
282
		if (authenticated) {
286
		if (authenticated) {
283
			if (!(ent->flags & MON_AUTHDECIDE))
287
			if (!(ent->flags & MON_AUTHDECIDE))
Lines 287-297 monitor_child_preauth(Authctxt *_authctx Link Here
287
			    !auth_root_allowed(auth_method))
291
			    !auth_root_allowed(auth_method))
288
				authenticated = 0;
292
				authenticated = 0;
289
		}
293
		}
294
		/* Loop until the required authmethods are done */
295
		if (authenticated && *req_auth != NULL) {
296
			if (auth_remove_from_list(req_auth, auth_method) != 1)
297
				fatal("INTERNAL ERROR: authenticated method "
298
				    "\"%s\" not in required list \"%s\"",
299
				    auth_method, *req_auth);
300
			debug2("monitor_child_preauth: required list now: %s",
301
			    *req_auth == NULL ? "DONE" : *req_auth);
302
			if (*req_auth != NULL)
303
				authenticated = 0;
304
			no_increment = 1;
305
		}
290
306
291
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
307
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
292
			auth_log(authctxt, authenticated, auth_method,
308
			auth_log(authctxt, authenticated, auth_method, NULL,
293
			    compat20 ? " ssh2" : "");
309
			    compat20 ? " ssh2" : "");
294
			if (!authenticated)
310
			if (!authenticated && !no_increment)
295
				authctxt->failures++;
311
				authctxt->failures++;
296
		}
312
		}
297
	}
313
	}
Lines 780-786 mm_answer_keyallowed(int sock, Buffer *m Link Here
780
		hostbased_chost = chost;
796
		hostbased_chost = chost;
781
	} else {
797
	} else {
782
		/* Log failed attempt */
798
		/* Log failed attempt */
783
		auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
799
		auth_log(authctxt, 0, auth_method, NULL,
800
		    compat20 ? " ssh2" : "");
784
		xfree(blob);
801
		xfree(blob);
785
		xfree(cuser);
802
		xfree(cuser);
786
		xfree(chost);
803
		xfree(chost);
(-)servconf.c (+34 lines)
Lines 36-41 Link Here
36
#include "key.h"
36
#include "key.h"
37
#include "kex.h"
37
#include "kex.h"
38
#include "mac.h"
38
#include "mac.h"
39
#include "hostfile.h"
40
#include "auth.h"
39
#include "match.h"
41
#include "match.h"
40
#include "channels.h"
42
#include "channels.h"
41
#include "groupaccess.h"
43
#include "groupaccess.h"
Lines 117-122 initialize_server_options(ServerOptions Link Here
117
	options->authorized_keys_file2 = NULL;
119
	options->authorized_keys_file2 = NULL;
118
	options->num_accept_env = 0;
120
	options->num_accept_env = 0;
119
	options->permit_tun = -1;
121
	options->permit_tun = -1;
122
	options->required_auth1 = NULL;
123
	options->required_auth2 = NULL;
120
	options->num_permitted_opens = -1;
124
	options->num_permitted_opens = -1;
121
	options->adm_forced_command = NULL;
125
	options->adm_forced_command = NULL;
122
	options->chroot_directory = NULL;
126
	options->chroot_directory = NULL;
Lines 275-280 typedef enum { Link Here
275
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
279
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
276
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
280
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
277
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
281
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
282
	sRequiredAuthentications1, sRequiredAuthentications2,
278
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
283
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
279
	sUsePrivilegeSeparation, sAllowAgentForwarding,
284
	sUsePrivilegeSeparation, sAllowAgentForwarding,
280
	sDeprecated, sUnsupported
285
	sDeprecated, sUnsupported
Lines 374-379 static struct { Link Here
374
	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
379
	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
375
	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
380
	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
376
	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
381
	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
382
	{ "requiredauthentications1", sRequiredAuthentications1 },
383
	{ "requiredauthentications2", sRequiredAuthentications2 },
377
	{ "match", sMatch, SSHCFG_ALL },
384
	{ "match", sMatch, SSHCFG_ALL },
378
	{ "permitopen", sPermitOpen, SSHCFG_ALL },
385
	{ "permitopen", sPermitOpen, SSHCFG_ALL },
379
	{ "forcecommand", sForceCommand, SSHCFG_ALL },
386
	{ "forcecommand", sForceCommand, SSHCFG_ALL },
Lines 1125-1130 process_server_config_line(ServerOptions Link Here
1125
			    filename, linenum);
1132
			    filename, linenum);
1126
		else
1133
		else
1127
			options->max_startups = options->max_startups_begin;
1134
			options->max_startups = options->max_startups_begin;
1135
		break;
1136
1137
1138
	case sRequiredAuthentications1:
1139
		charptr = &options->required_auth1;
1140
		arg = strdelim(&cp);
1141
		if (auth1_check_required(arg) != 0)
1142
			fatal("%.200s line %d: Invalid required authentication "
1143
			    "list", filename, linenum);
1144
		if (!arg || *arg == '\0')
1145
			fatal("%.200s line %d: Missing argument.",
1146
			    filename, linenum);
1147
		if (*charptr == NULL)
1148
			*charptr = xstrdup(arg);
1149
		break;
1150
1151
	case sRequiredAuthentications2:
1152
		charptr = &options->required_auth2;
1153
		arg = strdelim(&cp);
1154
		if (auth2_check_required(arg) != 0)
1155
			fatal("%.200s line %d: Invalid required authentication "
1156
			    "list", filename, linenum);
1157
		if (!arg || *arg == '\0')
1158
			fatal("%.200s line %d: Missing argument.",
1159
			    filename, linenum);
1160
		if (*charptr == NULL)
1161
			*charptr = xstrdup(arg);
1128
		break;
1162
		break;
1129
1163
1130
	case sMaxAuthTries:
1164
	case sMaxAuthTries:
(-)servconf.h (+3 lines)
Lines 140-145 typedef struct { Link Here
140
	char   *authorized_keys_file;	/* File containing public keys */
140
	char   *authorized_keys_file;	/* File containing public keys */
141
	char   *authorized_keys_file2;
141
	char   *authorized_keys_file2;
142
142
143
	char   *required_auth1; /* Required, but not sufficient */
144
	char   *required_auth2;
145
143
	char   *adm_forced_command;
146
	char   *adm_forced_command;
144
147
145
	int	permit_tun;
148
	int	permit_tun;
(-)sshconnect.c (-2 / +2 lines)
Lines 524-533 ssh_exchange_identification(int timeout_ Link Here
524
		    (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
524
		    (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
525
		    remote_major);
525
		    remote_major);
526
	/* Send our own protocol version identification. */
526
	/* Send our own protocol version identification. */
527
	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
527
	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
528
	    compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
528
	    compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
529
	    compat20 ? PROTOCOL_MINOR_2 : minor1,
529
	    compat20 ? PROTOCOL_MINOR_2 : minor1,
530
	    SSH_VERSION);
530
	    SSH_VERSION, compat20 ? "\r\n" : "\n");
531
	if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf))
531
	if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf))
532
		fatal("write: %.100s", strerror(errno));
532
		fatal("write: %.100s", strerror(errno));
533
	client_version_string = xstrdup(buf);
533
	client_version_string = xstrdup(buf);
(-)sshd.c (-2 / +4 lines)
Lines 379-385 sshd_exchange_identification(int sock_in Link Here
379
	int mismatch;
379
	int mismatch;
380
	int remote_major, remote_minor;
380
	int remote_major, remote_minor;
381
	int major, minor;
381
	int major, minor;
382
	char *s;
382
	char *s, *newline = "\n";
383
	char buf[256];			/* Must not be larger than remote_version. */
383
	char buf[256];			/* Must not be larger than remote_version. */
384
	char remote_version[256];	/* Must be at least as big as buf. */
384
	char remote_version[256];	/* Must be at least as big as buf. */
385
385
Lines 390-400 sshd_exchange_identification(int sock_in Link Here
390
	} else if (options.protocol & SSH_PROTO_2) {
390
	} else if (options.protocol & SSH_PROTO_2) {
391
		major = PROTOCOL_MAJOR_2;
391
		major = PROTOCOL_MAJOR_2;
392
		minor = PROTOCOL_MINOR_2;
392
		minor = PROTOCOL_MINOR_2;
393
		newline = "\r\n";
393
	} else {
394
	} else {
394
		major = PROTOCOL_MAJOR_1;
395
		major = PROTOCOL_MAJOR_1;
395
		minor = PROTOCOL_MINOR_1;
396
		minor = PROTOCOL_MINOR_1;
396
	}
397
	}
397
	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION);
398
	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
399
	    SSH_VERSION, newline);
398
	server_version_string = xstrdup(buf);
400
	server_version_string = xstrdup(buf);
399
401
400
	/* Send our protocol version identification. */
402
	/* Send our protocol version identification. */

Return to bug 983