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

Collapse All | Expand All

(-)auth.c (-3 / +59 lines)
Lines 245-251 allowed_user(struct passwd * pw) Link Here
245
}
245
}
246
246
247
void
247
void
248
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
248
auth_log(Authctxt *authctxt, int authenticated, const char *method,
249
    const char *submethod, const char *info)
249
{
250
{
250
	void (*authlog) (const char *fmt,...) = verbose;
251
	void (*authlog) (const char *fmt,...) = verbose;
251
	char *authmsg;
252
	char *authmsg;
Lines 265-273 auth_log(Authctxt *authctxt, int authent Link Here
265
	else
266
	else
266
		authmsg = authenticated ? "Accepted" : "Failed";
267
		authmsg = authenticated ? "Accepted" : "Failed";
267
268
268
	authlog("%s %s for %s%.100s from %.200s port %d%s",
269
	authlog("%s %s%s%s for %s%.100s from %.200s port %d%s",
269
	    authmsg,
270
	    authmsg,
270
	    method,
271
	    method,
272
	    submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod,
271
	    authctxt->valid ? "" : "invalid user ",
273
	    authctxt->valid ? "" : "invalid user ",
272
	    authctxt->user,
274
	    authctxt->user,
273
	    get_remote_ipaddr(),
275
	    get_remote_ipaddr(),
Lines 297-303 auth_log(Authctxt *authctxt, int authent Link Here
297
 * Check whether root logins are disallowed.
299
 * Check whether root logins are disallowed.
298
 */
300
 */
299
int
301
int
300
auth_root_allowed(char *method)
302
auth_root_allowed(const char *method)
301
{
303
{
302
	switch (options.permit_root_login) {
304
	switch (options.permit_root_login) {
303
	case PERMIT_YES:
305
	case PERMIT_YES:
Lines 619-622 fakepw(void) Link Here
619
	fake.pw_shell = "/nonexist";
621
	fake.pw_shell = "/nonexist";
620
622
621
	return (&fake);
623
	return (&fake);
624
}
625
626
int
627
auth_method_in_list(const char *list, const char *method)
628
{
629
	char *cp;
630
631
	cp = match_list(method, list, NULL);
632
	if (cp != NULL) {
633
		xfree(cp);
634
		return 1;
635
	}
636
637
	return 0;
638
}
639
640
#define	DELIM	","
641
int
642
auth_remove_from_list(char **list, const char *method)
643
{
644
	char *oldlist, *cp, *newlist = NULL;
645
	u_int len = 0, ret = 0;
646
647
	if (list == NULL || *list == NULL)
648
		return (0);
649
650
	oldlist = *list;
651
	len = strlen(oldlist) + 1;
652
	newlist = xmalloc(len);
653
	memset(newlist, '\0', len);
654
655
	/* Remove method from list, if present */
656
	for (;;) {
657
		if ((cp = strsep(&oldlist, DELIM)) == NULL)
658
			break;
659
		if (*cp == '\0')
660
			continue;
661
		if (strcmp(cp, method) != 0) {
662
			if (*newlist != '\0')
663
				strlcat(newlist, DELIM, len);
664
			strlcat(newlist, cp, len);
665
		} else
666
			ret++;
667
	}
668
669
	/* Return NULL instead of empty list */
670
	if (*newlist == '\0') {
671
		xfree(newlist);
672
		newlist = NULL;
673
	}
674
	xfree(*list);
675
	*list = newlist;
676
	
677
	return (ret);
622
}
678
}
(-)auth.h (-3 / +9 lines)
Lines 140-149 void disable_forwarding(void); Link Here
140
void	do_authentication(Authctxt *);
140
void	do_authentication(Authctxt *);
141
void	do_authentication2(Authctxt *);
141
void	do_authentication2(Authctxt *);
142
142
143
void	auth_log(Authctxt *, int, char *, char *);
143
void	auth_log(Authctxt *, int, const char *, const char *, const char *);
144
void	userauth_finish(Authctxt *, int, char *);
144
void	userauth_finish(Authctxt *, int, const char *, const char *);
145
int	auth_root_allowed(const char *);
146
145
void	userauth_send_banner(const char *);
147
void	userauth_send_banner(const char *);
146
int	auth_root_allowed(char *);
147
148
148
char	*auth2_read_banner(void);
149
char	*auth2_read_banner(void);
149
150
Lines 184-189 void auth_debug_send(void); Link Here
184
void	 auth_debug_reset(void);
185
void	 auth_debug_reset(void);
185
186
186
struct passwd *fakepw(void);
187
struct passwd *fakepw(void);
188
int	 auth_method_in_list(const char *, const char *);
189
int	 auth_remove_from_list(char **, const char *);
190
191
int	 auth1_check_required(const char *);
192
int	 auth2_check_required(const char *);
187
193
188
int	 sys_auth_passwd(Authctxt *, const char *);
194
int	 sys_auth_passwd(Authctxt *, const char *);
189
195
(-)auth1.c (-5 / +89 lines)
Lines 98-103 static const struct AuthMethod1 Link Here
98
	return (NULL);
98
	return (NULL);
99
}
99
}
100
100
101
static const struct AuthMethod1 *
102
lookup_authmethod1_by_name(const char *name)
103
{
104
	int i;
105
106
	for (i = 0; auth1_methods[i].name != NULL; i++)
107
		if (strcmp(auth1_methods[i].name, name) == 0)
108
			return (&(auth1_methods[i]));
109
110
	return NULL;
111
}
112
113
#define	DELIM	","
114
int
115
auth1_check_required(const char *list)
116
{
117
	char *orig_methods, *methods, *cp;
118
	static const struct AuthMethod1 *m;
119
	int ret = 0;
120
121
	orig_methods = methods = xstrdup(list);
122
	for(;;) { /* XXX maybe: while ((cp = ...) != NULL) ? */
123
		if ((cp = strsep(&methods, DELIM)) == NULL)
124
			break;
125
		debug2("auth1_check_required: method \"%s\"", cp);
126
		if (*cp == '\0') {
127
			debug("auth1_check_required: empty method");
128
			ret = -1;
129
		}
130
		if ((m = lookup_authmethod1_by_name(cp)) == NULL) {
131
			debug("auth1_check_required: unknown method "
132
			    "\"%s\"", cp);
133
			ret = -1;
134
		}
135
		if (*(m->enabled) == 0) {
136
			debug("auth1_check_required: method %s explicitly "
137
			    "disabled", cp);
138
			ret = -1;
139
		}
140
		/* Activate method if it isn't already */
141
		if (*(m->enabled) == -1)
142
			*(m->enabled) = 1;
143
        }
144
	xfree(orig_methods);
145
	return (ret);
146
}
147
148
101
static char *
149
static char *
102
get_authname(int type)
150
get_authname(int type)
103
{
151
{
Lines 237-242 do_authloop(Authctxt *authctxt) Link Here
237
{
285
{
238
	int authenticated = 0;
286
	int authenticated = 0;
239
	char info[1024];
287
	char info[1024];
288
	const char *meth_name;
240
	int prev = 0, type = 0;
289
	int prev = 0, type = 0;
241
	const struct AuthMethod1 *meth;
290
	const struct AuthMethod1 *meth;
242
291
Lines 244-250 do_authloop(Authctxt *authctxt) Link Here
244
	    authctxt->valid ? "" : "invalid user ", authctxt->user);
293
	    authctxt->valid ? "" : "invalid user ", authctxt->user);
245
294
246
	/* If the user has no password, accept authentication immediately. */
295
	/* If the user has no password, accept authentication immediately. */
247
	if (options.password_authentication &&
296
	if (options.required_auth1 == NULL && options.password_authentication &&
248
#ifdef KRB5
297
#ifdef KRB5
249
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
298
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
250
#endif
299
#endif
Lines 253-259 do_authloop(Authctxt *authctxt) Link Here
253
		if (options.use_pam && (PRIVSEP(do_pam_account())))
302
		if (options.use_pam && (PRIVSEP(do_pam_account())))
254
#endif
303
#endif
255
		{
304
		{
256
			auth_log(authctxt, 1, "without authentication", "");
305
			auth_log(authctxt, 1, "without authentication", NULL, "");
257
			return;
306
			return;
258
		}
307
		}
259
	}
308
	}
Lines 272-277 do_authloop(Authctxt *authctxt) Link Here
272
		/* Get a packet from the client. */
321
		/* Get a packet from the client. */
273
		prev = type;
322
		prev = type;
274
		type = packet_read();
323
		type = packet_read();
324
		meth_name = get_authname(type);
275
325
276
		/*
326
		/*
277
		 * If we started challenge-response authentication but the
327
		 * If we started challenge-response authentication but the
Lines 287-294 do_authloop(Authctxt *authctxt) Link Here
287
		if (authctxt->failures >= options.max_authtries)
337
		if (authctxt->failures >= options.max_authtries)
288
			goto skip;
338
			goto skip;
289
		if ((meth = lookup_authmethod1(type)) == NULL) {
339
		if ((meth = lookup_authmethod1(type)) == NULL) {
290
			logit("Unknown message during authentication: "
340
			logit("Unknown message during authentication: type %d",
291
			    "type %d", type);
341
			    type);
292
			goto skip;
342
			goto skip;
293
		}
343
		}
294
344
Lines 297-302 do_authloop(Authctxt *authctxt) Link Here
297
			goto skip;
347
			goto skip;
298
		}
348
		}
299
349
350
		/*
351
		 * Skip methods not in required list, until all the required
352
		 * ones are done
353
		 */
354
		if (options.required_auth1 != NULL &&
355
		    !auth_method_in_list(options.required_auth1, meth_name)) {
356
			debug("Skipping method \"%s\" until required "
357
			    "authentication completed", meth_name);
358
			goto skip;
359
		}
360
300
		authenticated = meth->method(authctxt, info, sizeof(info));
361
		authenticated = meth->method(authctxt, info, sizeof(info));
301
		if (authenticated == -1)
362
		if (authenticated == -1)
302
			continue; /* "postponed" */
363
			continue; /* "postponed" */
Lines 360-366 do_authloop(Authctxt *authctxt) Link Here
360
421
361
 skip:
422
 skip:
362
		/* Log before sending the reply */
423
		/* Log before sending the reply */
363
		auth_log(authctxt, authenticated, get_authname(type), info);
424
		auth_log(authctxt, authenticated, meth_name, NULL, info);
425
426
		/* Loop until the required authmethods are done */
427
		if (authenticated && options.required_auth1 != NULL) {
428
			if (auth_remove_from_list(&options.required_auth1,
429
			    meth_name) != 1)
430
				fatal("INTERNAL ERROR: authenticated method "
431
				    "\"%s\" not in required list \"%s\"",
432
				    meth_name, options.required_auth1);
433
			debug2("do_authloop: required list now: %s",
434
			    options.required_auth1 == NULL ?
435
			    "DONE" : options.required_auth1);
436
			if (options.required_auth1 == NULL)
437
				return;
438
			authenticated = 0;
439
			/*
440
			 * Disable method so client can't authenticate with it
441
			 * after the required authentications are complete.
442
			 */
443
			*(meth->enabled) = 0;
444
			packet_send_debug("Further authentication required");
445
			goto send_fail;
446
		}
364
447
365
		if (client_user != NULL) {
448
		if (client_user != NULL) {
366
			xfree(client_user);
449
			xfree(client_user);
Lines 376-381 do_authloop(Authctxt *authctxt) Link Here
376
#endif
459
#endif
377
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
460
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
378
		}
461
		}
462
 send_fail:
379
463
380
		packet_start(SSH_SMSG_FAILURE);
464
		packet_start(SSH_SMSG_FAILURE);
381
		packet_send();
465
		packet_send();
(-)auth2.c (-11 / +86 lines)
Lines 209-215 input_userauth_request(int type, u_int32 Link Here
209
{
209
{
210
	Authctxt *authctxt = ctxt;
210
	Authctxt *authctxt = ctxt;
211
	Authmethod *m = NULL;
211
	Authmethod *m = NULL;
212
	char *user, *service, *method, *style = NULL;
212
	char *user, *service, *method, *active_methods, *style = NULL;
213
	int authenticated = 0;
213
	int authenticated = 0;
214
214
215
	if (authctxt == NULL)
215
	if (authctxt == NULL)
Lines 266-287 input_userauth_request(int type, u_int32 Link Here
266
	authctxt->postponed = 0;
266
	authctxt->postponed = 0;
267
267
268
	/* try to authenticate user */
268
	/* try to authenticate user */
269
	m = authmethod_lookup(method);
269
	active_methods = authmethods_get();
270
	if (m != NULL && authctxt->failures < options.max_authtries) {
270
	if (strcmp(method, "none") == 0 || 
271
		debug2("input_userauth_request: try method %s", method);
271
	    auth_method_in_list(active_methods, method)) {
272
		authenticated =	m->userauth(authctxt);
272
		m = authmethod_lookup(method);
273
	}
273
		if (m != NULL) {
274
	userauth_finish(authctxt, authenticated, method);
274
			debug2("input_userauth_request: try method %s", method);
275
			authenticated =	m->userauth(authctxt);
276
		}
275
277
278
	}
279
	xfree(active_methods);
280
	userauth_finish(authctxt, authenticated, method, NULL);
281
 
276
	xfree(service);
282
	xfree(service);
277
	xfree(user);
283
	xfree(user);
278
	xfree(method);
284
	xfree(method);
279
}
285
}
280
286
281
void
287
void
282
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
288
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
289
    const char *submethod)
283
{
290
{
284
	char *methods;
291
	char *methods;
292
	Authmethod *m = NULL;
293
	u_int partial = 0;
285
294
286
	if (!authctxt->valid && authenticated)
295
	if (!authctxt->valid && authenticated)
287
		fatal("INTERNAL ERROR: authenticated invalid user %s",
296
		fatal("INTERNAL ERROR: authenticated invalid user %s",
Lines 319-330 userauth_finish(Authctxt *authctxt, int Link Here
319
#endif /* _UNICOS */
328
#endif /* _UNICOS */
320
329
321
	/* Log before sending the reply */
330
	/* Log before sending the reply */
322
	auth_log(authctxt, authenticated, method, " ssh2");
331
	auth_log(authctxt, authenticated, method, submethod, " ssh2");
323
332
324
	if (authctxt->postponed)
333
	if (authctxt->postponed)
325
		return;
334
		return;
326
335
327
	/* XXX todo: check if multiple auth methods are needed */
336
	/* Handle RequiredAuthentications2: loop until required methods done */
337
	if (authenticated && options.required_auth2 != NULL) {
338
		if ((m = authmethod_lookup(method)) == NULL)
339
			fatal("INTERNAL ERROR: authenticated method "
340
			    "\"%s\" unknown", method);
341
		if (auth_remove_from_list(&options.required_auth2, method) != 1)
342
			fatal("INTERNAL ERROR: authenticated method "
343
			    "\"%s\" not in required list \"%s\"", 
344
			    method, options.required_auth2);
345
		debug2("userauth_finish: required list now: %s",
346
		    options.required_auth2 == NULL ?
347
		    "DONE" : options.required_auth2);
348
		/*
349
		 * Disable method so client can't authenticate with it after
350
		 * the required authentications are complete.
351
		 */
352
		if (m->enabled != NULL)
353
			*(m->enabled) = 0;
354
		authenticated = 0;
355
		partial = 1;
356
		goto send_fail;
357
	}
358
328
	if (authenticated == 1) {
359
	if (authenticated == 1) {
329
		/* turn off userauth */
360
		/* turn off userauth */
330
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
361
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
Lines 344-353 userauth_finish(Authctxt *authctxt, int Link Here
344
#endif
375
#endif
345
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
376
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
346
		}
377
		}
378
 send_fail:
347
		methods = authmethods_get();
379
		methods = authmethods_get();
348
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
380
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
349
		packet_put_cstring(methods);
381
		packet_put_cstring(methods);
350
		packet_put_char(0);	/* XXX partial success, unused */
382
		packet_put_char(partial);
351
		packet_send();
383
		packet_send();
352
		packet_write_wait();
384
		packet_write_wait();
353
		xfree(methods);
385
		xfree(methods);
Lines 361-366 authmethods_get(void) Link Here
361
	char *list;
393
	char *list;
362
	int i;
394
	int i;
363
395
396
	if (options.required_auth2 != NULL)
397
		return xstrdup(options.required_auth2);
398
364
	buffer_init(&b);
399
	buffer_init(&b);
365
	for (i = 0; authmethods[i] != NULL; i++) {
400
	for (i = 0; authmethods[i] != NULL; i++) {
366
		if (strcmp(authmethods[i]->name, "none") == 0)
401
		if (strcmp(authmethods[i]->name, "none") == 0)
Lines 393-397 authmethod_lookup(const char *name) Link Here
393
	debug2("Unrecognized authentication method name: %s",
428
	debug2("Unrecognized authentication method name: %s",
394
	    name ? name : "NULL");
429
	    name ? name : "NULL");
395
	return NULL;
430
	return NULL;
431
}
432
433
#define DELIM ","
434
435
int
436
auth2_check_required(const char *list)
437
{
438
	char *orig_methods, *methods, *cp;
439
	struct Authmethod *m;
440
	int i, ret = 0;
441
442
	orig_methods = methods = xstrdup(list);
443
	for(;;) {
444
		if ((cp = strsep(&methods, DELIM)) == NULL)
445
			break;
446
		debug2("auth2_check_required: method \"%s\"", cp);
447
		if (*cp == '\0') {
448
			debug("auth2_check_required: empty method");
449
			ret = -1;
450
		}
451
		for (i = 0; authmethods[i] != NULL; i++)
452
			if (strcmp(cp, authmethods[i]->name) == 0)
453
				break;
454
		if ((m = authmethods[i]) == NULL) {
455
			debug("auth2_check_required: unknown method "
456
			    "\"%s\"", cp);
457
			ret = -1;
458
			break;
459
		}
460
		if (m->enabled == NULL || *(m->enabled) == 0) {
461
			debug("auth2_check_required: method %s explicitly "
462
			    "disabled", cp);
463
			ret = -1;
464
		}
465
		/* Activate method if it isn't already */
466
		if (*(m->enabled) == -1)
467
			*(m->enabled) = 1;
468
	}
469
	xfree(orig_methods);
470
	return (ret);
396
}
471
}
397
472
(-)auth2-none.c (-1 / +1 lines)
Lines 65-71 userauth_none(Authctxt *authctxt) Link Here
65
	if (check_nt_auth(1, authctxt->pw) == 0)
65
	if (check_nt_auth(1, authctxt->pw) == 0)
66
		return (0);
66
		return (0);
67
#endif
67
#endif
68
	if (options.password_authentication)
68
	if (options.password_authentication && options.required_auth2 == NULL)
69
		return (PRIVSEP(auth_password(authctxt, "")));
69
		return (PRIVSEP(auth_password(authctxt, "")));
70
	return (0);
70
	return (0);
71
}
71
}
(-)auth2-chall.c (-10 / +4 lines)
Lines 281-289 input_userauth_info_response(int type, u Link Here
281
{
281
{
282
	Authctxt *authctxt = ctxt;
282
	Authctxt *authctxt = ctxt;
283
	KbdintAuthctxt *kbdintctxt;
283
	KbdintAuthctxt *kbdintctxt;
284
	int authenticated = 0, res, len;
284
	int authenticated = 0, res;
285
	u_int i, nresp;
285
	u_int i, nresp;
286
	char **response = NULL, *method;
286
	char **response = NULL;
287
287
288
	if (authctxt == NULL)
288
	if (authctxt == NULL)
289
		fatal("input_userauth_info_response: no authctxt");
289
		fatal("input_userauth_info_response: no authctxt");
Lines 330-341 input_userauth_info_response(int type, u Link Here
330
		break;
330
		break;
331
	}
331
	}
332
332
333
	len = strlen("keyboard-interactive") + 2 +
334
		strlen(kbdintctxt->device->name);
335
	method = xmalloc(len);
336
	snprintf(method, len, "keyboard-interactive/%s",
337
	    kbdintctxt->device->name);
338
339
	if (!authctxt->postponed) {
333
	if (!authctxt->postponed) {
340
		if (authenticated) {
334
		if (authenticated) {
341
			auth2_challenge_stop(authctxt);
335
			auth2_challenge_stop(authctxt);
Lines 345-352 input_userauth_info_response(int type, u Link Here
345
			auth2_challenge_start(authctxt);
339
			auth2_challenge_start(authctxt);
346
		}
340
		}
347
	}
341
	}
348
	userauth_finish(authctxt, authenticated, method);
342
	userauth_finish(authctxt, authenticated, "keyboard-interactive",
349
	xfree(method);
343
	    kbdintctxt->device->name);
350
}
344
}
351
345
352
void
346
void
(-)auth2-gss.c (-3 / +3 lines)
Lines 161-167 input_gssapi_token(int type, u_int32_t p Link Here
161
		}
161
		}
162
		authctxt->postponed = 0;
162
		authctxt->postponed = 0;
163
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
163
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
164
		userauth_finish(authctxt, 0, "gssapi-with-mic");
164
		userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
165
	} else {
165
	} else {
166
		if (send_tok.length != 0) {
166
		if (send_tok.length != 0) {
167
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
167
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
Lines 249-255 input_gssapi_exchange_complete(int type, Link Here
249
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
249
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
250
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
250
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
251
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
251
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
252
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
252
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
253
}
253
}
254
254
255
static void
255
static void
Lines 289-295 input_gssapi_mic(int type, u_int32_t ple Link Here
289
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
289
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
290
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
290
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
291
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
291
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
292
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
292
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
293
}
293
}
294
294
295
Authmethod method_gssapi = {
295
Authmethod method_gssapi = {
(-)monitor.c (-4 / +21 lines)
Lines 327-333 void Link Here
327
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
327
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
328
{
328
{
329
	struct mon_table *ent;
329
	struct mon_table *ent;
330
	int authenticated = 0;
330
	int no_increment, authenticated = 0;
331
	char **req_auth;
331
332
332
	debug3("preauth child monitor started");
333
	debug3("preauth child monitor started");
333
334
Lines 338-349 monitor_child_preauth(Authctxt *_authctx Link Here
338
339
339
	if (compat20) {
340
	if (compat20) {
340
		mon_dispatch = mon_dispatch_proto20;
341
		mon_dispatch = mon_dispatch_proto20;
342
		req_auth = &options.required_auth2;
341
343
342
		/* Permit requests for moduli and signatures */
344
		/* Permit requests for moduli and signatures */
343
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
345
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
344
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
346
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
345
	} else {
347
	} else {
346
		mon_dispatch = mon_dispatch_proto15;
348
		mon_dispatch = mon_dispatch_proto15;
349
		req_auth = &options.required_auth1;
347
350
348
		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
351
		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
349
	}
352
	}
Lines 351-356 monitor_child_preauth(Authctxt *_authctx Link Here
351
	/* The first few requests do not require asynchronous access */
354
	/* The first few requests do not require asynchronous access */
352
	while (!authenticated) {
355
	while (!authenticated) {
353
		auth_method = "unknown";
356
		auth_method = "unknown";
357
		no_increment = 1;
354
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
358
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
355
		if (authenticated) {
359
		if (authenticated) {
356
			if (!(ent->flags & MON_AUTHDECIDE))
360
			if (!(ent->flags & MON_AUTHDECIDE))
Lines 372-382 monitor_child_preauth(Authctxt *_authctx Link Here
372
			}
376
			}
373
#endif
377
#endif
374
		}
378
		}
379
		/* Loop until the required authmethods are done */
380
		if (authenticated && *req_auth != NULL) {
381
			if (auth_remove_from_list(req_auth, auth_method) != 1)
382
				fatal("INTERNAL ERROR: authenticated method "
383
				    "\"%s\" not in required list \"%s\"",
384
				    auth_method, *req_auth);
385
			debug2("monitor_child_preauth: required list now: %s",
386
			    *req_auth == NULL ? "DONE" : *req_auth);
387
			if (*req_auth != NULL)
388
				authenticated = 0;
389
			no_increment = 1;
390
		}
375
391
376
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
392
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
377
			auth_log(authctxt, authenticated, auth_method,
393
			auth_log(authctxt, authenticated, auth_method, NULL,
378
			    compat20 ? " ssh2" : "");
394
			    compat20 ? " ssh2" : "");
379
			if (!authenticated)
395
			if (!authenticated && !no_increment)
380
				authctxt->failures++;
396
				authctxt->failures++;
381
		}
397
		}
382
	}
398
	}
Lines 1053-1059 mm_answer_keyallowed(int sock, Buffer *m Link Here
1053
		hostbased_chost = chost;
1069
		hostbased_chost = chost;
1054
	} else {
1070
	} else {
1055
		/* Log failed attempt */
1071
		/* Log failed attempt */
1056
		auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
1072
		auth_log(authctxt, 0, auth_method, NULL,
1073
		    compat20 ? " ssh2" : "");
1057
		xfree(blob);
1074
		xfree(blob);
1058
		xfree(cuser);
1075
		xfree(cuser);
1059
		xfree(chost);
1076
		xfree(chost);
(-)servconf.c (+34 lines)
Lines 38-43 Link Here
38
#include "key.h"
38
#include "key.h"
39
#include "kex.h"
39
#include "kex.h"
40
#include "mac.h"
40
#include "mac.h"
41
#include "hostfile.h"
42
#include "auth.h"
41
#include "match.h"
43
#include "match.h"
42
#include "channels.h"
44
#include "channels.h"
43
#include "groupaccess.h"
45
#include "groupaccess.h"
Lines 124-129 initialize_server_options(ServerOptions Link Here
124
	options->authorized_keys_file2 = NULL;
126
	options->authorized_keys_file2 = NULL;
125
	options->num_accept_env = 0;
127
	options->num_accept_env = 0;
126
	options->permit_tun = -1;
128
	options->permit_tun = -1;
129
	options->required_auth1 = NULL;
130
	options->required_auth2 = NULL;
127
	options->num_permitted_opens = -1;
131
	options->num_permitted_opens = -1;
128
	options->adm_forced_command = NULL;
132
	options->adm_forced_command = NULL;
129
	options->chroot_directory = NULL;
133
	options->chroot_directory = NULL;
Lines 300-305 typedef enum { Link Here
300
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
304
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
301
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
305
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
302
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
306
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
307
	sRequiredAuthentications1, sRequiredAuthentications2,
303
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
308
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
304
	sUsePrivilegeSeparation, sAllowAgentForwarding,
309
	sUsePrivilegeSeparation, sAllowAgentForwarding,
305
	sDeprecated, sUnsupported
310
	sDeprecated, sUnsupported
Lines 411-416 static struct { Link Here
411
	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
416
	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
412
	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
417
	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
413
	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
418
	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
419
	{ "requiredauthentications1", sRequiredAuthentications1 },
420
	{ "requiredauthentications2", sRequiredAuthentications2 },
414
 	{ "match", sMatch, SSHCFG_ALL },
421
 	{ "match", sMatch, SSHCFG_ALL },
415
	{ "permitopen", sPermitOpen, SSHCFG_ALL },
422
	{ "permitopen", sPermitOpen, SSHCFG_ALL },
416
	{ "forcecommand", sForceCommand, SSHCFG_ALL },
423
	{ "forcecommand", sForceCommand, SSHCFG_ALL },
Lines 1151-1156 process_server_config_line(ServerOptions Link Here
1151
			    filename, linenum);
1158
			    filename, linenum);
1152
		else
1159
		else
1153
			options->max_startups = options->max_startups_begin;
1160
			options->max_startups = options->max_startups_begin;
1161
		break;
1162
1163
1164
	case sRequiredAuthentications1:
1165
		charptr = &options->required_auth1;
1166
		arg = strdelim(&cp);
1167
		if (auth1_check_required(arg) != 0)
1168
			fatal("%.200s line %d: Invalid required authentication "
1169
			    "list", filename, linenum);
1170
		if (!arg || *arg == '\0')
1171
			fatal("%.200s line %d: Missing argument.",
1172
			    filename, linenum);
1173
		if (*charptr == NULL)
1174
			*charptr = xstrdup(arg);
1175
		break;
1176
1177
	case sRequiredAuthentications2:
1178
		charptr = &options->required_auth2;
1179
		arg = strdelim(&cp);
1180
		if (auth2_check_required(arg) != 0)
1181
			fatal("%.200s line %d: Invalid required authentication "
1182
			    "list", filename, linenum);
1183
		if (!arg || *arg == '\0')
1184
			fatal("%.200s line %d: Missing argument.",
1185
			    filename, linenum);
1186
		if (*charptr == NULL)
1187
			*charptr = xstrdup(arg);
1154
		break;
1188
		break;
1155
1189
1156
	case sMaxAuthTries:
1190
	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	use_pam;		/* Enable auth via PAM */
148
	int	use_pam;		/* Enable auth via PAM */
(-)sshd_config.5 (+14 lines)
Lines 607-612 Available keywords are Link Here
607
.Cm PasswordAuthentication ,
607
.Cm PasswordAuthentication ,
608
.Cm PermitOpen ,
608
.Cm PermitOpen ,
609
.Cm PermitRootLogin ,
609
.Cm PermitRootLogin ,
610
.Cm RequiredMethods1,
611
.Cm RequiredMethods2,
610
.Cm RhostsRSAAuthentication ,
612
.Cm RhostsRSAAuthentication ,
611
.Cm RSAAuthentication ,
613
.Cm RSAAuthentication ,
612
.Cm X11DisplayOffset ,
614
.Cm X11DisplayOffset ,
Lines 798-803 Specifies whether public key authenticat Link Here
798
The default is
800
The default is
799
.Dq yes .
801
.Dq yes .
800
Note that this option applies to protocol version 2 only.
802
Note that this option applies to protocol version 2 only.
803
.It Cm RequiredMethods[12]
804
 Requires two authentication methods to succeed before authorizing the connection.
805
806
 RequiredAuthentications1 method[,method...]
807
 RequiredAuthentications2 method[,method...]
808
809
.Pp
810
Example:
811
812
 RequiredAuthentications1 password
813
 RequiredAuthentications2 publickey
814
801
.It Cm RhostsRSAAuthentication
815
.It Cm RhostsRSAAuthentication
802
Specifies whether rhosts or /etc/hosts.equiv authentication together
816
Specifies whether rhosts or /etc/hosts.equiv authentication together
803
with successful RSA host authentication is allowed.
817
with successful RSA host authentication is allowed.

Return to bug 983