auth1.c revision 74147
1/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 *                    All rights reserved
4 *
5 * As far as I am concerned, the code I have written for this software
6 * can be used freely for any purpose.  Any derived versions of this
7 * software must be clearly marked as such, and if the derived work is
8 * incompatible with the protocol description in the RFC file, it must be
9 * called by a name other than "ssh" or "Secure Shell".
10 */
11
12#include "includes.h"
13RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
14RCSID("$FreeBSD: head/crypto/openssh/auth1.c 74147 2001-03-12 08:14:22Z assar $");
15
16#include "xmalloc.h"
17#include "rsa.h"
18#include "ssh.h"
19#include "packet.h"
20#include "buffer.h"
21#include "mpaux.h"
22#include "servconf.h"
23#include "compat.h"
24#include "auth.h"
25#include "session.h"
26#include <login_cap.h>
27#include <security/pam_appl.h>
28
29#ifdef KRB5
30extern krb5_context ssh_context;
31krb5_principal tkt_client = NULL;    /* Principal from the received ticket.
32Also is used as an indication of succesful krb5 authentization. */
33#endif
34
35/* import */
36extern ServerOptions options;
37extern char *forced_command;
38
39/*
40 * convert ssh auth msg type into description
41 */
42char *
43get_authname(int type)
44{
45	static char buf[1024];
46	switch (type) {
47	case SSH_CMSG_AUTH_PASSWORD:
48		return "password";
49	case SSH_CMSG_AUTH_RSA:
50		return "rsa";
51	case SSH_CMSG_AUTH_RHOSTS_RSA:
52		return "rhosts-rsa";
53	case SSH_CMSG_AUTH_RHOSTS:
54		return "rhosts";
55#if defined(KRB4) || defined(KRB5)
56	case SSH_CMSG_AUTH_KERBEROS:
57		return "kerberos";
58#endif
59#ifdef SKEY
60	case SSH_CMSG_AUTH_TIS_RESPONSE:
61		return "s/key";
62#endif
63	}
64	snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
65	return buf;
66}
67
68/*
69 * read packets and try to authenticate local user 'luser'.
70 * return if authentication is successfull. not that pw == NULL
71 * if the user does not exists or is not allowed to login.
72 * each auth method has to 'fake' authentication for nonexisting
73 * users.
74 */
75void
76do_authloop(struct passwd * pw, char *luser)
77{
78	int authenticated = 0;
79	int attempt = 0;
80	unsigned int bits;
81	RSA *client_host_key;
82	BIGNUM *n;
83	char *client_user, *password;
84	char user[1024];
85	unsigned int dlen;
86	int plen, nlen, elen;
87	unsigned int ulen;
88	int type = 0;
89	void (*authlog) (const char *fmt,...) = verbose;
90#ifdef HAVE_LOGIN_CAP
91	login_cap_t *lc;
92#endif /* HAVE_LOGIN_CAP */
93#ifdef USE_PAM
94	struct inverted_pam_cookie *pam_cookie;
95#endif /* USE_PAM */
96#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
97	const char *from_host, *from_ip;
98
99	from_host = get_canonical_hostname();
100	from_ip = get_remote_ipaddr();
101#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
102#if 0
103#ifdef KRB5
104	{
105	  	krb5_error_code ret;
106
107		ret = krb5_init_context(&ssh_context);
108		if (ret)
109		 	verbose("Error while initializing Kerberos V5.");
110		krb5_init_ets(ssh_context);
111
112	}
113#endif /* KRB5 */
114#endif
115
116	/* Indicate that authentication is needed. */
117	packet_start(SSH_SMSG_FAILURE);
118	packet_send();
119	packet_write_wait();
120
121	client_user = NULL;
122
123	for (attempt = 1;; attempt++) {
124		/* default to fail */
125		authenticated = 0;
126
127		strlcpy(user, "", sizeof user);
128
129		/* Get a packet from the client. */
130		type = packet_read(&plen);
131
132		/* Process the packet. */
133		switch (type) {
134#ifdef AFS
135#ifndef KRB5
136		case SSH_CMSG_HAVE_KRB4_TGT:
137			if (!options.krb4_tgt_passing) {
138				/* packet_get_all(); */
139				verbose("Kerberos v4 tgt passing disabled.");
140				break;
141			} else {
142				/* Accept Kerberos v4 tgt. */
143				char *tgt = packet_get_string(&dlen);
144				packet_integrity_check(plen, 4 + dlen, type);
145				if (!auth_krb4_tgt(pw, tgt))
146					verbose("Kerberos v4 tgt REFUSED for %s", luser);
147				xfree(tgt);
148			}
149			continue;
150#endif /* !KRB5 */
151		case SSH_CMSG_HAVE_AFS_TOKEN:
152			if (!options.afs_token_passing || !k_hasafs()) {
153				verbose("AFS token passing disabled.");
154				break;
155			} else {
156				/* Accept AFS token. */
157				char *token_string = packet_get_string(&dlen);
158				packet_integrity_check(plen, 4 + dlen, type);
159				if (!auth_afs_token(pw, token_string))
160					verbose("AFS token REFUSED for %.100s", luser);
161				xfree(token_string);
162			}
163			continue;
164#endif /* AFS */
165#if defined(KRB4) || defined(KRB5)
166		case SSH_CMSG_AUTH_KERBEROS:
167			if (!options.kerberos_authentication) {
168				verbose("Kerberos authentication disabled.");
169  			} else {
170				unsigned int length;
171				char *kdata = packet_get_string(&length);
172				packet_integrity_check(plen, 4 + length, type);
173
174				/* 4 == KRB_PROT_VERSION */
175				if (kdata[0] == 4) {
176#ifndef KRB4
177					verbose("Kerberos v4 authentication disabled.");
178#else
179					char *tkt_user = NULL;
180					KTEXT_ST auth;
181					auth.length = length;
182					if (auth.length < MAX_KTXT_LEN)
183						memcpy(auth.dat, kdata, auth.length);
184
185					authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
186
187					if (authenticated) {
188						snprintf(user, sizeof user, " tktuser %s", tkt_user);
189						xfree(tkt_user);
190					}
191  #endif /* KRB4 */
192				} else {
193#ifndef KRB5
194					verbose("Kerberos v5 authentication disabled.");
195#else
196				  	krb5_data k5data;
197					k5data.length = length;
198					k5data.data = kdata;
199  #if 0
200					if (krb5_init_context(&ssh_context)) {
201						verbose("Error while initializing Kerberos V5.");
202						break;
203					}
204					krb5_init_ets(ssh_context);
205  #endif
206					/* pw->name is passed just for logging purposes */
207					if (auth_krb5(pw->pw_name, &k5data, &tkt_client)) {
208					  	/* authorize client against .k5login */
209					  	if (krb5_kuserok(ssh_context,
210						      tkt_client,
211						      pw->pw_name))
212						  	authenticated = 1;
213					}
214#endif /* KRB5 */
215  				}
216				xfree(kdata);
217  			}
218  			break;
219#endif /* KRB4 || KRB5 */
220
221		case SSH_CMSG_AUTH_RHOSTS:
222			if (!options.rhosts_authentication) {
223				verbose("Rhosts authentication disabled.");
224				break;
225			}
226			/*
227			 * Get client user name.  Note that we just have to
228			 * trust the client; this is one reason why rhosts
229			 * authentication is insecure. (Another is
230			 * IP-spoofing on a local network.)
231			 */
232			client_user = packet_get_string(&ulen);
233			packet_integrity_check(plen, 4 + ulen, type);
234
235			/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
236			authenticated = auth_rhosts(pw, client_user);
237
238			snprintf(user, sizeof user, " ruser %s", client_user);
239			break;
240
241		case SSH_CMSG_AUTH_RHOSTS_RSA:
242			if (!options.rhosts_rsa_authentication) {
243				verbose("Rhosts with RSA authentication disabled.");
244				break;
245			}
246			/*
247			 * Get client user name.  Note that we just have to
248			 * trust the client; root on the client machine can
249			 * claim to be any user.
250			 */
251			client_user = packet_get_string(&ulen);
252
253			/* Get the client host key. */
254			client_host_key = RSA_new();
255			if (client_host_key == NULL)
256				fatal("RSA_new failed");
257			client_host_key->e = BN_new();
258			client_host_key->n = BN_new();
259			if (client_host_key->e == NULL || client_host_key->n == NULL)
260				fatal("BN_new failed");
261			bits = packet_get_int();
262			packet_get_bignum(client_host_key->e, &elen);
263			packet_get_bignum(client_host_key->n, &nlen);
264
265			if (bits != BN_num_bits(client_host_key->n))
266				verbose("Warning: keysize mismatch for client_host_key: "
267				    "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
268			packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
269
270			authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
271			RSA_free(client_host_key);
272
273			snprintf(user, sizeof user, " ruser %s", client_user);
274			break;
275
276		case SSH_CMSG_AUTH_RSA:
277			if (!options.rsa_authentication) {
278				verbose("RSA authentication disabled.");
279				break;
280			}
281			/* RSA authentication requested. */
282			n = BN_new();
283			packet_get_bignum(n, &nlen);
284			packet_integrity_check(plen, nlen, type);
285			authenticated = auth_rsa(pw, n);
286			BN_clear_free(n);
287			break;
288
289		case SSH_CMSG_AUTH_PASSWORD:
290			if (!options.password_authentication) {
291				verbose("Password authentication disabled.");
292				break;
293			}
294			/*
295			 * Read user password.  It is in plain text, but was
296			 * transmitted over the encrypted channel so it is
297			 * not visible to an outside observer.
298			 */
299			password = packet_get_string(&dlen);
300			packet_integrity_check(plen, 4 + dlen, type);
301
302#ifdef USE_PAM
303			/* Do PAM auth with password */
304			authenticated = auth_pam_password(pw, password);
305#else /* !USE_PAM */
306 			/* Try authentication with the password. */
307			authenticated = auth_password(pw, password);
308#endif /* USE_PAM */
309
310			memset(password, 0, strlen(password));
311			xfree(password);
312			break;
313
314#ifdef USE_PAM
315		case SSH_CMSG_AUTH_TIS:
316			debug("rcvd SSH_CMSG_AUTH_TIS: Trying PAM");
317			pam_cookie = ipam_start_auth("csshd", pw->pw_name);
318			/* We now have data available to send as a challenge */
319			if (pam_cookie->num_msg != 1 ||
320			    (pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_OFF &&
321			     pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_ON)) {
322			    /* We got several challenges or an unknown challenge type */
323			    ipam_free_cookie(pam_cookie);
324			    pam_cookie = NULL;
325			    break;
326			}
327			packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
328			packet_put_string(pam_cookie->msg[0]->msg, strlen(pam_cookie->msg[0]->msg));
329			packet_send();
330			packet_write_wait();
331			continue;
332		case SSH_CMSG_AUTH_TIS_RESPONSE:
333			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
334			if (pam_cookie == NULL)
335			    break;
336			{
337			    char *response = packet_get_string(&dlen);
338
339			    packet_integrity_check(plen, 4 + dlen, type);
340			    pam_cookie->resp[0]->resp = strdup(response);
341			    xfree(response);
342			    authenticated = ipam_complete_auth(pam_cookie);
343			    ipam_free_cookie(pam_cookie);
344			    pam_cookie = NULL;
345			}
346			break;
347#elif defined(SKEY)
348		case SSH_CMSG_AUTH_TIS:
349			debug("rcvd SSH_CMSG_AUTH_TIS");
350			if (options.skey_authentication == 1) {
351				char *skeyinfo = pw ? opie_keyinfo(pw->pw_name) :
352				    NULL;
353				if (skeyinfo == NULL) {
354					debug("generating fake skeyinfo for %.100s.", luser);
355					skeyinfo = skey_fake_keyinfo(luser);
356				}
357				if (skeyinfo != NULL) {
358					/* we send our s/key- in tis-challenge messages */
359					debug("sending challenge '%s'", skeyinfo);
360					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
361					packet_put_cstring(skeyinfo);
362					packet_send();
363					packet_write_wait();
364					continue;
365				}
366			}
367			break;
368		case SSH_CMSG_AUTH_TIS_RESPONSE:
369			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
370			if (options.skey_authentication == 1) {
371				char *response = packet_get_string(&dlen);
372				debug("skey response == '%s'", response);
373				packet_integrity_check(plen, 4 + dlen, type);
374				authenticated = (pw != NULL &&
375				    opie_haskey(pw->pw_name) == 0 &&
376				    opie_passverify(pw->pw_name, response) != -1);
377				xfree(response);
378			}
379			break;
380#else
381		case SSH_CMSG_AUTH_TIS:
382			/* TIS Authentication is unsupported */
383			log("TIS authentication unsupported.");
384			break;
385#endif
386#ifdef KRB5
387		case SSH_CMSG_HAVE_KERBEROS_TGT:
388			/* Passing krb5 ticket */
389			if (!options.krb5_tgt_passing
390                            /*|| !options.krb5_authentication */) {
391
392			}
393
394			if (tkt_client == NULL) {
395			  /* passing tgt without krb5 authentication */
396			}
397
398			{
399			  krb5_data tgt;
400			  u_int tgtlen;
401			  tgt.data = packet_get_string(&tgtlen);
402			  tgt.length = tgtlen;
403
404			  if (!auth_krb5_tgt(luser, &tgt, tkt_client))
405			    verbose ("Kerberos V5 TGT refused for %.100s", luser);
406			  xfree(tgt.data);
407
408			  break;
409			}
410#endif /* KRB5 */
411
412		default:
413			/*
414			 * Any unknown messages will be ignored (and failure
415			 * returned) during authentication.
416			 */
417			log("Unknown message during authentication: type %d", type);
418			break;
419		}
420		if (authenticated && pw == NULL)
421			fatal("internal error: authenticated for pw == NULL");
422
423		/*
424		 * Check if the user is logging in as root and root logins
425		 * are disallowed.
426		 * Note that root login is allowed for forced commands.
427		 */
428		if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
429			if (forced_command) {
430				log("Root login accepted for forced command.");
431			} else {
432				authenticated = 0;
433				log("ROOT LOGIN REFUSED FROM %.200s",
434				    get_canonical_hostname());
435			}
436		}
437
438#ifdef HAVE_LOGIN_CAP
439		if (pw != NULL) {
440		  lc = login_getpwclass(pw);
441		  if (lc == NULL)
442			lc = login_getclassbyname(NULL, pw);
443		  if (!auth_hostok(lc, from_host, from_ip)) {
444			log("Denied connection for %.200s from %.200s [%.200s].",
445		      pw->pw_name, from_host, from_ip);
446			packet_disconnect("Sorry, you are not allowed to connect.");
447		  }
448		  if (!auth_timeok(lc, time(NULL))) {
449			log("LOGIN %.200s REFUSED (TIME) FROM %.200s",
450		      pw->pw_name, from_host);
451			packet_disconnect("Logins not available right now.");
452		  }
453		  login_close(lc);
454		  lc = NULL;
455		}
456#endif  /* HAVE_LOGIN_CAP */
457#ifdef LOGIN_ACCESS
458		if (pw != NULL && !login_access(pw->pw_name, from_host)) {
459		  log("Denied connection for %.200s from %.200s [%.200s].",
460		      pw->pw_name, from_host, from_ip);
461		  packet_disconnect("Sorry, you are not allowed to connect.");
462		}
463#endif /* LOGIN_ACCESS */
464
465		if (pw != NULL && pw->pw_uid == 0)
466		  log("ROOT LOGIN as '%.100s' from %.100s",
467		      pw->pw_name, get_canonical_hostname());
468
469		/* Raise logging level */
470		if (authenticated ||
471		    attempt == AUTH_FAIL_LOG ||
472		    type == SSH_CMSG_AUTH_PASSWORD)
473			authlog = log;
474
475		authlog("%s %s for %s%.100s from %.200s port %d%s",
476			authenticated ? "Accepted" : "Failed",
477			get_authname(type),
478			pw ? "" : "illegal user ",
479			pw && pw->pw_uid == 0 ? "ROOT" : luser,
480			get_remote_ipaddr(),
481			get_remote_port(),
482			user);
483
484		if (authenticated)
485			return;
486
487#ifdef USE_PAM
488		if (authenticated && !do_pam_account(pw->pw_name, client_user))
489			authenticated = 0;
490#endif
491
492		if (client_user != NULL) {
493			xfree(client_user);
494			client_user = NULL;
495		}
496
497		if (attempt > AUTH_FAIL_MAX)
498			packet_disconnect(AUTH_FAIL_MSG, luser);
499
500		/* Send a message indicating that the authentication attempt failed. */
501		packet_start(SSH_SMSG_FAILURE);
502		packet_send();
503		packet_write_wait();
504	}
505}
506
507/*
508 * Performs authentication of an incoming connection.  Session key has already
509 * been exchanged and encryption is enabled.
510 */
511void
512do_authentication()
513{
514	struct passwd *pw, pwcopy;
515	int plen;
516	unsigned int ulen;
517	char *user;
518
519	/* Get the name of the user that we wish to log in as. */
520	packet_read_expect(&plen, SSH_CMSG_USER);
521
522	/* Get the user name. */
523	user = packet_get_string(&ulen);
524	packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
525
526	setproctitle("%s", user);
527
528#ifdef AFS
529	/* If machine has AFS, set process authentication group. */
530	if (k_hasafs()) {
531		k_setpag();
532		k_unlog();
533	}
534#endif /* AFS */
535
536	/* Verify that the user is a valid user. */
537	pw = getpwnam(user);
538	if (pw && allowed_user(pw)) {
539		/* Take a copy of the returned structure. */
540		memset(&pwcopy, 0, sizeof(pwcopy));
541		pwcopy.pw_name = xstrdup(pw->pw_name);
542		pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
543		pwcopy.pw_uid = pw->pw_uid;
544		pwcopy.pw_gid = pw->pw_gid;
545		pwcopy.pw_class = xstrdup(pw->pw_class);
546		pwcopy.pw_dir = xstrdup(pw->pw_dir);
547		pwcopy.pw_shell = xstrdup(pw->pw_shell);
548		pwcopy.pw_expire = pw->pw_expire;
549		pwcopy.pw_change = pw->pw_change;
550		pw = &pwcopy;
551	} else {
552		pw = NULL;
553	}
554
555#ifdef USE_PAM
556	if (pw != NULL)
557		start_pam(pw);
558#endif
559	/*
560	 * If we are not running as root, the user must have the same uid as
561	 * the server.
562	 */
563	if (getuid() != 0 && pw && pw->pw_uid != getuid())
564		packet_disconnect("Cannot change user when server not running as root.");
565
566	debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
567
568	/* If the user has no password, accept authentication immediately. */
569	if (options.password_authentication &&
570#ifdef KRB5
571	    !options.kerberos_authentication &&
572#endif /* KRB5 */
573#ifdef KRB4
574	    (!options.kerberos_authentication || options.krb4_or_local_passwd) &&
575#endif /* KRB4 */
576#ifdef USE_PAM
577	    auth_pam_password(pw, "")
578#else /* !USE_PAM */
579 	    auth_password(pw, "")
580#endif /* USE_PAM */
581		) {
582		/* Authentication with empty password succeeded. */
583		log("Login for user %s from %.100s, accepted without authentication.",
584		    user, get_remote_ipaddr());
585	} else {
586		/* Loop until the user has been authenticated or the
587		   connection is closed, do_authloop() returns only if
588		   authentication is successfull */
589		do_authloop(pw, user);
590	}
591	if (pw == NULL)
592		fatal("internal error, authentication successfull for user '%.100s'", user);
593
594	/* The user has been authenticated and accepted. */
595	packet_start(SSH_SMSG_SUCCESS);
596	packet_send();
597	packet_write_wait();
598
599	/* Perform session preparation. */
600	do_authenticated(pw);
601}
602