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