1 /* $OpenBSD: auth1.c,v 1.73 2008/07/04 23:30:16 djm Exp $ */
2 /*
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  *
6  * As far as I am concerned, the code I have written for this software
7  * can be used freely for any purpose.  Any derived versions of this
8  * software must be clearly marked as such, and if the derived work is
9  * incompatible with the protocol description in the RFC file, it must be
10  * called by a name other than "ssh" or "Secure Shell".
11  */
12 
13 #include <sys/types.h>
14 #include <sys/queue.h>
15 
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <pwd.h>
20 
21 #include "xmalloc.h"
22 #include "rsa.h"
23 #include "ssh1.h"
24 #include "packet.h"
25 #include "buffer.h"
26 #include "log.h"
27 #include "servconf.h"
28 #include "compat.h"
29 #include "key.h"
30 #include "hostfile.h"
31 #include "auth.h"
32 #include "channels.h"
33 #include "session.h"
34 #include "uidswap.h"
35 #include "monitor_wrap.h"
36 
37 __RCSID("$MirOS: src/usr.bin/ssh/auth1.c,v 1.10 2009/10/04 14:29:01 tg Exp $");
38 
39 /* import */
40 extern ServerOptions options;
41 
42 static int auth1_process_password(Authctxt *, char *, size_t);
43 static int auth1_process_rsa(Authctxt *, char *, size_t);
44 static int auth1_process_rhosts_rsa(Authctxt *, char *, size_t);
45 static int auth1_process_tis_challenge(Authctxt *, char *, size_t);
46 static int auth1_process_tis_response(Authctxt *, char *, size_t);
47 
48 struct AuthMethod1 {
49 	int type;
50 	const char *name;
51 	int *enabled;
52 	int (*method)(Authctxt *, char *, size_t);
53 };
54 
55 const struct AuthMethod1 auth1_methods[] = {
56 	{
57 		SSH_CMSG_AUTH_PASSWORD, "password",
58 		&options.password_authentication, auth1_process_password
59 	},
60 	{
61 		SSH_CMSG_AUTH_RSA, "rsa",
62 		&options.rsa_authentication, auth1_process_rsa
63 	},
64 	{
65 		SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
66 		&options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
67 	},
68 	{
69 		SSH_CMSG_AUTH_TIS, "challenge-response",
70 		&options.challenge_response_authentication,
71 		auth1_process_tis_challenge
72 	},
73 	{
74 		SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
75 		&options.challenge_response_authentication,
76 		auth1_process_tis_response
77 	},
78 	{ -1, NULL, NULL, NULL}
79 };
80 
81 static const struct AuthMethod1
lookup_authmethod1(int type)82 *lookup_authmethod1(int type)
83 {
84 	int i;
85 
86 	for (i = 0; auth1_methods[i].name != NULL; i++)
87 		if (auth1_methods[i].type == type)
88 			return (&(auth1_methods[i]));
89 
90 	return (NULL);
91 }
92 
93 static const char *
get_authname(int type)94 get_authname(int type)
95 {
96 	const struct AuthMethod1 *a;
97 	static char buf[64];
98 
99 	if ((a = lookup_authmethod1(type)) != NULL)
100 		return (a->name);
101 	snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
102 	return (buf);
103 }
104 
105 /*ARGSUSED*/
106 static int
auth1_process_password(Authctxt * authctxt,char * info,size_t infolen)107 auth1_process_password(Authctxt *authctxt, char *info, size_t infolen)
108 {
109 	int authenticated = 0;
110 	char *password;
111 	u_int dlen;
112 
113 	/*
114 	 * Read user password.  It is in plain text, but was
115 	 * transmitted over the encrypted channel so it is
116 	 * not visible to an outside observer.
117 	 */
118 	password = packet_get_string(&dlen);
119 	packet_check_eom();
120 
121 	/* Try authentication with the password. */
122 	authenticated = PRIVSEP(auth_password(authctxt, password));
123 
124 	memset(password, 0, dlen);
125 	xfree(password);
126 
127 	return (authenticated);
128 }
129 
130 /*ARGSUSED*/
131 static int
auth1_process_rsa(Authctxt * authctxt,char * info,size_t infolen)132 auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen)
133 {
134 	int authenticated = 0;
135 	BIGNUM *n;
136 
137 	/* RSA authentication requested. */
138 	if ((n = BN_new()) == NULL)
139 		fatal("do_authloop: BN_new failed");
140 	packet_get_bignum(n);
141 	packet_check_eom();
142 	authenticated = auth_rsa(authctxt, n);
143 	BN_clear_free(n);
144 
145 	return (authenticated);
146 }
147 
148 /*ARGSUSED*/
149 static int
auth1_process_rhosts_rsa(Authctxt * authctxt,char * info,size_t infolen)150 auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
151 {
152 	int keybits, authenticated = 0;
153 	u_int bits;
154 	char *client_user;
155 	Key *client_host_key;
156 	u_int ulen;
157 
158 	/*
159 	 * Get client user name.  Note that we just have to
160 	 * trust the client; root on the client machine can
161 	 * claim to be any user.
162 	 */
163 	client_user = packet_get_string(&ulen);
164 
165 	/* Get the client host key. */
166 	client_host_key = key_new(KEY_RSA1);
167 	bits = packet_get_int();
168 	packet_get_bignum(client_host_key->rsa->e);
169 	packet_get_bignum(client_host_key->rsa->n);
170 
171 	keybits = BN_num_bits(client_host_key->rsa->n);
172 	if (keybits < 0 || bits != (u_int)keybits) {
173 		verbose("Warning: keysize mismatch for client_host_key: "
174 		    "actual %d, announced %d",
175 		    BN_num_bits(client_host_key->rsa->n), bits);
176 	}
177 	packet_check_eom();
178 
179 	authenticated = auth_rhosts_rsa(authctxt, client_user,
180 	    client_host_key);
181 	key_free(client_host_key);
182 
183 	snprintf(info, infolen, " ruser %.100s", client_user);
184 	xfree(client_user);
185 
186 	return (authenticated);
187 }
188 
189 /*ARGSUSED*/
190 static int
auth1_process_tis_challenge(Authctxt * authctxt,char * info,size_t infolen)191 auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
192 {
193 	char *challenge;
194 
195 	if ((challenge = get_challenge(authctxt)) == NULL)
196 		return (0);
197 
198 	debug("sending challenge '%s'", challenge);
199 	packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
200 	packet_put_cstring(challenge);
201 	xfree(challenge);
202 	packet_send();
203 	packet_write_wait();
204 
205 	return (-1);
206 }
207 
208 /*ARGSUSED*/
209 static int
auth1_process_tis_response(Authctxt * authctxt,char * info,size_t infolen)210 auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
211 {
212 	int authenticated = 0;
213 	char *response;
214 	u_int dlen;
215 
216 	response = packet_get_string(&dlen);
217 	packet_check_eom();
218 	authenticated = verify_response(authctxt, response);
219 	memset(response, 'r', dlen);
220 	xfree(response);
221 
222 	return (authenticated);
223 }
224 
225 /*
226  * read packets, try to authenticate the user and
227  * return only if authentication is successful
228  */
229 static void
do_authloop(Authctxt * authctxt)230 do_authloop(Authctxt *authctxt)
231 {
232 	int authenticated = 0;
233 	char info[1024];
234 	int type = 0;
235 	const struct AuthMethod1 *meth;
236 
237 	debug("Attempting authentication for %s%.100s.",
238 	    authctxt->valid ? "" : "invalid user ", authctxt->user);
239 
240 	/* If the user has no password, accept authentication immediately. */
241 	if (options.password_authentication &&
242 	    PRIVSEP(auth_password(authctxt, (char *)""))) {
243 		auth_log(authctxt, 1, "without authentication", "");
244 		return;
245 	}
246 
247 	/* Indicate that authentication is needed. */
248 	packet_start(SSH_SMSG_FAILURE);
249 	packet_send();
250 	packet_write_wait();
251 
252 	for (;;) {
253 		/* default to fail */
254 		authenticated = 0;
255 
256 		info[0] = '\0';
257 
258 		/* Get a packet from the client. */
259 		type = packet_read();
260 		if (authctxt->failures >= options.max_authtries)
261 			goto skip;
262 		if ((meth = lookup_authmethod1(type)) == NULL) {
263 			logit("Unknown message during authentication: "
264 			    "type %d", type);
265 			goto skip;
266 		}
267 
268 		if (!*(meth->enabled)) {
269 			verbose("%s authentication disabled.", meth->name);
270 			goto skip;
271 		}
272 
273 		authenticated = meth->method(authctxt, info, sizeof(info));
274 		if (authenticated == -1)
275 			continue; /* "postponed" */
276 
277 #ifdef BSD_AUTH
278 		if (authctxt->as) {
279 			auth_close(authctxt->as);
280 			authctxt->as = NULL;
281 		}
282 #endif
283 		if (!authctxt->valid && authenticated)
284 			fatal("INTERNAL ERROR: authenticated invalid user %s",
285 			    authctxt->user);
286 
287 		/* Special handling for root */
288 		if (authenticated && authctxt->pw->pw_uid == 0 &&
289 		    !auth_root_allowed(meth->name))
290 			authenticated = 0;
291 
292  skip:
293 		/* Log before sending the reply */
294 		auth_log(authctxt, authenticated, get_authname(type), info);
295 
296 		if (authenticated)
297 			return;
298 
299 		if (++authctxt->failures >= options.max_authtries)
300 			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
301 
302 		packet_start(SSH_SMSG_FAILURE);
303 		packet_send();
304 		packet_write_wait();
305 	}
306 }
307 
308 /*
309  * Performs authentication of an incoming connection.  Session key has already
310  * been exchanged and encryption is enabled.
311  */
312 void
do_authentication(Authctxt * authctxt)313 do_authentication(Authctxt *authctxt)
314 {
315 	u_int ulen;
316 	char *user, *style = NULL;
317 
318 	/* Get the name of the user that we wish to log in as. */
319 	packet_read_expect(SSH_CMSG_USER);
320 
321 	/* Get the user name. */
322 	user = packet_get_string(&ulen);
323 	packet_check_eom();
324 
325 	if ((style = strchr(user, ':')) != NULL)
326 		*style++ = '\0';
327 
328 	authctxt->user = user;
329 	authctxt->style = style;
330 
331 	/* Verify that the user is a valid user. */
332 	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
333 		authctxt->valid = 1;
334 	else {
335 		debug("do_authentication: invalid user %s", user);
336 		authctxt->pw = fakepw();
337 	}
338 
339 	setproctitle("%s%s", authctxt->valid ? user : "unknown",
340 	    use_privsep ? " [net]" : "");
341 
342 	/*
343 	 * If we are not running as root, the user must have the same uid as
344 	 * the server.
345 	 */
346 	if (!use_privsep && getuid() != 0 && authctxt->pw &&
347 	    authctxt->pw->pw_uid != getuid())
348 		packet_disconnect("Cannot change user when server not running as root.");
349 
350 	/*
351 	 * Loop until the user has been authenticated or the connection is
352 	 * closed, do_authloop() returns only if authentication is successful
353 	 */
354 	do_authloop(authctxt);
355 
356 	/* The user has been authenticated and accepted. */
357 	packet_start(SSH_SMSG_SUCCESS);
358 	packet_send();
359 	packet_write_wait();
360 }
361