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