xref: /onnv-gate/usr/src/cmd/ssh/sshd/auth1.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3*0Sstevel@tonic-gate  *                    All rights reserved
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  * As far as I am concerned, the code I have written for this software
6*0Sstevel@tonic-gate  * can be used freely for any purpose.  Any derived versions of this
7*0Sstevel@tonic-gate  * software must be clearly marked as such, and if the derived work is
8*0Sstevel@tonic-gate  * incompatible with the protocol description in the RFC file, it must be
9*0Sstevel@tonic-gate  * called by a name other than "ssh" or "Secure Shell".
10*0Sstevel@tonic-gate  */
11*0Sstevel@tonic-gate /*
12*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
13*0Sstevel@tonic-gate  * Use is subject to license terms.
14*0Sstevel@tonic-gate  */
15*0Sstevel@tonic-gate 
16*0Sstevel@tonic-gate #include "includes.h"
17*0Sstevel@tonic-gate RCSID("$OpenBSD: auth1.c,v 1.44 2002/09/26 11:38:43 markus Exp $");
18*0Sstevel@tonic-gate 
19*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
20*0Sstevel@tonic-gate 
21*0Sstevel@tonic-gate #include "xmalloc.h"
22*0Sstevel@tonic-gate #include "rsa.h"
23*0Sstevel@tonic-gate #include "ssh1.h"
24*0Sstevel@tonic-gate #include "packet.h"
25*0Sstevel@tonic-gate #include "buffer.h"
26*0Sstevel@tonic-gate #include "mpaux.h"
27*0Sstevel@tonic-gate #include "log.h"
28*0Sstevel@tonic-gate #include "servconf.h"
29*0Sstevel@tonic-gate #include "compat.h"
30*0Sstevel@tonic-gate #include "auth.h"
31*0Sstevel@tonic-gate #include "channels.h"
32*0Sstevel@tonic-gate #include "session.h"
33*0Sstevel@tonic-gate #include "uidswap.h"
34*0Sstevel@tonic-gate #include "monitor_wrap.h"
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #ifdef HAVE_BSM
37*0Sstevel@tonic-gate #include "bsmaudit.h"
38*0Sstevel@tonic-gate extern adt_session_data_t *ah;
39*0Sstevel@tonic-gate #endif /* HAVE_BSM */
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /* import */
42*0Sstevel@tonic-gate extern ServerOptions options;
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate /*
45*0Sstevel@tonic-gate  * convert ssh auth msg type into description
46*0Sstevel@tonic-gate  */
47*0Sstevel@tonic-gate static char *
48*0Sstevel@tonic-gate get_authname(int type)
49*0Sstevel@tonic-gate {
50*0Sstevel@tonic-gate 	static char buf[1024];
51*0Sstevel@tonic-gate 	switch (type) {
52*0Sstevel@tonic-gate 	case SSH_CMSG_AUTH_PASSWORD:
53*0Sstevel@tonic-gate 		return "password";
54*0Sstevel@tonic-gate 	case SSH_CMSG_AUTH_RSA:
55*0Sstevel@tonic-gate 		return "rsa";
56*0Sstevel@tonic-gate 	case SSH_CMSG_AUTH_RHOSTS_RSA:
57*0Sstevel@tonic-gate 		return "rhosts-rsa";
58*0Sstevel@tonic-gate 	case SSH_CMSG_AUTH_RHOSTS:
59*0Sstevel@tonic-gate 		return "rhosts";
60*0Sstevel@tonic-gate 	case SSH_CMSG_AUTH_TIS:
61*0Sstevel@tonic-gate 	case SSH_CMSG_AUTH_TIS_RESPONSE:
62*0Sstevel@tonic-gate 		return "challenge-response";
63*0Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
64*0Sstevel@tonic-gate 	case SSH_CMSG_AUTH_KERBEROS:
65*0Sstevel@tonic-gate 		return "kerberos";
66*0Sstevel@tonic-gate #endif
67*0Sstevel@tonic-gate 	}
68*0Sstevel@tonic-gate 	snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
69*0Sstevel@tonic-gate 	return buf;
70*0Sstevel@tonic-gate }
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate /*
73*0Sstevel@tonic-gate  * read packets, try to authenticate the user and
74*0Sstevel@tonic-gate  * return only if authentication is successful
75*0Sstevel@tonic-gate  */
76*0Sstevel@tonic-gate static void
77*0Sstevel@tonic-gate do_authloop(Authctxt *authctxt)
78*0Sstevel@tonic-gate {
79*0Sstevel@tonic-gate 	int authenticated = 0;
80*0Sstevel@tonic-gate 	u_int bits;
81*0Sstevel@tonic-gate 	Key *client_host_key;
82*0Sstevel@tonic-gate 	BIGNUM *n;
83*0Sstevel@tonic-gate 	char *client_user, *password;
84*0Sstevel@tonic-gate 	char info[1024];
85*0Sstevel@tonic-gate 	u_int dlen;
86*0Sstevel@tonic-gate 	u_int ulen;
87*0Sstevel@tonic-gate 	int type = 0;
88*0Sstevel@tonic-gate 	struct passwd *pw = authctxt->pw;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 	debug("Attempting authentication for %s%.100s.",
91*0Sstevel@tonic-gate 	    authctxt->valid ? "" : "illegal user ", authctxt->user);
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	/* If the user has no password, accept authentication immediately. */
94*0Sstevel@tonic-gate 	if (options.password_authentication &&
95*0Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
96*0Sstevel@tonic-gate 	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
97*0Sstevel@tonic-gate #endif
98*0Sstevel@tonic-gate 	    PRIVSEP(auth_password(authctxt, ""))) {
99*0Sstevel@tonic-gate 		auth_log(authctxt, 1, "without authentication", "");
100*0Sstevel@tonic-gate 		return;
101*0Sstevel@tonic-gate 	}
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 	/* Indicate that authentication is needed. */
104*0Sstevel@tonic-gate 	packet_start(SSH_SMSG_FAILURE);
105*0Sstevel@tonic-gate 	packet_send();
106*0Sstevel@tonic-gate 	packet_write_wait();
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	client_user = NULL;
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 	for ( ;; ) {
111*0Sstevel@tonic-gate 		/* default to fail */
112*0Sstevel@tonic-gate 		authenticated = 0;
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 		info[0] = '\0';
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 		/* Get a packet from the client. */
117*0Sstevel@tonic-gate 		authctxt->v1_auth_type = type = packet_read();
118*0Sstevel@tonic-gate 		authctxt->v1_auth_name = get_authname(type);
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 		authctxt->attempt++;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 		/* Process the packet. */
123*0Sstevel@tonic-gate 		switch (type) {
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
126*0Sstevel@tonic-gate 		case SSH_CMSG_AUTH_KERBEROS:
127*0Sstevel@tonic-gate 			if (!options.kerberos_authentication) {
128*0Sstevel@tonic-gate 				verbose("Kerberos authentication disabled.");
129*0Sstevel@tonic-gate 			} else {
130*0Sstevel@tonic-gate 				char *kdata = packet_get_string(&dlen);
131*0Sstevel@tonic-gate 				packet_check_eom();
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 				if (kdata[0] == 4) { /* KRB_PROT_VERSION */
134*0Sstevel@tonic-gate #ifdef KRB4
135*0Sstevel@tonic-gate 					KTEXT_ST tkt, reply;
136*0Sstevel@tonic-gate 					tkt.length = dlen;
137*0Sstevel@tonic-gate 					if (tkt.length < MAX_KTXT_LEN)
138*0Sstevel@tonic-gate 						memcpy(tkt.dat, kdata, tkt.length);
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 					if (PRIVSEP(auth_krb4(authctxt, &tkt,
141*0Sstevel@tonic-gate 					    &client_user, &reply))) {
142*0Sstevel@tonic-gate 						authenticated = 1;
143*0Sstevel@tonic-gate 						snprintf(info, sizeof(info),
144*0Sstevel@tonic-gate 						    " tktuser %.100s",
145*0Sstevel@tonic-gate 						    client_user);
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 						packet_start(
148*0Sstevel@tonic-gate 						    SSH_SMSG_AUTH_KERBEROS_RESPONSE);
149*0Sstevel@tonic-gate 						packet_put_string((char *)
150*0Sstevel@tonic-gate 						    reply.dat, reply.length);
151*0Sstevel@tonic-gate 						packet_send();
152*0Sstevel@tonic-gate 						packet_write_wait();
153*0Sstevel@tonic-gate 					}
154*0Sstevel@tonic-gate #endif /* KRB4 */
155*0Sstevel@tonic-gate 				} else {
156*0Sstevel@tonic-gate #ifdef KRB5
157*0Sstevel@tonic-gate 					krb5_data tkt, reply;
158*0Sstevel@tonic-gate 					tkt.length = dlen;
159*0Sstevel@tonic-gate 					tkt.data = kdata;
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 					if (PRIVSEP(auth_krb5(authctxt, &tkt,
162*0Sstevel@tonic-gate 					    &client_user, &reply))) {
163*0Sstevel@tonic-gate 						authenticated = 1;
164*0Sstevel@tonic-gate 						snprintf(info, sizeof(info),
165*0Sstevel@tonic-gate 						    " tktuser %.100s",
166*0Sstevel@tonic-gate 						    client_user);
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate  						/* Send response to client */
169*0Sstevel@tonic-gate  						packet_start(
170*0Sstevel@tonic-gate 						    SSH_SMSG_AUTH_KERBEROS_RESPONSE);
171*0Sstevel@tonic-gate  						packet_put_string((char *)
172*0Sstevel@tonic-gate 						    reply.data, reply.length);
173*0Sstevel@tonic-gate  						packet_send();
174*0Sstevel@tonic-gate  						packet_write_wait();
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate  						if (reply.length)
177*0Sstevel@tonic-gate  							xfree(reply.data);
178*0Sstevel@tonic-gate 					}
179*0Sstevel@tonic-gate #endif /* KRB5 */
180*0Sstevel@tonic-gate 				}
181*0Sstevel@tonic-gate 				xfree(kdata);
182*0Sstevel@tonic-gate 			}
183*0Sstevel@tonic-gate 			break;
184*0Sstevel@tonic-gate #endif /* KRB4 || KRB5 */
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
187*0Sstevel@tonic-gate 			/* XXX - punt on backward compatibility here. */
188*0Sstevel@tonic-gate 		case SSH_CMSG_HAVE_KERBEROS_TGT:
189*0Sstevel@tonic-gate 			packet_send_debug("Kerberos TGT passing disabled before authentication.");
190*0Sstevel@tonic-gate 			break;
191*0Sstevel@tonic-gate #ifdef AFS
192*0Sstevel@tonic-gate 		case SSH_CMSG_HAVE_AFS_TOKEN:
193*0Sstevel@tonic-gate 			packet_send_debug("AFS token passing disabled before authentication.");
194*0Sstevel@tonic-gate 			break;
195*0Sstevel@tonic-gate #endif /* AFS */
196*0Sstevel@tonic-gate #endif /* AFS || KRB5 */
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 		case SSH_CMSG_AUTH_RHOSTS:
199*0Sstevel@tonic-gate 			if (!options.rhosts_authentication) {
200*0Sstevel@tonic-gate 				verbose("Rhosts authentication disabled.");
201*0Sstevel@tonic-gate 				break;
202*0Sstevel@tonic-gate 			}
203*0Sstevel@tonic-gate 			/*
204*0Sstevel@tonic-gate 			 * Get client user name.  Note that we just have to
205*0Sstevel@tonic-gate 			 * trust the client; this is one reason why rhosts
206*0Sstevel@tonic-gate 			 * authentication is insecure. (Another is
207*0Sstevel@tonic-gate 			 * IP-spoofing on a local network.)
208*0Sstevel@tonic-gate 			 */
209*0Sstevel@tonic-gate 			client_user = packet_get_string(&ulen);
210*0Sstevel@tonic-gate 			packet_check_eom();
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 			/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
213*0Sstevel@tonic-gate 			authenticated = auth_rhosts(pw, client_user);
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 			snprintf(info, sizeof info, " ruser %.100s", client_user);
216*0Sstevel@tonic-gate 			break;
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 		case SSH_CMSG_AUTH_RHOSTS_RSA:
219*0Sstevel@tonic-gate 			if (!options.rhosts_rsa_authentication) {
220*0Sstevel@tonic-gate 				verbose("Rhosts with RSA authentication disabled.");
221*0Sstevel@tonic-gate 				break;
222*0Sstevel@tonic-gate 			}
223*0Sstevel@tonic-gate 			/*
224*0Sstevel@tonic-gate 			 * Get client user name.  Note that we just have to
225*0Sstevel@tonic-gate 			 * trust the client; root on the client machine can
226*0Sstevel@tonic-gate 			 * claim to be any user.
227*0Sstevel@tonic-gate 			 */
228*0Sstevel@tonic-gate 			client_user = packet_get_string(&ulen);
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate 			/* Get the client host key. */
231*0Sstevel@tonic-gate 			client_host_key = key_new(KEY_RSA1);
232*0Sstevel@tonic-gate 			bits = packet_get_int();
233*0Sstevel@tonic-gate 			packet_get_bignum(client_host_key->rsa->e);
234*0Sstevel@tonic-gate 			packet_get_bignum(client_host_key->rsa->n);
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 			if (bits != BN_num_bits(client_host_key->rsa->n))
237*0Sstevel@tonic-gate 				verbose("Warning: keysize mismatch for client_host_key: "
238*0Sstevel@tonic-gate 				    "actual %d, announced %d",
239*0Sstevel@tonic-gate 				    BN_num_bits(client_host_key->rsa->n), bits);
240*0Sstevel@tonic-gate 			packet_check_eom();
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 			authenticated = auth_rhosts_rsa(pw, client_user,
243*0Sstevel@tonic-gate 			    client_host_key);
244*0Sstevel@tonic-gate 			key_free(client_host_key);
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 			snprintf(info, sizeof info, " ruser %.100s", client_user);
247*0Sstevel@tonic-gate 			break;
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 		case SSH_CMSG_AUTH_RSA:
250*0Sstevel@tonic-gate 			if (!options.rsa_authentication) {
251*0Sstevel@tonic-gate 				verbose("RSA authentication disabled.");
252*0Sstevel@tonic-gate 				break;
253*0Sstevel@tonic-gate 			}
254*0Sstevel@tonic-gate 			/* RSA authentication requested. */
255*0Sstevel@tonic-gate 			if ((n = BN_new()) == NULL)
256*0Sstevel@tonic-gate 				fatal("do_authloop: BN_new failed");
257*0Sstevel@tonic-gate 			packet_get_bignum(n);
258*0Sstevel@tonic-gate 			packet_check_eom();
259*0Sstevel@tonic-gate 			authenticated = auth_rsa(pw, n);
260*0Sstevel@tonic-gate 			BN_clear_free(n);
261*0Sstevel@tonic-gate 			break;
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 		case SSH_CMSG_AUTH_PASSWORD:
264*0Sstevel@tonic-gate 			authctxt->init_attempt++;
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 			if (!options.password_authentication) {
267*0Sstevel@tonic-gate 				verbose("Password authentication disabled.");
268*0Sstevel@tonic-gate 				break;
269*0Sstevel@tonic-gate 			}
270*0Sstevel@tonic-gate 			/*
271*0Sstevel@tonic-gate 			 * Read user password.  It is in plain text, but was
272*0Sstevel@tonic-gate 			 * transmitted over the encrypted channel so it is
273*0Sstevel@tonic-gate 			 * not visible to an outside observer.
274*0Sstevel@tonic-gate 			 */
275*0Sstevel@tonic-gate 			password = packet_get_string(&dlen);
276*0Sstevel@tonic-gate 			packet_check_eom();
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 			/* Try authentication with the password. */
279*0Sstevel@tonic-gate 			if (authctxt->init_failures <
280*0Sstevel@tonic-gate 				options.max_init_auth_tries)
281*0Sstevel@tonic-gate 				authenticated =
282*0Sstevel@tonic-gate 				    PRIVSEP(auth_password(authctxt,
283*0Sstevel@tonic-gate 						password));
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 			memset(password, 0, strlen(password));
286*0Sstevel@tonic-gate 			xfree(password);
287*0Sstevel@tonic-gate 			break;
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate 		case SSH_CMSG_AUTH_TIS:
290*0Sstevel@tonic-gate 			debug("rcvd SSH_CMSG_AUTH_TIS");
291*0Sstevel@tonic-gate 			if (options.challenge_response_authentication == 1) {
292*0Sstevel@tonic-gate 				char *challenge = get_challenge(authctxt);
293*0Sstevel@tonic-gate 				if (challenge != NULL) {
294*0Sstevel@tonic-gate 					debug("sending challenge '%s'", challenge);
295*0Sstevel@tonic-gate 					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
296*0Sstevel@tonic-gate 					packet_put_cstring(challenge);
297*0Sstevel@tonic-gate 					xfree(challenge);
298*0Sstevel@tonic-gate 					packet_send();
299*0Sstevel@tonic-gate 					packet_write_wait();
300*0Sstevel@tonic-gate 					continue;
301*0Sstevel@tonic-gate 				}
302*0Sstevel@tonic-gate 			}
303*0Sstevel@tonic-gate 			break;
304*0Sstevel@tonic-gate 		case SSH_CMSG_AUTH_TIS_RESPONSE:
305*0Sstevel@tonic-gate 			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
306*0Sstevel@tonic-gate 			if (options.challenge_response_authentication == 1) {
307*0Sstevel@tonic-gate 				char *response = packet_get_string(&dlen);
308*0Sstevel@tonic-gate 				debug("got response '%s'", response);
309*0Sstevel@tonic-gate 				packet_check_eom();
310*0Sstevel@tonic-gate 				authenticated = verify_response(authctxt, response);
311*0Sstevel@tonic-gate 				memset(response, 'r', dlen);
312*0Sstevel@tonic-gate 				xfree(response);
313*0Sstevel@tonic-gate 			}
314*0Sstevel@tonic-gate 			break;
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 		default:
317*0Sstevel@tonic-gate 			/*
318*0Sstevel@tonic-gate 			 * Any unknown messages will be ignored (and failure
319*0Sstevel@tonic-gate 			 * returned) during authentication.
320*0Sstevel@tonic-gate 			 */
321*0Sstevel@tonic-gate 			log("Unknown message during authentication: type %d", type);
322*0Sstevel@tonic-gate 			break;
323*0Sstevel@tonic-gate 		}
324*0Sstevel@tonic-gate #ifdef BSD_AUTH
325*0Sstevel@tonic-gate 		if (authctxt->as) {
326*0Sstevel@tonic-gate 			auth_close(authctxt->as);
327*0Sstevel@tonic-gate 			authctxt->as = NULL;
328*0Sstevel@tonic-gate 		}
329*0Sstevel@tonic-gate #endif
330*0Sstevel@tonic-gate 		if (!authctxt->valid && authenticated) {
331*0Sstevel@tonic-gate 			authenticated = 0;
332*0Sstevel@tonic-gate 			log("Ignoring authenticated invalid user %s",
333*0Sstevel@tonic-gate 			    authctxt->user);
334*0Sstevel@tonic-gate 		}
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate #ifdef _UNICOS
337*0Sstevel@tonic-gate 		if (type == SSH_CMSG_AUTH_PASSWORD && !authenticated)
338*0Sstevel@tonic-gate 			cray_login_failure(authctxt->user, IA_UDBERR);
339*0Sstevel@tonic-gate 		if (authenticated && cray_access_denied(authctxt->user)) {
340*0Sstevel@tonic-gate 			authenticated = 0;
341*0Sstevel@tonic-gate 			fatal("Access denied for user %s.",authctxt->user);
342*0Sstevel@tonic-gate 		}
343*0Sstevel@tonic-gate #endif /* _UNICOS */
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate #ifdef HAVE_CYGWIN
346*0Sstevel@tonic-gate 		if (authenticated &&
347*0Sstevel@tonic-gate 		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) {
348*0Sstevel@tonic-gate 			packet_disconnect("Authentication rejected for uid %d.",
349*0Sstevel@tonic-gate 			pw == NULL ? -1 : pw->pw_uid);
350*0Sstevel@tonic-gate 			authenticated = 0;
351*0Sstevel@tonic-gate 		}
352*0Sstevel@tonic-gate #else
353*0Sstevel@tonic-gate 		/* Special handling for root */
354*0Sstevel@tonic-gate 		if (!use_privsep &&
355*0Sstevel@tonic-gate 		    authenticated && authctxt->pw->pw_uid == 0 &&
356*0Sstevel@tonic-gate 		    !auth_root_allowed(get_authname(type)))
357*0Sstevel@tonic-gate 			authenticated = 0;
358*0Sstevel@tonic-gate #endif
359*0Sstevel@tonic-gate #ifdef USE_PAM
360*0Sstevel@tonic-gate 		/* XXX PAM and PRIVSEP don't mix */
361*0Sstevel@tonic-gate 		if (use_privsep && authenticated)
362*0Sstevel@tonic-gate 			fatal("Privsep is not supported");
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 		if (authenticated && type != SSH_CMSG_AUTH_PASSWORD)
365*0Sstevel@tonic-gate 			authenticated = do_pam_non_initial_userauth(authctxt);
366*0Sstevel@tonic-gate 		else if (authenticated && !AUTHPAM_DONE(authctxt))
367*0Sstevel@tonic-gate 			authenticated = 0;
368*0Sstevel@tonic-gate 
369*0Sstevel@tonic-gate 		if (!authenticated)
370*0Sstevel@tonic-gate 			authctxt->pam_retval = AUTHPAM_ERROR(authctxt,
371*0Sstevel@tonic-gate 				PAM_PERM_DENIED);
372*0Sstevel@tonic-gate #endif /* USE_PAM */
373*0Sstevel@tonic-gate 
374*0Sstevel@tonic-gate 		/* Log before sending the reply */
375*0Sstevel@tonic-gate 		auth_log(authctxt, authenticated, get_authname(type), info);
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 		if (client_user != NULL) {
378*0Sstevel@tonic-gate 			xfree(client_user);
379*0Sstevel@tonic-gate 			client_user = NULL;
380*0Sstevel@tonic-gate 		}
381*0Sstevel@tonic-gate 
382*0Sstevel@tonic-gate 		if (authenticated)
383*0Sstevel@tonic-gate 			return;
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate 		if (type == SSH_CMSG_AUTH_PASSWORD)
386*0Sstevel@tonic-gate 			authctxt->init_failures++;
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 		if (authctxt->failures++ > options.max_auth_tries) {
389*0Sstevel@tonic-gate #ifdef HAVE_BSM
390*0Sstevel@tonic-gate 			fatal_remove_cleanup(audit_failed_login_cleanup,
391*0Sstevel@tonic-gate 				authctxt);
392*0Sstevel@tonic-gate 			audit_sshd_login_failure(&ah, PAM_MAXTRIES);
393*0Sstevel@tonic-gate #endif /* HAVE_BSM */
394*0Sstevel@tonic-gate 			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
395*0Sstevel@tonic-gate 		}
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate 		packet_start(SSH_SMSG_FAILURE);
398*0Sstevel@tonic-gate 		packet_send();
399*0Sstevel@tonic-gate 		packet_write_wait();
400*0Sstevel@tonic-gate 	}
401*0Sstevel@tonic-gate }
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate /*
404*0Sstevel@tonic-gate  * Performs authentication of an incoming connection.  Session key has already
405*0Sstevel@tonic-gate  * been exchanged and encryption is enabled.
406*0Sstevel@tonic-gate  */
407*0Sstevel@tonic-gate Authctxt *
408*0Sstevel@tonic-gate do_authentication(void)
409*0Sstevel@tonic-gate {
410*0Sstevel@tonic-gate 	Authctxt *authctxt;
411*0Sstevel@tonic-gate 	u_int ulen;
412*0Sstevel@tonic-gate 	char *user, *style = NULL;
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate 	/* Get the name of the user that we wish to log in as. */
415*0Sstevel@tonic-gate 	packet_read_expect(SSH_CMSG_USER);
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 	/* Get the user name. */
418*0Sstevel@tonic-gate 	user = packet_get_string(&ulen);
419*0Sstevel@tonic-gate 	packet_check_eom();
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	if ((style = strchr(user, ':')) != NULL)
422*0Sstevel@tonic-gate 		*style++ = '\0';
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate #ifdef KRB5
425*0Sstevel@tonic-gate 	/* XXX - SSH.com Kerberos v5 braindeath. */
426*0Sstevel@tonic-gate 	if ((datafellows & SSH_BUG_K5USER) &&
427*0Sstevel@tonic-gate 	    options.kerberos_authentication) {
428*0Sstevel@tonic-gate 		char *p;
429*0Sstevel@tonic-gate 		if ((p = strchr(user, '@')) != NULL)
430*0Sstevel@tonic-gate 			*p = '\0';
431*0Sstevel@tonic-gate 	}
432*0Sstevel@tonic-gate #endif
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate 	authctxt = authctxt_new();
435*0Sstevel@tonic-gate 	authctxt->user = user;
436*0Sstevel@tonic-gate 	authctxt->style = style;
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate #ifdef HAVE_BSM
439*0Sstevel@tonic-gate 	fatal_add_cleanup(audit_failed_login_cleanup, authctxt);
440*0Sstevel@tonic-gate #endif /* HAVE_BSM */
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	/* Verify that the user is a valid user. */
443*0Sstevel@tonic-gate 	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) {
444*0Sstevel@tonic-gate 		authctxt->valid = 1;
445*0Sstevel@tonic-gate 	} else {
446*0Sstevel@tonic-gate 		authctxt->valid = 0;
447*0Sstevel@tonic-gate 		debug("do_authentication: illegal user %s", user);
448*0Sstevel@tonic-gate 	}
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	setproctitle("%s%s", authctxt->pw ? user : "unknown",
451*0Sstevel@tonic-gate 	    use_privsep ? " [net]" : "");
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate #if 0
454*0Sstevel@tonic-gate #ifdef USE_PAM
455*0Sstevel@tonic-gate 	PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user));
456*0Sstevel@tonic-gate #endif
457*0Sstevel@tonic-gate #endif
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 	/*
460*0Sstevel@tonic-gate 	 * If we are not running as root, the user must have the same uid as
461*0Sstevel@tonic-gate 	 * the server. (Unless you are running Windows)
462*0Sstevel@tonic-gate 	 */
463*0Sstevel@tonic-gate #ifndef HAVE_CYGWIN
464*0Sstevel@tonic-gate 	if (!use_privsep && getuid() != 0 && authctxt->pw &&
465*0Sstevel@tonic-gate 	    authctxt->pw->pw_uid != getuid())
466*0Sstevel@tonic-gate 		packet_disconnect("Cannot change user when server not running as root.");
467*0Sstevel@tonic-gate #endif
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate 	/*
470*0Sstevel@tonic-gate 	 * Loop until the user has been authenticated or the connection is
471*0Sstevel@tonic-gate 	 * closed, do_authloop() returns only if authentication is successful
472*0Sstevel@tonic-gate 	 */
473*0Sstevel@tonic-gate 	do_authloop(authctxt);
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 	/* The user has been authenticated and accepted. */
476*0Sstevel@tonic-gate 	packet_start(SSH_SMSG_SUCCESS);
477*0Sstevel@tonic-gate 	packet_send();
478*0Sstevel@tonic-gate 	packet_write_wait();
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	return (authctxt);
481*0Sstevel@tonic-gate }
482