xref: /freebsd/crypto/openssh/auth2.c (revision 64db83a8ab2d1f72a9b2174b39d2ef42b5b0580c)
1 /*
2  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by Markus Friedl.
15  * 4. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 #include "includes.h"
32 RCSID("$OpenBSD: auth2.c,v 1.8 2000/05/08 17:42:24 markus Exp $");
33 
34 #include <openssl/dsa.h>
35 #include <openssl/rsa.h>
36 #include <openssl/evp.h>
37 
38 #include "xmalloc.h"
39 #include "rsa.h"
40 #include "ssh.h"
41 #include "pty.h"
42 #include "packet.h"
43 #include "buffer.h"
44 #include "cipher.h"
45 #include "servconf.h"
46 #include "compat.h"
47 #include "channels.h"
48 #include "bufaux.h"
49 #include "ssh2.h"
50 #include "auth.h"
51 #include "session.h"
52 #include "dispatch.h"
53 #include "auth.h"
54 #include "key.h"
55 #include "kex.h"
56 
57 #include "dsa.h"
58 #include "uidswap.h"
59 
60 /* import */
61 extern ServerOptions options;
62 extern unsigned char *session_id2;
63 extern int session_id2_len;
64 
65 /* protocol */
66 
67 void	input_service_request(int type, int plen);
68 void	input_userauth_request(int type, int plen);
69 void	protocol_error(int type, int plen);
70 
71 /* auth */
72 int	ssh2_auth_none(struct passwd *pw);
73 int	ssh2_auth_password(struct passwd *pw);
74 int	ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen);
75 
76 /* helper */
77 struct passwd*	 auth_set_user(char *u, char *s);
78 int	user_dsa_key_allowed(struct passwd *pw, Key *key);
79 
80 typedef struct Authctxt Authctxt;
81 struct Authctxt {
82 	char *user;
83 	char *service;
84 	struct passwd pw;
85 	int valid;
86 };
87 static Authctxt	*authctxt = NULL;
88 static int userauth_success = 0;
89 
90 /*
91  * loop until userauth_success == TRUE
92  */
93 
94 void
95 do_authentication2()
96 {
97 	/* turn off skey/kerberos, not supported by SSH2 */
98 #ifdef SKEY
99 	options.skey_authentication = 0;
100 #endif
101 #ifdef KRB4
102 	options.krb4_authentication = 0;
103 #endif
104 
105 	dispatch_init(&protocol_error);
106 	dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
107 	dispatch_run(DISPATCH_BLOCK, &userauth_success);
108 	do_authenticated2();
109 }
110 
111 void
112 protocol_error(int type, int plen)
113 {
114 	log("auth: protocol error: type %d plen %d", type, plen);
115 	packet_start(SSH2_MSG_UNIMPLEMENTED);
116 	packet_put_int(0);
117 	packet_send();
118 	packet_write_wait();
119 }
120 
121 void
122 input_service_request(int type, int plen)
123 {
124 	unsigned int len;
125 	int accept = 0;
126 	char *service = packet_get_string(&len);
127 	packet_done();
128 
129 	if (strcmp(service, "ssh-userauth") == 0) {
130 		if (!userauth_success) {
131 			accept = 1;
132 			/* now we can handle user-auth requests */
133 			dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
134 		}
135 	}
136 	/* XXX all other service requests are denied */
137 
138 	if (accept) {
139 		packet_start(SSH2_MSG_SERVICE_ACCEPT);
140 		packet_put_cstring(service);
141 		packet_send();
142 		packet_write_wait();
143 	} else {
144 		debug("bad service request %s", service);
145 		packet_disconnect("bad service request %s", service);
146 	}
147 	xfree(service);
148 }
149 
150 void
151 input_userauth_request(int type, int plen)
152 {
153 	static void (*authlog) (const char *fmt,...) = verbose;
154 	static int attempt = 0;
155 	unsigned int len, rlen;
156 	int authenticated = 0;
157 	char *raw, *user, *service, *method, *authmsg = NULL;
158 	struct passwd *pw;
159 
160 	if (++attempt == AUTH_FAIL_MAX)
161 		packet_disconnect("too many failed userauth_requests");
162 
163 	raw = packet_get_raw(&rlen);
164 	if (plen != rlen)
165 		fatal("plen != rlen");
166 	user = packet_get_string(&len);
167 	service = packet_get_string(&len);
168 	method = packet_get_string(&len);
169 	debug("userauth-request for user %s service %s method %s", user, service, method);
170 
171 	/* XXX we only allow the ssh-connection service */
172 	pw = auth_set_user(user, service);
173 	if (pw && strcmp(service, "ssh-connection")==0) {
174 		if (strcmp(method, "none") == 0) {
175 			authenticated =	ssh2_auth_none(pw);
176 		} else if (strcmp(method, "password") == 0) {
177 			authenticated =	ssh2_auth_password(pw);
178 		} else if (strcmp(method, "publickey") == 0) {
179 			authenticated =	ssh2_auth_pubkey(pw, raw, rlen);
180 		}
181 	}
182 	if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
183 		authenticated = 0;
184 		log("ROOT LOGIN REFUSED FROM %.200s",
185 		    get_canonical_hostname());
186 	}
187 
188 	/* Raise logging level */
189 	if (authenticated == 1 ||
190 	    attempt == AUTH_FAIL_LOG ||
191 	    strcmp(method, "password") == 0)
192 		authlog = log;
193 
194 	/* Log before sending the reply */
195 	if (authenticated == 1) {
196 		authmsg = "Accepted";
197 	} else if (authenticated == 0) {
198 		authmsg = "Failed";
199 	} else {
200 		authmsg = "Postponed";
201 	}
202 	authlog("%s %s for %.200s from %.200s port %d ssh2",
203 		authmsg,
204 		method,
205 		pw && pw->pw_uid == 0 ? "ROOT" : user,
206 		get_remote_ipaddr(),
207 		get_remote_port());
208 
209 	/* XXX todo: check if multiple auth methods are needed */
210 	if (authenticated == 1) {
211 		/* turn off userauth */
212 		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
213 		packet_start(SSH2_MSG_USERAUTH_SUCCESS);
214 		packet_send();
215 		packet_write_wait();
216 		/* now we can break out */
217 		userauth_success = 1;
218 	} else if (authenticated == 0) {
219 		packet_start(SSH2_MSG_USERAUTH_FAILURE);
220 		packet_put_cstring("publickey,password");	/* XXX dynamic */
221 		packet_put_char(0);				/* XXX partial success, unused */
222 		packet_send();
223 		packet_write_wait();
224 	}
225 
226 	xfree(service);
227 	xfree(user);
228 	xfree(method);
229 }
230 
231 int
232 ssh2_auth_none(struct passwd *pw)
233 {
234 	packet_done();
235 	return auth_password(pw, "");
236 }
237 int
238 ssh2_auth_password(struct passwd *pw)
239 {
240 	char *password;
241 	int authenticated = 0;
242 	int change;
243 	unsigned int len;
244 	change = packet_get_char();
245 	if (change)
246 		log("password change not supported");
247 	password = packet_get_string(&len);
248 	packet_done();
249 	if (options.password_authentication &&
250 	    auth_password(pw, password) == 1)
251 		authenticated = 1;
252 	memset(password, 0, len);
253 	xfree(password);
254 	return authenticated;
255 }
256 int
257 ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
258 {
259 	Buffer b;
260 	Key *key;
261 	char *pkalg, *pkblob, *sig;
262 	unsigned int alen, blen, slen;
263 	int have_sig;
264 	int authenticated = 0;
265 
266 	if (options.dsa_authentication == 0) {
267 		debug("pubkey auth disabled");
268 		return 0;
269 	}
270 	if (datafellows & SSH_BUG_PUBKEYAUTH) {
271 		log("bug compatibility with ssh-2.0.13 pubkey not implemented");
272 		return 0;
273 	}
274 	have_sig = packet_get_char();
275 	pkalg = packet_get_string(&alen);
276 	if (strcmp(pkalg, KEX_DSS) != 0) {
277 		xfree(pkalg);
278 		log("bad pkalg %s", pkalg);	/*XXX*/
279 		return 0;
280 	}
281 	pkblob = packet_get_string(&blen);
282 	key = dsa_key_from_blob(pkblob, blen);
283 	if (key != NULL) {
284 		if (have_sig) {
285 			sig = packet_get_string(&slen);
286 			packet_done();
287 			buffer_init(&b);
288 			buffer_append(&b, session_id2, session_id2_len);
289 			buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
290 			if (slen + 4 > rlen)
291 				fatal("bad rlen/slen");
292 			buffer_append(&b, raw, rlen - slen - 4);
293 #ifdef DEBUG_DSS
294 			buffer_dump(&b);
295 #endif
296 			/* test for correct signature */
297 			if (user_dsa_key_allowed(pw, key) &&
298 			    dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
299 				authenticated = 1;
300 			buffer_clear(&b);
301 			xfree(sig);
302 		} else {
303 			packet_done();
304 			debug("test key...");
305 			/* test whether pkalg/pkblob are acceptable */
306 			/* XXX fake reply and always send PK_OK ? */
307 			/*
308 			 * XXX this allows testing whether a user is allowed
309 			 * to login: if you happen to have a valid pubkey this
310 			 * message is sent. the message is NEVER sent at all
311 			 * if a user is not allowed to login. is this an
312 			 * issue? -markus
313 			 */
314 			if (user_dsa_key_allowed(pw, key)) {
315 				packet_start(SSH2_MSG_USERAUTH_PK_OK);
316 				packet_put_string(pkalg, alen);
317 				packet_put_string(pkblob, blen);
318 				packet_send();
319 				packet_write_wait();
320 				authenticated = -1;
321 			}
322 		}
323 		key_free(key);
324 	}
325 	xfree(pkalg);
326 	xfree(pkblob);
327 	return authenticated;
328 }
329 
330 /* set and get current user */
331 
332 struct passwd*
333 auth_get_user(void)
334 {
335 	return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL;
336 }
337 
338 struct passwd*
339 auth_set_user(char *u, char *s)
340 {
341 	struct passwd *pw, *copy;
342 
343 	if (authctxt == NULL) {
344 		authctxt = xmalloc(sizeof(*authctxt));
345 		authctxt->valid = 0;
346 		authctxt->user = xstrdup(u);
347 		authctxt->service = xstrdup(s);
348 		setproctitle("%s", u);
349 		pw = getpwnam(u);
350 		if (!pw || !allowed_user(pw)) {
351 			log("auth_set_user: illegal user %s", u);
352 			return NULL;
353 		}
354 		copy = &authctxt->pw;
355 		memset(copy, 0, sizeof(*copy));
356 		copy->pw_name = xstrdup(pw->pw_name);
357 		copy->pw_passwd = xstrdup(pw->pw_passwd);
358 		copy->pw_uid = pw->pw_uid;
359 		copy->pw_gid = pw->pw_gid;
360 		copy->pw_dir = xstrdup(pw->pw_dir);
361 		copy->pw_shell = xstrdup(pw->pw_shell);
362 		authctxt->valid = 1;
363 	} else {
364 		if (strcmp(u, authctxt->user) != 0 ||
365 		    strcmp(s, authctxt->service) != 0) {
366 			log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
367 			    u, s, authctxt->user, authctxt->service);
368 			return NULL;
369 		}
370 	}
371 	return auth_get_user();
372 }
373 
374 /* return 1 if user allows given key */
375 int
376 user_dsa_key_allowed(struct passwd *pw, Key *key)
377 {
378 	char line[8192], file[1024];
379 	int found_key = 0;
380 	unsigned int bits = -1;
381 	FILE *f;
382 	unsigned long linenum = 0;
383 	struct stat st;
384 	Key *found;
385 
386 	/* Temporarily use the user's uid. */
387 	temporarily_use_uid(pw->pw_uid);
388 
389 	/* The authorized keys. */
390 	snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
391 	    SSH_USER_PERMITTED_KEYS2);
392 
393 	/* Fail quietly if file does not exist */
394 	if (stat(file, &st) < 0) {
395 		/* Restore the privileged uid. */
396 		restore_uid();
397 		return 0;
398 	}
399 	/* Open the file containing the authorized keys. */
400 	f = fopen(file, "r");
401 	if (!f) {
402 		/* Restore the privileged uid. */
403 		restore_uid();
404 		return 0;
405 	}
406 	if (options.strict_modes) {
407 		int fail = 0;
408 		char buf[1024];
409 		/* Check open file in order to avoid open/stat races */
410 		if (fstat(fileno(f), &st) < 0 ||
411 		    (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
412 		    (st.st_mode & 022) != 0) {
413 			snprintf(buf, sizeof buf, "DSA authentication refused for %.100s: "
414 			    "bad ownership or modes for '%s'.", pw->pw_name, file);
415 			fail = 1;
416 		} else {
417 			/* Check path to SSH_USER_PERMITTED_KEYS */
418 			int i;
419 			static const char *check[] = {
420 				"", SSH_USER_DIR, NULL
421 			};
422 			for (i = 0; check[i]; i++) {
423 				snprintf(line, sizeof line, "%.500s/%.100s",
424 				    pw->pw_dir, check[i]);
425 				if (stat(line, &st) < 0 ||
426 				    (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
427 				    (st.st_mode & 022) != 0) {
428 					snprintf(buf, sizeof buf,
429 					    "DSA authentication refused for %.100s: "
430 					    "bad ownership or modes for '%s'.",
431 					    pw->pw_name, line);
432 					fail = 1;
433 					break;
434 				}
435 			}
436 		}
437 		if (fail) {
438 			log(buf);
439 			fclose(f);
440 			restore_uid();
441 			return 0;
442 		}
443 	}
444 	found_key = 0;
445 	found = key_new(KEY_DSA);
446 
447 	while (fgets(line, sizeof(line), f)) {
448 		char *cp;
449 		linenum++;
450 		/* Skip leading whitespace, empty and comment lines. */
451 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
452 			;
453 		if (!*cp || *cp == '\n' || *cp == '#')
454 			continue;
455 		bits = key_read(found, &cp);
456 		if (bits == 0)
457 			continue;
458 		if (key_equal(found, key)) {
459 			found_key = 1;
460 			debug("matching key found: file %s, line %ld",
461 			    file, linenum);
462 			break;
463 		}
464 	}
465 	restore_uid();
466 	fclose(f);
467 	key_free(found);
468 	return found_key;
469 }
470