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

Collapse All | Expand All

(-)auth.c (-3 / +59 lines)
Lines 156-162 allowed_user(struct passwd * pw) Link Here
156
}
156
}
157
157
158
void
158
void
159
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
159
auth_log(Authctxt *authctxt, int authenticated, const char *method,
160
    const char *submethod, const char *info)
160
{
161
{
161
	void (*authlog) (const char *fmt,...) = verbose;
162
	void (*authlog) (const char *fmt,...) = verbose;
162
	char *authmsg;
163
	char *authmsg;
Lines 173-181 auth_log(Authctxt *authctxt, int authent Link Here
173
	else
174
	else
174
		authmsg = authenticated ? "Accepted" : "Failed";
175
		authmsg = authenticated ? "Accepted" : "Failed";
175
176
176
	authlog("%s %s for %s%.100s from %.200s port %d%s",
177
	authlog("%s %s%s%s for %s%.100s from %.200s port %d%s",
177
	    authmsg,
178
	    authmsg,
178
	    method,
179
	    method,
180
	    submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod,
179
	    authctxt->valid ? "" : "invalid user ",
181
	    authctxt->valid ? "" : "invalid user ",
180
	    authctxt->user,
182
	    authctxt->user,
181
	    get_remote_ipaddr(),
183
	    get_remote_ipaddr(),
Lines 187-193 auth_log(Authctxt *authctxt, int authent Link Here
187
 * Check whether root logins are disallowed.
189
 * Check whether root logins are disallowed.
188
 */
190
 */
189
int
191
int
190
auth_root_allowed(char *method)
192
auth_root_allowed(const char *method)
191
{
193
{
192
	switch (options.permit_root_login) {
194
	switch (options.permit_root_login) {
193
	case PERMIT_YES:
195
	case PERMIT_YES:
Lines 483-486 fakepw(void) Link Here
483
	fake.pw_shell = "/nonexist";
485
	fake.pw_shell = "/nonexist";
484
486
485
	return (&fake);
487
	return (&fake);
488
}
489
490
int
491
auth_method_in_list(const char *list, const char *method)
492
{
493
	char *cp;
494
495
	cp = match_list(method, list, NULL);
496
	if (cp != NULL) {
497
		xfree(cp);
498
		return 1;
499
	}
500
501
	return 0;
502
}
503
504
#define	DELIM	","
505
int
506
auth_remove_from_list(char **list, const char *method)
507
{
508
	char *oldlist, *cp, *newlist = NULL;
509
	u_int len = 0, ret = 0;
510
511
	if (list == NULL || *list == NULL)
512
		return (0);
513
514
	oldlist = *list;
515
	len = strlen(oldlist) + 1;
516
	newlist = xmalloc(len);
517
	memset(newlist, '\0', len);
518
519
	/* Remove method from list, if present */
520
	for (;;) {
521
		if ((cp = strsep(&oldlist, DELIM)) == NULL)
522
			break;
523
		if (*cp == '\0')
524
			continue;
525
		if (strcmp(cp, method) != 0) {
526
			if (*newlist != '\0')
527
				strlcat(newlist, DELIM, len);
528
			strlcat(newlist, cp, len);
529
		} else
530
			ret++;
531
	}
532
533
	/* Return NULL instead of empty list */
534
	if (*newlist == '\0') {
535
		xfree(newlist);
536
		newlist = NULL;
537
	}
538
	xfree(*list);
539
	*list = newlist;
540
	
541
	return (ret);
486
}
542
}
(-)auth.h (-3 / +8 lines)
Lines 125-133 void krb5_cleanup_proc(Authctxt *authctx Link Here
125
void	do_authentication(Authctxt *);
125
void	do_authentication(Authctxt *);
126
void	do_authentication2(Authctxt *);
126
void	do_authentication2(Authctxt *);
127
127
128
void	auth_log(Authctxt *, int, char *, char *);
128
void	auth_log(Authctxt *, int, const char *, const char *, const char *);
129
void	userauth_finish(Authctxt *, int, char *);
129
void	userauth_finish(Authctxt *, int, const char *, const char *);
130
int	auth_root_allowed(char *);
130
int	auth_root_allowed(const char *);
131
131
132
char	*auth2_read_banner(void);
132
char	*auth2_read_banner(void);
133
133
Lines 169-174 void auth_debug_send(void); Link Here
169
void	 auth_debug_reset(void);
169
void	 auth_debug_reset(void);
170
170
171
struct passwd *fakepw(void);
171
struct passwd *fakepw(void);
172
int	 auth_method_in_list(const char *, const char *);
173
int	 auth_remove_from_list(char **, const char *);
174
175
int	 auth1_check_required(const char *);
176
int	 auth2_check_required(const char *);
172
177
173
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
178
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
174
179
(-)auth1.c (-61 / +143 lines)
Lines 29-56 RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/ Link Here
29
/* import */
29
/* import */
30
extern ServerOptions options;
30
extern ServerOptions options;
31
31
32
/*
32
struct Authmethod1 {
33
 * convert ssh auth msg type into description
33
	int type;
34
 */
34
	char *name;
35
static char *
35
	int *enabled;
36
get_authname(int type)
36
};
37
38
static struct Authmethod1 auth1_methods[] = {
39
	{ SSH_CMSG_AUTH_PASSWORD, "password", &options.password_authentication },
40
	{ SSH_CMSG_AUTH_RSA, "rsa", &options.rsa_authentication },
41
	{ SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa", &options.rhosts_rsa_authentication },
42
	{ SSH_CMSG_AUTH_TIS, "challenge-response", &options.challenge_response_authentication },
43
	{ SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response", &options.challenge_response_authentication },
44
	{ -1, NULL }
45
};
46
47
static struct Authmethod1 *
48
get_authmethod1_by_type(int type)
49
{
50
	int i;
51
52
	for (i = 0; auth1_methods[i].name != NULL; i++)
53
		if (auth1_methods[i].type == type)
54
			return &auth1_methods[i];
55
56
	return NULL;
57
}
58
59
static struct Authmethod1 *
60
get_authmethod1_by_name(const char *name)
61
{
62
	int i;
63
64
	for (i = 0; auth1_methods[i].name != NULL; i++)
65
		if (strcmp(auth1_methods[i].name, name) == 0)
66
			return &auth1_methods[i];
67
68
	return NULL;
69
}
70
71
#define	DELIM	","
72
int
73
auth1_check_required(const char *list)
37
{
74
{
38
	static char buf[1024];
75
	char *orig_methods, *methods, *cp;
39
	switch (type) {
76
	struct Authmethod1 *m;
40
	case SSH_CMSG_AUTH_PASSWORD:
77
	int ret = 0;
41
		return "password";
78
42
	case SSH_CMSG_AUTH_RSA:
79
	orig_methods = methods = xstrdup(list);
43
		return "rsa";
80
	for(;;) {
44
	case SSH_CMSG_AUTH_RHOSTS_RSA:
81
		if ((cp = strsep(&methods, DELIM)) == NULL)
45
		return "rhosts-rsa";
82
			break;
46
	case SSH_CMSG_AUTH_RHOSTS:
83
		debug2("auth1_check_required: method \"%s\"", cp);
47
		return "rhosts";
84
		if (*cp == '\0') {
48
	case SSH_CMSG_AUTH_TIS:
85
			debug("auth1_check_required: empty method");
49
	case SSH_CMSG_AUTH_TIS_RESPONSE:
86
			ret = -1;
50
		return "challenge-response";
87
		}
88
		if ((m = get_authmethod1_by_name(cp)) == NULL) {
89
			debug("auth1_check_required: unknown method "
90
			    "\"%s\"", cp);
91
			ret = -1;
92
		}
93
		if (*(m->enabled) == 0) {
94
			debug("auth1_check_required: method %s explicitly "
95
			    "disabled", cp);
96
			ret = -1;
97
		}
98
		/* Activate method if it isn't already */
99
		if (*(m->enabled) == -1)
100
			*(m->enabled) = 1;
51
	}
101
	}
52
	snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
102
	xfree(orig_methods);
53
	return buf;
103
	return (ret);
54
}
104
}
55
105
56
/*
106
/*
Lines 64-85 do_authloop(Authctxt *authctxt) Link Here
64
	u_int bits;
114
	u_int bits;
65
	Key *client_host_key;
115
	Key *client_host_key;
66
	BIGNUM *n;
116
	BIGNUM *n;
67
	char *client_user, *password;
117
	char *client_user, *password, *challenge, *response, meth_name[64];
68
	char info[1024];
118
	char info[1024];
69
	u_int dlen;
119
	u_int dlen;
70
	u_int ulen;
120
	u_int ulen;
71
	int type = 0;
121
	int type = 0;
122
	struct Authmethod1 *meth;
72
123
73
	debug("Attempting authentication for %s%.100s.",
124
	debug("Attempting authentication for %s%.100s.",
74
	    authctxt->valid ? "" : "invalid user ", authctxt->user);
125
	    authctxt->valid ? "" : "invalid user ", authctxt->user);
75
126
76
	/* If the user has no password, accept authentication immediately. */
127
	/* If the user has no password, accept authentication immediately. */
77
	if (options.password_authentication &&
128
	if (options.required_auth1 == NULL && options.password_authentication &&
78
#ifdef KRB5
129
#ifdef KRB5
79
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
130
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
80
#endif
131
#endif
81
	    PRIVSEP(auth_password(authctxt, ""))) {
132
	    PRIVSEP(auth_password(authctxt, ""))) {
82
		auth_log(authctxt, 1, "without authentication", "");
133
		auth_log(authctxt, 1, "without authentication", NULL, "");
83
		return;
134
		return;
84
	}
135
	}
85
136
Lines 97-109 do_authloop(Authctxt *authctxt) Link Here
97
		/* Get a packet from the client. */
148
		/* Get a packet from the client. */
98
		type = packet_read();
149
		type = packet_read();
99
150
151
		/*
152
		 * Any unknown messages will be ignored (and failure
153
		 * returned) during authentication.
154
		 */
155
		if ((meth = get_authmethod1_by_type(type)) == NULL) {
156
			logit("Unknown message during authentication: type %d",
157
			    type);
158
		 	snprintf(meth_name, sizeof meth_name,
159
			    "bad-auth-msg-%d", type);
160
			goto skip_method;
161
		}
162
		strlcpy(meth_name, meth->name, sizeof meth_name);
163
	
164
		/* Skip disabled methods */
165
		if (!*(meth->enabled)) {
166
			verbose("%s authentication disabled", meth_name);
167
			goto skip_method;
168
		}
169
170
		/*
171
		 * Skip methods not in required list, until all the required
172
		 * ones are done
173
		 */
174
		if (options.required_auth1 != NULL &&
175
		    !auth_method_in_list(options.required_auth1, meth_name)) {
176
			debug("Skipping method \"%s\" until required "
177
			    "authentication completed", meth_name);
178
			goto skip_method;
179
		}
180
100
		/* Process the packet. */
181
		/* Process the packet. */
101
		switch (type) {
182
		switch (type) {
102
		case SSH_CMSG_AUTH_RHOSTS_RSA:
183
		case SSH_CMSG_AUTH_RHOSTS_RSA:
103
			if (!options.rhosts_rsa_authentication) {
104
				verbose("Rhosts with RSA authentication disabled.");
105
				break;
106
			}
107
			/*
184
			/*
108
			 * Get client user name.  Note that we just have to
185
			 * Get client user name.  Note that we just have to
109
			 * trust the client; root on the client machine can
186
			 * trust the client; root on the client machine can
Lines 132-141 do_authloop(Authctxt *authctxt) Link Here
132
			break;
209
			break;
133
210
134
		case SSH_CMSG_AUTH_RSA:
211
		case SSH_CMSG_AUTH_RSA:
135
			if (!options.rsa_authentication) {
136
				verbose("RSA authentication disabled.");
137
				break;
138
			}
139
			/* RSA authentication requested. */
212
			/* RSA authentication requested. */
140
			if ((n = BN_new()) == NULL)
213
			if ((n = BN_new()) == NULL)
141
				fatal("do_authloop: BN_new failed");
214
				fatal("do_authloop: BN_new failed");
Lines 146-155 do_authloop(Authctxt *authctxt) Link Here
146
			break;
219
			break;
147
220
148
		case SSH_CMSG_AUTH_PASSWORD:
221
		case SSH_CMSG_AUTH_PASSWORD:
149
			if (!options.password_authentication) {
150
				verbose("Password authentication disabled.");
151
				break;
152
			}
153
			/*
222
			/*
154
			 * Read user password.  It is in plain text, but was
223
			 * Read user password.  It is in plain text, but was
155
			 * transmitted over the encrypted channel so it is
224
			 * transmitted over the encrypted channel so it is
Lines 167-204 do_authloop(Authctxt *authctxt) Link Here
167
236
168
		case SSH_CMSG_AUTH_TIS:
237
		case SSH_CMSG_AUTH_TIS:
169
			debug("rcvd SSH_CMSG_AUTH_TIS");
238
			debug("rcvd SSH_CMSG_AUTH_TIS");
170
			if (options.challenge_response_authentication == 1) {
239
			challenge = get_challenge(authctxt);
171
				char *challenge = get_challenge(authctxt);
240
			if (challenge != NULL) {
172
				if (challenge != NULL) {
241
				debug("sending challenge '%s'", challenge);
173
					debug("sending challenge '%s'", challenge);
242
				packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
174
					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
243
				packet_put_cstring(challenge);
175
					packet_put_cstring(challenge);
244
				xfree(challenge);
176
					xfree(challenge);
245
				packet_send();
177
					packet_send();
246
				packet_write_wait();
178
					packet_write_wait();
247
				continue;
179
					continue;
180
				}
181
			}
248
			}
182
			break;
249
			break;
183
		case SSH_CMSG_AUTH_TIS_RESPONSE:
250
		case SSH_CMSG_AUTH_TIS_RESPONSE:
184
			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
251
			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
185
			if (options.challenge_response_authentication == 1) {
252
			response = packet_get_string(&dlen);
186
				char *response = packet_get_string(&dlen);
253
			packet_check_eom();
187
				packet_check_eom();
254
			authenticated = verify_response(authctxt, response);
188
				authenticated = verify_response(authctxt, response);
255
			memset(response, 'r', dlen);
189
				memset(response, 'r', dlen);
256
			xfree(response);
190
				xfree(response);
191
			}
192
			break;
257
			break;
193
258
194
		default:
259
		default:
195
			/*
260
			fatal("INTERNAL ERROR: unrecognised method %d", type);
196
			 * Any unknown messages will be ignored (and failure
197
			 * returned) during authentication.
198
			 */
199
			logit("Unknown message during authentication: type %d", type);
200
			break;
201
		}
261
		}
262
 skip_method:
202
#ifdef BSD_AUTH
263
#ifdef BSD_AUTH
203
		if (authctxt->as) {
264
		if (authctxt->as) {
204
			auth_close(authctxt->as);
265
			auth_close(authctxt->as);
Lines 211-221 do_authloop(Authctxt *authctxt) Link Here
211
272
212
		/* Special handling for root */
273
		/* Special handling for root */
213
		if (authenticated && authctxt->pw->pw_uid == 0 &&
274
		if (authenticated && authctxt->pw->pw_uid == 0 &&
214
		    !auth_root_allowed(get_authname(type)))
275
		    !auth_root_allowed(meth_name))
215
			authenticated = 0;
276
			authenticated = 0;
216
277
217
		/* Log before sending the reply */
278
		/* Log before sending the reply */
218
		auth_log(authctxt, authenticated, get_authname(type), info);
279
		auth_log(authctxt, authenticated, meth_name, NULL, info);
280
281
		/* Loop until the required authmethods are done */
282
		if (authenticated && options.required_auth1 != NULL) {
283
			if (auth_remove_from_list(&options.required_auth1, 
284
			    meth_name) != 1)
285
				fatal("INTERNAL ERROR: authenticated method "
286
				    "\"%s\" not in required list \"%s\"", 
287
				    meth_name, options.required_auth1);
288
			debug2("do_authloop: required list now: %s",
289
			    options.required_auth1 == NULL ?
290
			    "DONE" : options.required_auth1);
291
			authenticated = 0;
292
			/*
293
			 * Disable method so client can't authenticate with it 
294
			 * after the required authentications are complete.
295
			 */
296
			*(meth->enabled) = 0;
297
			packet_send_debug("Further authentication required");
298
			goto send_fail;
299
		}
219
300
220
		if (authenticated)
301
		if (authenticated)
221
			return;
302
			return;
Lines 223-228 do_authloop(Authctxt *authctxt) Link Here
223
		if (authctxt->failures++ > options.max_authtries)
304
		if (authctxt->failures++ > options.max_authtries)
224
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
305
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
225
306
307
 send_fail:
226
		packet_start(SSH_SMSG_FAILURE);
308
		packet_start(SSH_SMSG_FAILURE);
227
		packet_send();
309
		packet_send();
228
		packet_write_wait();
310
		packet_write_wait();
(-)auth2-chall.c (-10 / +4 lines)
Lines 243-251 input_userauth_info_response(int type, u Link Here
243
{
243
{
244
	Authctxt *authctxt = ctxt;
244
	Authctxt *authctxt = ctxt;
245
	KbdintAuthctxt *kbdintctxt;
245
	KbdintAuthctxt *kbdintctxt;
246
	int i, authenticated = 0, res, len;
246
	int i, authenticated = 0, res;
247
	u_int nresp;
247
	u_int nresp;
248
	char **response = NULL, *method;
248
	char **response = NULL;
249
249
250
	if (authctxt == NULL)
250
	if (authctxt == NULL)
251
		fatal("input_userauth_info_response: no authctxt");
251
		fatal("input_userauth_info_response: no authctxt");
Lines 292-303 input_userauth_info_response(int type, u Link Here
292
		break;
292
		break;
293
	}
293
	}
294
294
295
	len = strlen("keyboard-interactive") + 2 +
296
		strlen(kbdintctxt->device->name);
297
	method = xmalloc(len);
298
	snprintf(method, len, "keyboard-interactive/%s",
299
	    kbdintctxt->device->name);
300
301
	if (!authctxt->postponed) {
295
	if (!authctxt->postponed) {
302
		if (authenticated) {
296
		if (authenticated) {
303
			auth2_challenge_stop(authctxt);
297
			auth2_challenge_stop(authctxt);
Lines 307-314 input_userauth_info_response(int type, u Link Here
307
			auth2_challenge_start(authctxt);
301
			auth2_challenge_start(authctxt);
308
		}
302
		}
309
	}
303
	}
310
	userauth_finish(authctxt, authenticated, method);
304
	userauth_finish(authctxt, authenticated, "keyboard-interactive",
311
	xfree(method);
305
	    kbdintctxt->device->name);
312
}
306
}
313
307
314
void
308
void
(-)auth2-gss.c (-3 / +3 lines)
Lines 155-161 input_gssapi_token(int type, u_int32_t p Link Here
155
		}
155
		}
156
		authctxt->postponed = 0;
156
		authctxt->postponed = 0;
157
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
157
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
158
		userauth_finish(authctxt, 0, "gssapi-with-mic");
158
		userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
159
	} else {
159
	} else {
160
		if (send_tok.length != 0) {
160
		if (send_tok.length != 0) {
161
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
161
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
Lines 243-249 input_gssapi_exchange_complete(int type, Link Here
243
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
243
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
244
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
244
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
245
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
245
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
246
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
246
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
247
}
247
}
248
248
249
static void
249
static void
Lines 283-289 input_gssapi_mic(int type, u_int32_t ple Link Here
283
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
283
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
284
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
284
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
285
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
285
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
286
	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
286
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
287
}
287
}
288
288
289
Authmethod method_gssapi = {
289
Authmethod method_gssapi = {
(-)auth2-none.c (-1 / +1 lines)
Lines 101-107 userauth_none(Authctxt *authctxt) Link Here
101
	none_enabled = 0;
101
	none_enabled = 0;
102
	packet_check_eom();
102
	packet_check_eom();
103
	userauth_banner();
103
	userauth_banner();
104
	if (options.password_authentication)
104
	if (options.password_authentication && options.required_auth2 == NULL)
105
		return (PRIVSEP(auth_password(authctxt, "")));
105
		return (PRIVSEP(auth_password(authctxt, "")));
106
	return (0);
106
	return (0);
107
}
107
}
(-)auth2.c (-10 / +81 lines)
Lines 132-138 input_userauth_request(int type, u_int32 Link Here
132
{
132
{
133
	Authctxt *authctxt = ctxt;
133
	Authctxt *authctxt = ctxt;
134
	Authmethod *m = NULL;
134
	Authmethod *m = NULL;
135
	char *user, *service, *method, *style = NULL;
135
	char *user, *service, *method, *active_methods, *style = NULL;
136
	int authenticated = 0;
136
	int authenticated = 0;
137
137
138
	if (authctxt == NULL)
138
	if (authctxt == NULL)
Lines 181-192 input_userauth_request(int type, u_int32 Link Here
181
	authctxt->postponed = 0;
181
	authctxt->postponed = 0;
182
182
183
	/* try to authenticate user */
183
	/* try to authenticate user */
184
	m = authmethod_lookup(method);
184
	active_methods = authmethods_get();
185
	if (m != NULL) {
185
	if (strcmp(method, "none") == 0 || 
186
		debug2("input_userauth_request: try method %s", method);
186
	    auth_method_in_list(active_methods, method)) {
187
		authenticated =	m->userauth(authctxt);
187
		m = authmethod_lookup(method);
188
		if (m != NULL) {
189
			debug2("input_userauth_request: try method %s", method);
190
			authenticated =	m->userauth(authctxt);
191
		}
188
	}
192
	}
189
	userauth_finish(authctxt, authenticated, method);
193
	xfree(active_methods);
194
	userauth_finish(authctxt, authenticated, method, NULL);
190
195
191
	xfree(service);
196
	xfree(service);
192
	xfree(user);
197
	xfree(user);
Lines 194-202 input_userauth_request(int type, u_int32 Link Here
194
}
199
}
195
200
196
void
201
void
197
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
202
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
203
    const char *submethod)
198
{
204
{
199
	char *methods;
205
	char *methods;
206
	Authmethod *m = NULL;
207
	u_int partial = 0;
200
208
201
	if (!authctxt->valid && authenticated)
209
	if (!authctxt->valid && authenticated)
202
		fatal("INTERNAL ERROR: authenticated invalid user %s",
210
		fatal("INTERNAL ERROR: authenticated invalid user %s",
Lines 208-219 userauth_finish(Authctxt *authctxt, int Link Here
208
		authenticated = 0;
216
		authenticated = 0;
209
217
210
	/* Log before sending the reply */
218
	/* Log before sending the reply */
211
	auth_log(authctxt, authenticated, method, " ssh2");
219
	auth_log(authctxt, authenticated, method, submethod, " ssh2");
212
220
213
	if (authctxt->postponed)
221
	if (authctxt->postponed)
214
		return;
222
		return;
215
223
216
	/* XXX todo: check if multiple auth methods are needed */
224
	/* Handle RequiredAuthentications2: loop until required methods done */
225
	if (authenticated && options.required_auth2 != NULL) {
226
		if ((m = authmethod_lookup(method)) == NULL)
227
			fatal("INTERNAL ERROR: authenticated method "
228
			    "\"%s\" unknown", method);
229
		if (auth_remove_from_list(&options.required_auth2, method) != 1)
230
			fatal("INTERNAL ERROR: authenticated method "
231
			    "\"%s\" not in required list \"%s\"", 
232
			    method, options.required_auth2);
233
		debug2("userauth_finish: required list now: %s",
234
		    options.required_auth2 == NULL ?
235
		    "DONE" : options.required_auth2);
236
		/*
237
		 * Disable method so client can't authenticate with it after
238
		 * the required authentications are complete.
239
		 */
240
		if (m->enabled != NULL)
241
			*(m->enabled) = 0;
242
		authenticated = 0;
243
		partial = 1;
244
		goto send_fail;
245
	}
246
217
	if (authenticated == 1) {
247
	if (authenticated == 1) {
218
		/* turn off userauth */
248
		/* turn off userauth */
219
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
249
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
Lines 225-234 userauth_finish(Authctxt *authctxt, int Link Here
225
	} else {
255
	} else {
226
		if (authctxt->failures++ > options.max_authtries)
256
		if (authctxt->failures++ > options.max_authtries)
227
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
257
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
258
 send_fail:
228
		methods = authmethods_get();
259
		methods = authmethods_get();
229
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
260
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
230
		packet_put_cstring(methods);
261
		packet_put_cstring(methods);
231
		packet_put_char(0);	/* XXX partial success, unused */
262
		packet_put_char(partial);
232
		packet_send();
263
		packet_send();
233
		packet_write_wait();
264
		packet_write_wait();
234
		xfree(methods);
265
		xfree(methods);
Lines 244-249 authmethods_get(void) Link Here
244
	char *list;
275
	char *list;
245
	int i;
276
	int i;
246
277
278
	if (options.required_auth2 != NULL)
279
		return xstrdup(options.required_auth2);
280
247
	buffer_init(&b);
281
	buffer_init(&b);
248
	for (i = 0; authmethods[i] != NULL; i++) {
282
	for (i = 0; authmethods[i] != NULL; i++) {
249
		if (strcmp(authmethods[i]->name, "none") == 0)
283
		if (strcmp(authmethods[i]->name, "none") == 0)
Lines 276-279 authmethod_lookup(const char *name) Link Here
276
	debug2("Unrecognized authentication method name: %s",
310
	debug2("Unrecognized authentication method name: %s",
277
	    name ? name : "NULL");
311
	    name ? name : "NULL");
278
	return NULL;
312
	return NULL;
313
}
314
315
int
316
auth2_check_required(const char *list)
317
{
318
	char *orig_methods, *methods, *cp;
319
	struct Authmethod *m;
320
	int i, ret = 0;
321
322
	orig_methods = methods = xstrdup(list);
323
	for(;;) {
324
		if ((cp = strsep(&methods, DELIM)) == NULL)
325
			break;
326
		debug2("auth2_check_required: method \"%s\"", cp);
327
		if (*cp == '\0') {
328
			debug("auth2_check_required: empty method");
329
			ret = -1;
330
		}
331
		for (i = 0; authmethods[i] != NULL; i++)
332
			if (strcmp(cp, authmethods[i]->name) == 0)
333
				break;
334
		if ((m = authmethods[i]) == NULL) {
335
			debug("auth2_check_required: unknown method "
336
			    "\"%s\"", cp);
337
			ret = -1;
338
		}
339
		if (m->enabled == NULL || *(m->enabled) == 0) {
340
			debug("auth2_check_required: method %s explicitly "
341
			    "disabled", cp);
342
			ret = -1;
343
		}
344
		/* Activate method if it isn't already */
345
		if (*(m->enabled) == -1)
346
			*(m->enabled) = 1;
347
	}
348
	xfree(orig_methods);
349
	return (ret);
279
}
350
}
(-)monitor.c (-3 / +18 lines)
Lines 253-259 void Link Here
253
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
253
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
254
{
254
{
255
	struct mon_table *ent;
255
	struct mon_table *ent;
256
	int authenticated = 0;
256
	int no_increment, authenticated = 0;
257
	char **req_auth;
257
258
258
	debug3("preauth child monitor started");
259
	debug3("preauth child monitor started");
259
260
Lines 262-279 monitor_child_preauth(Authctxt *_authctx Link Here
262
263
263
	if (compat20) {
264
	if (compat20) {
264
		mon_dispatch = mon_dispatch_proto20;
265
		mon_dispatch = mon_dispatch_proto20;
266
		req_auth = &options.required_auth2;
265
267
266
		/* Permit requests for moduli and signatures */
268
		/* Permit requests for moduli and signatures */
267
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
269
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
268
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
270
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
269
	} else {
271
	} else {
270
		mon_dispatch = mon_dispatch_proto15;
272
		mon_dispatch = mon_dispatch_proto15;
273
		req_auth = &options.required_auth1;
271
274
272
		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
275
		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
273
	}
276
	}
274
277
275
	/* The first few requests do not require asynchronous access */
278
	/* The first few requests do not require asynchronous access */
276
	while (!authenticated) {
279
	while (!authenticated) {
280
		no_increment = 0;
277
		authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
281
		authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
278
		if (authenticated) {
282
		if (authenticated) {
279
			if (!(ent->flags & MON_AUTHDECIDE))
283
			if (!(ent->flags & MON_AUTHDECIDE))
Lines 283-293 monitor_child_preauth(Authctxt *_authctx Link Here
283
			    !auth_root_allowed(auth_method))
287
			    !auth_root_allowed(auth_method))
284
				authenticated = 0;
288
				authenticated = 0;
285
		}
289
		}
290
		/* Loop until the required authmethods are done */
291
		if (authenticated && *req_auth != NULL) {
292
			if (auth_remove_from_list(req_auth, auth_method) != 1)
293
				fatal("INTERNAL ERROR: authenticated method "
294
				    "\"%s\" not in required list \"%s\"", 
295
				    auth_method, *req_auth);
296
			debug2("monitor_child_preauth: required list now: %s",
297
			    *req_auth == NULL ? "DONE" : *req_auth);
298
			authenticated = 0;
299
			no_increment = 1;
300
		}
286
301
287
		if (ent->flags & MON_AUTHDECIDE) {
302
		if (ent->flags & MON_AUTHDECIDE) {
288
			auth_log(authctxt, authenticated, auth_method,
303
			auth_log(authctxt, authenticated, auth_method, NULL, 
289
			    compat20 ? " ssh2" : "");
304
			    compat20 ? " ssh2" : "");
290
			if (!authenticated)
305
			if (!authenticated && !no_increment)
291
				authctxt->failures++;
306
				authctxt->failures++;
292
		}
307
		}
293
	}
308
	}
(-)servconf.c (-1 / +34 lines)
Lines 22-27 RCSID("$OpenBSD: servconf.c,v 1.138 2004 Link Here
22
#include "cipher.h"
22
#include "cipher.h"
23
#include "kex.h"
23
#include "kex.h"
24
#include "mac.h"
24
#include "mac.h"
25
#include "auth.h"
25
26
26
static void add_listen_addr(ServerOptions *, char *, u_short);
27
static void add_listen_addr(ServerOptions *, char *, u_short);
27
static void add_one_listen_addr(ServerOptions *, char *, u_short);
28
static void add_one_listen_addr(ServerOptions *, char *, u_short);
Lines 96-101 initialize_server_options(ServerOptions Link Here
96
	options->authorized_keys_file = NULL;
97
	options->authorized_keys_file = NULL;
97
	options->authorized_keys_file2 = NULL;
98
	options->authorized_keys_file2 = NULL;
98
	options->num_accept_env = 0;
99
	options->num_accept_env = 0;
100
	options->required_auth1 = NULL;
101
	options->required_auth2 = NULL;
99
102
100
	/* Needs to be accessable in many places */
103
	/* Needs to be accessable in many places */
101
	use_privsep = -1;
104
	use_privsep = -1;
Lines 248-254 typedef enum { Link Here
248
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
251
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
249
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
252
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
250
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv,
253
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv,
251
	sUsePrivilegeSeparation,
254
	sRequiredAuthentications1, sRequiredAuthentications2,
255
	sUsePrivilegeSeparation, 
252
	sDeprecated, sUnsupported
256
	sDeprecated, sUnsupported
253
} ServerOpCodes;
257
} ServerOpCodes;
254
258
Lines 338-343 static struct { Link Here
338
	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
342
	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
339
	{ "useprivilegeseparation", sUsePrivilegeSeparation},
343
	{ "useprivilegeseparation", sUsePrivilegeSeparation},
340
	{ "acceptenv", sAcceptEnv },
344
	{ "acceptenv", sAcceptEnv },
345
	{ "requiredauthentications1", sRequiredAuthentications1 },
346
	{ "requiredauthentications2", sRequiredAuthentications2 },
341
	{ NULL, sBadOption }
347
	{ NULL, sBadOption }
342
};
348
};
343
349
Lines 853-858 parse_flag: Link Here
853
			    filename, linenum);
859
			    filename, linenum);
854
		else
860
		else
855
			options->max_startups = options->max_startups_begin;
861
			options->max_startups = options->max_startups_begin;
862
		break;
863
864
865
	case sRequiredAuthentications1:
866
		charptr = &options->required_auth1;
867
		arg = strdelim(&cp);
868
		if (auth1_check_required(arg) != 0)
869
			fatal("%.200s line %d: Invalid required authentication "
870
			    "list", filename, linenum);
871
		if (!arg || *arg == '\0')
872
			fatal("%.200s line %d: Missing argument.",
873
			    filename, linenum);
874
		if (*charptr == NULL)
875
			*charptr = xstrdup(arg);
876
		break;
877
878
	case sRequiredAuthentications2:
879
		charptr = &options->required_auth2;
880
		arg = strdelim(&cp);
881
		if (auth2_check_required(arg) != 0)
882
			fatal("%.200s line %d: Invalid required authentication "
883
			    "list", filename, linenum);
884
		if (!arg || *arg == '\0')
885
			fatal("%.200s line %d: Missing argument.",
886
			    filename, linenum);
887
		if (*charptr == NULL)
888
			*charptr = xstrdup(arg);
856
		break;
889
		break;
857
890
858
	case sMaxAuthTries:
891
	case sMaxAuthTries:
(-)servconf.h (+3 lines)
Lines 133-138 typedef struct { Link Here
133
133
134
	char   *authorized_keys_file;	/* File containing public keys */
134
	char   *authorized_keys_file;	/* File containing public keys */
135
	char   *authorized_keys_file2;
135
	char   *authorized_keys_file2;
136
137
	char   *required_auth1; /* Required, but not sufficient */
138
	char   *required_auth2;
136
}       ServerOptions;
139
}       ServerOptions;
137
140
138
void	 initialize_server_options(ServerOptions *);
141
void	 initialize_server_options(ServerOptions *);

Return to bug 983