blob: 3e7efcb2a64b1a58b6638a30727537a0b5a46d12 [file] [log] [blame]
Damien Millereba71ba2000-04-29 23:57:08 +10001/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 * All rights reserved
4 */
5
6#include "includes.h"
Damien Millerbd483e72000-04-30 10:00:53 +10007RCSID("$OpenBSD: auth1.c,v 1.2 2000/04/29 18:11:52 markus Exp $");
Damien Millereba71ba2000-04-29 23:57:08 +10008
9#include "xmalloc.h"
10#include "rsa.h"
11#include "ssh.h"
12#include "packet.h"
13#include "buffer.h"
14#include "cipher.h"
15#include "mpaux.h"
16#include "servconf.h"
17#include "compat.h"
18#include "auth.h"
19#include "session.h"
20
21/* import */
22extern ServerOptions options;
23extern char *forced_command;
24
25/*
26 * convert ssh auth msg type into description
27 */
28char *
29get_authname(int type)
30{
31 static char buf[1024];
32 switch (type) {
33 case SSH_CMSG_AUTH_PASSWORD:
34 return "password";
35 case SSH_CMSG_AUTH_RSA:
36 return "rsa";
37 case SSH_CMSG_AUTH_RHOSTS_RSA:
38 return "rhosts-rsa";
39 case SSH_CMSG_AUTH_RHOSTS:
40 return "rhosts";
41#ifdef KRB4
42 case SSH_CMSG_AUTH_KERBEROS:
43 return "kerberos";
44#endif
45#ifdef SKEY
46 case SSH_CMSG_AUTH_TIS_RESPONSE:
47 return "s/key";
48#endif
49 }
50 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
51 return buf;
52}
53
54/*
55 * The user does not exist or access is denied,
56 * but fake indication that authentication is needed.
57 */
58void
59do_fake_authloop1(char *user)
60{
61 int attempt = 0;
62
63 log("Faking authloop for illegal user %.200s from %.200s port %d",
64 user,
65 get_remote_ipaddr(),
66 get_remote_port());
67
68#ifdef WITH_AIXAUTHENTICATE
Damien Millerd2c208a2000-05-17 22:00:02 +100069 loginfailed(user,get_canonical_hostname(),"ssh");
Damien Millereba71ba2000-04-29 23:57:08 +100070#endif /* WITH_AIXAUTHENTICATE */
71
72 /* Indicate that authentication is needed. */
73 packet_start(SSH_SMSG_FAILURE);
74 packet_send();
75 packet_write_wait();
76
77 /*
78 * Keep reading packets, and always respond with a failure. This is
79 * to avoid disclosing whether such a user really exists.
80 */
81 for (attempt = 1;; attempt++) {
82 /* Read a packet. This will not return if the client disconnects. */
83 int plen;
84#ifndef SKEY
85 (void)packet_read(&plen);
86#else /* SKEY */
87 int type = packet_read(&plen);
88 unsigned int dlen;
89 char *password, *skeyinfo;
90 password = NULL;
91 /* Try to send a fake s/key challenge. */
92 if (options.skey_authentication == 1 &&
93 (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
94 if (type == SSH_CMSG_AUTH_TIS) {
95 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
96 packet_put_string(skeyinfo, strlen(skeyinfo));
97 packet_send();
98 packet_write_wait();
99 continue;
100 } else if (type == SSH_CMSG_AUTH_PASSWORD &&
101 options.password_authentication &&
102 (password = packet_get_string(&dlen)) != NULL &&
103 dlen == 5 &&
104 strncasecmp(password, "s/key", 5) == 0 ) {
105 packet_send_debug(skeyinfo);
106 }
107 }
108 if (password != NULL)
109 xfree(password);
110#endif
111 if (attempt > AUTH_FAIL_MAX)
112 packet_disconnect(AUTH_FAIL_MSG, user);
113
114 /*
115 * Send failure. This should be indistinguishable from a
116 * failed authentication.
117 */
118 packet_start(SSH_SMSG_FAILURE);
119 packet_send();
120 packet_write_wait();
121 }
122 /* NOTREACHED */
123 abort();
124}
125
126/*
127 * read packets and try to authenticate local user *pw.
128 * return if authentication is successfull
129 */
130void
131do_authloop(struct passwd * pw)
132{
133 int attempt = 0;
134 unsigned int bits;
135 RSA *client_host_key;
136 BIGNUM *n;
137 char *client_user = NULL, *password = NULL;
138 char user[1024];
139 unsigned int dlen;
140 int plen, nlen, elen;
141 unsigned int ulen;
142 int type = 0;
143 void (*authlog) (const char *fmt,...) = verbose;
144
145 /* Indicate that authentication is needed. */
146 packet_start(SSH_SMSG_FAILURE);
147 packet_send();
148 packet_write_wait();
149
150 for (attempt = 1;; attempt++) {
151 int authenticated = 0;
152 strlcpy(user, "", sizeof user);
153
154 /* Get a packet from the client. */
155 type = packet_read(&plen);
156
157 /* Process the packet. */
158 switch (type) {
159#ifdef AFS
160 case SSH_CMSG_HAVE_KERBEROS_TGT:
161 if (!options.kerberos_tgt_passing) {
162 /* packet_get_all(); */
163 verbose("Kerberos tgt passing disabled.");
164 break;
165 } else {
166 /* Accept Kerberos tgt. */
167 char *tgt = packet_get_string(&dlen);
168 packet_integrity_check(plen, 4 + dlen, type);
169 if (!auth_kerberos_tgt(pw, tgt))
170 verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
171 xfree(tgt);
172 }
173 continue;
174
175 case SSH_CMSG_HAVE_AFS_TOKEN:
176 if (!options.afs_token_passing || !k_hasafs()) {
177 /* packet_get_all(); */
178 verbose("AFS token passing disabled.");
179 break;
180 } else {
181 /* Accept AFS token. */
182 char *token_string = packet_get_string(&dlen);
183 packet_integrity_check(plen, 4 + dlen, type);
184 if (!auth_afs_token(pw, token_string))
185 verbose("AFS token REFUSED for %s", pw->pw_name);
186 xfree(token_string);
187 }
188 continue;
189#endif /* AFS */
190#ifdef KRB4
191 case SSH_CMSG_AUTH_KERBEROS:
192 if (!options.kerberos_authentication) {
193 /* packet_get_all(); */
194 verbose("Kerberos authentication disabled.");
195 break;
196 } else {
197 /* Try Kerberos v4 authentication. */
198 KTEXT_ST auth;
199 char *tkt_user = NULL;
200 char *kdata = packet_get_string((unsigned int *) &auth.length);
201 packet_integrity_check(plen, 4 + auth.length, type);
202
203 if (auth.length < MAX_KTXT_LEN)
204 memcpy(auth.dat, kdata, auth.length);
205 xfree(kdata);
206
207 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
208
209 if (authenticated) {
210 snprintf(user, sizeof user, " tktuser %s", tkt_user);
211 xfree(tkt_user);
212 }
213 }
214 break;
215#endif /* KRB4 */
216
217 case SSH_CMSG_AUTH_RHOSTS:
218 if (!options.rhosts_authentication) {
219 verbose("Rhosts authentication disabled.");
220 break;
221 }
222 /*
223 * Get client user name. Note that we just have to
224 * trust the client; this is one reason why rhosts
225 * authentication is insecure. (Another is
226 * IP-spoofing on a local network.)
227 */
228 client_user = packet_get_string(&ulen);
229 packet_integrity_check(plen, 4 + ulen, type);
230
231 /* Try to authenticate using /etc/hosts.equiv and
232 .rhosts. */
233 authenticated = auth_rhosts(pw, client_user);
234
235 snprintf(user, sizeof user, " ruser %s", client_user);
236 break;
237
238 case SSH_CMSG_AUTH_RHOSTS_RSA:
239 if (!options.rhosts_rsa_authentication) {
240 verbose("Rhosts with RSA authentication disabled.");
241 break;
242 }
243 /*
244 * Get client user name. Note that we just have to
245 * trust the client; root on the client machine can
246 * claim to be any user.
247 */
248 client_user = packet_get_string(&ulen);
249
250 /* Get the client host key. */
251 client_host_key = RSA_new();
252 if (client_host_key == NULL)
253 fatal("RSA_new failed");
254 client_host_key->e = BN_new();
255 client_host_key->n = BN_new();
256 if (client_host_key->e == NULL || client_host_key->n == NULL)
257 fatal("BN_new failed");
258 bits = packet_get_int();
259 packet_get_bignum(client_host_key->e, &elen);
260 packet_get_bignum(client_host_key->n, &nlen);
261
262 if (bits != BN_num_bits(client_host_key->n))
Damien Millerbd483e72000-04-30 10:00:53 +1000263 log("Warning: keysize mismatch for client_host_key: "
264 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
Damien Millereba71ba2000-04-29 23:57:08 +1000265 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
266
267 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
268 RSA_free(client_host_key);
269
270 snprintf(user, sizeof user, " ruser %s", client_user);
271 break;
272
273 case SSH_CMSG_AUTH_RSA:
274 if (!options.rsa_authentication) {
275 verbose("RSA authentication disabled.");
276 break;
277 }
278 /* RSA authentication requested. */
279 n = BN_new();
280 packet_get_bignum(n, &nlen);
281 packet_integrity_check(plen, nlen, type);
282 authenticated = auth_rsa(pw, n);
283 BN_clear_free(n);
284 break;
285
286 case SSH_CMSG_AUTH_PASSWORD:
287 if (!options.password_authentication) {
288 verbose("Password authentication disabled.");
289 break;
290 }
291 /*
292 * Read user password. It is in plain text, but was
293 * transmitted over the encrypted channel so it is
294 * not visible to an outside observer.
295 */
296 password = packet_get_string(&dlen);
297 packet_integrity_check(plen, 4 + dlen, type);
298
299#ifdef USE_PAM
300 /* Do PAM auth with password */
301 authenticated = auth_pam_password(pw, password);
302#else /* USE_PAM */
303 /* Try authentication with the password. */
304 authenticated = auth_password(pw, password);
305#endif /* USE_PAM */
306
307 memset(password, 0, strlen(password));
308 xfree(password);
309 break;
310
311#ifdef SKEY
312 case SSH_CMSG_AUTH_TIS:
313 debug("rcvd SSH_CMSG_AUTH_TIS");
314 if (options.skey_authentication == 1) {
315 char *skeyinfo = skey_keyinfo(pw->pw_name);
316 if (skeyinfo == NULL) {
317 debug("generating fake skeyinfo for %.100s.", pw->pw_name);
318 skeyinfo = skey_fake_keyinfo(pw->pw_name);
319 }
320 if (skeyinfo != NULL) {
321 /* we send our s/key- in tis-challenge messages */
322 debug("sending challenge '%s'", skeyinfo);
323 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
324 packet_put_string(skeyinfo, strlen(skeyinfo));
325 packet_send();
326 packet_write_wait();
327 continue;
328 }
329 }
330 break;
331 case SSH_CMSG_AUTH_TIS_RESPONSE:
332 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
333 if (options.skey_authentication == 1) {
334 char *response = packet_get_string(&dlen);
335 debug("skey response == '%s'", response);
336 packet_integrity_check(plen, 4 + dlen, type);
337 authenticated = (skey_haskey(pw->pw_name) == 0 &&
338 skey_passcheck(pw->pw_name, response) != -1);
339 xfree(response);
340 }
341 break;
342#else
343 case SSH_CMSG_AUTH_TIS:
344 /* TIS Authentication is unsupported */
345 log("TIS authentication unsupported.");
346 break;
347#endif
348
349 default:
350 /*
351 * Any unknown messages will be ignored (and failure
352 * returned) during authentication.
353 */
354 log("Unknown message during authentication: type %d", type);
355 break;
356 }
357
358 /*
359 * Check if the user is logging in as root and root logins
360 * are disallowed.
361 * Note that root login is allowed for forced commands.
362 */
363 if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
364 if (forced_command) {
365 log("Root login accepted for forced command.");
366 } else {
367 authenticated = 0;
368 log("ROOT LOGIN REFUSED FROM %.200s",
369 get_canonical_hostname());
370 }
371 }
372
373 /* Raise logging level */
374 if (authenticated ||
375 attempt == AUTH_FAIL_LOG ||
376 type == SSH_CMSG_AUTH_PASSWORD)
377 authlog = log;
378
379 authlog("%s %s for %.200s from %.200s port %d%s",
380 authenticated ? "Accepted" : "Failed",
381 get_authname(type),
382 pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
383 get_remote_ipaddr(),
384 get_remote_port(),
385 user);
386
387#ifdef USE_PAM
388 if (authenticated) {
389 if (!do_pam_account(pw->pw_name, client_user)) {
390 if (client_user != NULL) {
391 xfree(client_user);
392 client_user = NULL;
393 }
394 do_fake_authloop1(pw->pw_name);
395 }
396 return;
397 }
398#else /* USE_PAM */
399 if (authenticated) {
400 return;
401 }
402#endif /* USE_PAM */
403
404 if (client_user != NULL) {
405 xfree(client_user);
406 client_user = NULL;
407 }
408
Damien Millerd2c208a2000-05-17 22:00:02 +1000409 if (attempt > AUTH_FAIL_MAX) {
410#ifdef WITH_AIXAUTHENTICATE
411 loginfailed(pw->pw_name,get_canonical_hostname(),"ssh");
412#endif /* WITH_AIXAUTHENTICATE */
Damien Millereba71ba2000-04-29 23:57:08 +1000413 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
Damien Millerd2c208a2000-05-17 22:00:02 +1000414 }
Damien Millereba71ba2000-04-29 23:57:08 +1000415
416 /* Send a message indicating that the authentication attempt failed. */
417 packet_start(SSH_SMSG_FAILURE);
418 packet_send();
419 packet_write_wait();
420 }
421}
422
423/*
424 * Performs authentication of an incoming connection. Session key has already
425 * been exchanged and encryption is enabled.
426 */
427void
428do_authentication()
429{
430 struct passwd *pw, pwcopy;
431 int plen;
432 unsigned int ulen;
433 char *user;
434#ifdef WITH_AIXAUTHENTICATE
Damien Millerd2c208a2000-05-17 22:00:02 +1000435 extern char *aixloginmsg;
Damien Millereba71ba2000-04-29 23:57:08 +1000436#endif /* WITH_AIXAUTHENTICATE */
437
438 /* Get the name of the user that we wish to log in as. */
439 packet_read_expect(&plen, SSH_CMSG_USER);
440
441 /* Get the user name. */
442 user = packet_get_string(&ulen);
443 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
444
445 setproctitle("%s", user);
446
447#ifdef AFS
448 /* If machine has AFS, set process authentication group. */
449 if (k_hasafs()) {
450 k_setpag();
451 k_unlog();
452 }
453#endif /* AFS */
454
455 /* Verify that the user is a valid user. */
456 pw = getpwnam(user);
457 if (!pw || !allowed_user(pw))
458 do_fake_authloop1(user);
459 xfree(user);
460
461 /* Take a copy of the returned structure. */
462 memset(&pwcopy, 0, sizeof(pwcopy));
463 pwcopy.pw_name = xstrdup(pw->pw_name);
464 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
465 pwcopy.pw_uid = pw->pw_uid;
466 pwcopy.pw_gid = pw->pw_gid;
467 pwcopy.pw_dir = xstrdup(pw->pw_dir);
468 pwcopy.pw_shell = xstrdup(pw->pw_shell);
469 pw = &pwcopy;
470
471#ifdef USE_PAM
472 start_pam(pw);
473#endif
474
475 /*
476 * If we are not running as root, the user must have the same uid as
477 * the server.
478 */
479 if (getuid() != 0 && pw->pw_uid != getuid())
480 packet_disconnect("Cannot change user when server not running as root.");
481
482 debug("Attempting authentication for %.100s.", pw->pw_name);
483
484 /* If the user has no password, accept authentication immediately. */
485 if (options.password_authentication &&
486#ifdef KRB4
487 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
488#endif /* KRB4 */
489#ifdef USE_PAM
490 auth_pam_password(pw, "")) {
491#else /* USE_PAM */
492 auth_password(pw, "")) {
493#endif /* USE_PAM */
494 /* Authentication with empty password succeeded. */
495 log("Login for user %s from %.100s, accepted without authentication.",
496 pw->pw_name, get_remote_ipaddr());
497 } else {
498 /* Loop until the user has been authenticated or the
499 connection is closed, do_authloop() returns only if
500 authentication is successfull */
501 do_authloop(pw);
502 }
503
504 /* The user has been authenticated and accepted. */
505#ifdef WITH_AIXAUTHENTICATE
Damien Millerd2c208a2000-05-17 22:00:02 +1000506 /* We don't have a pty yet, so just label the line as "ssh" */
507 if (loginsuccess(user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
508 aixloginmsg = NULL;
Damien Millereba71ba2000-04-29 23:57:08 +1000509#endif /* WITH_AIXAUTHENTICATE */
510 packet_start(SSH_SMSG_SUCCESS);
511 packet_send();
512 packet_write_wait();
513
514 /* Perform session preparation. */
515 do_authenticated(pw);
516}