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