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