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