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