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