]> andersk Git - gssapi-openssh.git/blob - openssh/auth1.c
removing unneeded #ifdef GSSAPI
[gssapi-openssh.git] / openssh / 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.35 2002/02/03 17:53:25 markus Exp $");
14
15 #include "xmalloc.h"
16 #include "rsa.h"
17 #include "ssh1.h"
18 #include "dispatch.h"
19 #include "packet.h"
20 #include "buffer.h"
21 #include "mpaux.h"
22 #include "log.h"
23 #include "servconf.h"
24 #include "compat.h"
25 #include "auth.h"
26 #include "channels.h"
27 #include "session.h"
28 #include "misc.h"
29 #include "uidswap.h"
30
31 /* import */
32 extern ServerOptions options;
33
34 #ifdef GSSAPI
35 int     userauth_gssapi(Authctxt *authctxt);
36
37 void
38 auth1_gss_protocol_error(int type, u_int32_t plen, void *ctxt)
39 {
40   Authctxt *authctxt = ctxt;
41   /* Other side told us to abort, dont need to tell him */ 
42   /* maybe we can us some other method. */
43   if (type == SSH_MSG_AUTH_GSSAPI_ABORT) {
44       log("auth1: GSSAPI aborting");
45       dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
46       authctxt->success = 1; /* get out of loop*/
47       return;
48   }
49
50   log("auth1: protocol error: type %d plen %d", type, plen);
51   packet_disconnect("Protocol error during GSSAPI authentication: "
52           "Unknown packet type %d", type);
53 }
54
55 /*
56  * SSH1 GSSAPI clients may send us a user name of the form:
57  *
58  *   (1) username:x:SSL Subject Name
59  *     or
60  *   (2) username:i:SSL Subject Name
61  *     or
62  *   (3) username
63  *
64  *  if case 1, then uname is an explicit name (ssh -l uname). Keep this
65  *  name always, rewrite the user parameter to be just uname. We'll pull
66  *  the GSSAPI idenity out and deal with (or skip it) later.
67  *  
68  *  if case 2, then uname is implicit (user didn't use the -l option), so
69  *  use the default gridmap mapping and replace uname with whatever
70  *  the gridmap maps to. If the gridmap mapping fails, drop down
71  *  to just uname
72  *  
73  *  if case 3, then leave it be.
74  *
75  *  This function may return the original pointer to the orginal string,
76  *  the original pointer to a modified string, or a completely new pointer.
77  */
78 static char *
79 ssh1_gssapi_parse_userstring(char *userstring)
80 {
81   char name_type = '\0';        /* explicit 'x' or implicit 'i' */
82   char *ssl_subject_name = NULL;
83   char *delim = NULL;
84
85   debug("Looking at username '%s' for gssapi-ssleay type name", userstring);
86   if((delim = strchr(userstring, ':')) != NULL) {
87       /* Parse and split into components */
88       ssl_subject_name = strchr(delim + 1, ':');
89
90       if (ssl_subject_name) {
91         /* Successful parse, split into components */
92         *delim = '\0';
93         name_type = *(delim + 1);
94         *ssl_subject_name = '\0';
95         ssl_subject_name++;
96
97         debug("Name parsed. type = '%c'. ssl subject name is \"%s\"",
98               name_type, ssl_subject_name);
99
100       } else {
101
102         debug("Don't understand name format. Letting it pass.");
103       } 
104   }     
105
106 #ifdef GSI
107   if(ssl_subject_name) {
108     char *gridmapped_name = NULL;
109     switch (name_type) {
110     case 'x':
111       debug("explicit name given, using %s as username", userstring);
112       break;
113
114     case 'i':
115       /* gridmap check */
116       debug("implicit name given. gridmapping '%s'", ssl_subject_name);
117
118       if(globus_gss_assist_gridmap(ssl_subject_name,
119                                      &gridmapped_name) == 0) {
120         userstring = gridmapped_name;
121         debug("I gridmapped and got %s", userstring);
122
123       } else {
124         debug("I gridmapped and got null, reverting to %s", userstring);
125       }
126       break;
127
128     default:
129       debug("Unknown name type '%c'. Ignoring.", name_type);
130       break;
131     }
132   } else {
133     debug("didn't find any :'s so I assume it's just a user name");
134   }
135 #endif /* GSI */
136
137   return userstring;
138 }
139 #endif
140
141 /*
142  * convert ssh auth msg type into description
143  */
144 static char *
145 get_authname(int type)
146 {
147         static char buf[1024];
148         switch (type) {
149         case SSH_CMSG_AUTH_PASSWORD:
150                 return "password";
151         case SSH_CMSG_AUTH_RSA:
152                 return "rsa";
153         case SSH_CMSG_AUTH_RHOSTS_RSA:
154                 return "rhosts-rsa";
155         case SSH_CMSG_AUTH_RHOSTS:
156                 return "rhosts";
157         case SSH_CMSG_AUTH_TIS:
158         case SSH_CMSG_AUTH_TIS_RESPONSE:
159                 return "challenge-response";
160 #if defined(KRB4) || defined(KRB5)
161         case SSH_CMSG_AUTH_KERBEROS:
162                 return "kerberos";
163 #endif
164 #if defined(GSSAPI)
165         case SSH_CMSG_AUTH_GSSAPI:
166                 return "gssapi";
167 #endif
168         }
169         snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
170         return buf;
171 }
172
173 /*
174  * read packets, try to authenticate the user and
175  * return only if authentication is successful
176  */
177 static void
178 do_authloop(Authctxt *authctxt)
179 {
180         int authenticated = 0;
181         u_int bits;
182         Key *client_host_key;
183         BIGNUM *n;
184         char *client_user, *password;
185         char info[1024];
186         u_int dlen;
187         u_int ulen;
188         int type = 0;
189         struct passwd *pw = authctxt->pw;
190
191         debug("Attempting authentication for %s%.100s.",
192             authctxt->valid ? "" : "illegal user ", authctxt->user);
193
194         /* If the user has no password, accept authentication immediately. */
195         if (options.password_authentication &&
196 #if defined(KRB4) || defined(KRB5)
197             (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
198 #endif
199 #ifdef USE_PAM
200             auth_pam_password(pw, "")) {
201 #elif defined(HAVE_OSF_SIA)
202             0) {
203 #else
204             auth_password(authctxt, "")) {
205 #endif
206                 auth_log(authctxt, 1, "without authentication", "");
207                 return;
208         }
209
210         /* Indicate that authentication is needed. */
211         packet_start(SSH_SMSG_FAILURE);
212         packet_send();
213         packet_write_wait();
214
215         client_user = NULL;
216
217         for (;;) {
218                 /* default to fail */
219                 authenticated = 0;
220
221                 info[0] = '\0';
222
223                 /* Get a packet from the client. */
224                 type = packet_read();
225
226                 /* Process the packet. */
227                 switch (type) {
228
229 #if defined(KRB4) || defined(KRB5)
230                 case SSH_CMSG_AUTH_KERBEROS:
231                         if (!options.kerberos_authentication) {
232                                 verbose("Kerberos authentication disabled.");
233                         } else {
234                                 char *kdata = packet_get_string(&dlen);
235                                 packet_check_eom();
236
237                                 if (kdata[0] == 4) { /* KRB_PROT_VERSION */
238 #ifdef KRB4
239                                         KTEXT_ST tkt;
240
241                                         tkt.length = dlen;
242                                         if (tkt.length < MAX_KTXT_LEN)
243                                                 memcpy(tkt.dat, kdata, tkt.length);
244
245                                         if (auth_krb4(authctxt, &tkt, &client_user)) {
246                                                 authenticated = 1;
247                                                 snprintf(info, sizeof(info),
248                                                     " tktuser %.100s",
249                                                     client_user);
250                                         }
251 #endif /* KRB4 */
252                                 } else {
253 #ifdef KRB5
254                                         krb5_data tkt;
255                                         tkt.length = dlen;
256                                         tkt.data = kdata;
257
258                                         if (auth_krb5(authctxt, &tkt, &client_user)) {
259                                                 authenticated = 1;
260                                                 snprintf(info, sizeof(info),
261                                                     " tktuser %.100s",
262                                                     client_user);
263                                         }
264 #endif /* KRB5 */
265                                 }
266                                 xfree(kdata);
267                         }
268                         break;
269 #endif /* KRB4 || KRB5 */
270
271 #ifdef GSSAPI
272                 case SSH_CMSG_AUTH_GSSAPI:
273                         if (!options.gss_authentication) {
274                                 verbose("GSSAPI authentication disabled.");
275                                 break;
276                         }
277                         /*
278                         * GSSAPI was first added to ssh1 in ssh-1.2.27, and
279                         * was added to the SecurtCRT product. In order
280                         * to continue operating with these, we will add
281                         * the equivelent GSSAPI support to SSH1. 
282                         * Will use the gssapi routines from the ssh2 as
283                         * they are almost identical. But they use dispatch
284                         * so we need to setup the dispatch tables here 
285                         * auth1.c for use only by the gssapi code. 
286                         * Since we already have the packet, we will call
287                         * userauth_gssapi then start the dispatch loop.
288                         */
289                         if (!authctxt->valid) {
290                         packet_disconnect("Authentication rejected for invalid user");
291                         }
292                         dispatch_init(&auth1_gss_protocol_error);
293                         userauth_gssapi(authctxt);
294                         dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
295                         if (authctxt->postponed) { /* failed, try other methods */
296                                 authctxt->success = 0;
297                                 authctxt->postponed = 0;
298                                 break;
299                         }
300                         do_authenticated(authctxt);
301                         /* will only return if authenticated */
302                         authenticated = 1;
303                         break;
304 #endif /* GSSAPI */
305                         
306 #if defined(AFS) || defined(KRB5)
307                         /* XXX - punt on backward compatibility here. */
308                 case SSH_CMSG_HAVE_KERBEROS_TGT:
309                         packet_send_debug("Kerberos TGT passing disabled before authentication.");
310                         break;
311 #ifdef AFS
312                 case SSH_CMSG_HAVE_AFS_TOKEN:
313                         packet_send_debug("AFS token passing disabled before authentication.");
314                         break;
315 #endif /* AFS */
316 #endif /* AFS || KRB5 */
317
318                 case SSH_CMSG_AUTH_RHOSTS:
319                         if (!options.rhosts_authentication) {
320                                 verbose("Rhosts authentication disabled.");
321                                 break;
322                         }
323                         /*
324                          * Get client user name.  Note that we just have to
325                          * trust the client; this is one reason why rhosts
326                          * authentication is insecure. (Another is
327                          * IP-spoofing on a local network.)
328                          */
329                         client_user = packet_get_string(&ulen);
330                         packet_check_eom();
331
332                         /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
333                         authenticated = auth_rhosts(pw, client_user);
334
335                         snprintf(info, sizeof info, " ruser %.100s", client_user);
336                         break;
337
338                 case SSH_CMSG_AUTH_RHOSTS_RSA:
339                         if (!options.rhosts_rsa_authentication) {
340                                 verbose("Rhosts with RSA authentication disabled.");
341                                 break;
342                         }
343                         /*
344                          * Get client user name.  Note that we just have to
345                          * trust the client; root on the client machine can
346                          * claim to be any user.
347                          */
348                         client_user = packet_get_string(&ulen);
349
350                         /* Get the client host key. */
351                         client_host_key = key_new(KEY_RSA1);
352                         bits = packet_get_int();
353                         packet_get_bignum(client_host_key->rsa->e);
354                         packet_get_bignum(client_host_key->rsa->n);
355
356                         if (bits != BN_num_bits(client_host_key->rsa->n))
357                                 verbose("Warning: keysize mismatch for client_host_key: "
358                                     "actual %d, announced %d",
359                                      BN_num_bits(client_host_key->rsa->n), bits);
360                         packet_check_eom();
361
362                         authenticated = auth_rhosts_rsa(pw, client_user,
363                             client_host_key);
364                         key_free(client_host_key);
365
366                         snprintf(info, sizeof info, " ruser %.100s", client_user);
367                         break;
368
369                 case SSH_CMSG_AUTH_RSA:
370                         if (!options.rsa_authentication) {
371                                 verbose("RSA authentication disabled.");
372                                 break;
373                         }
374                         /* RSA authentication requested. */
375                         if ((n = BN_new()) == NULL)
376                                 fatal("do_authloop: BN_new failed");
377                         packet_get_bignum(n);
378                         packet_check_eom();
379                         authenticated = auth_rsa(pw, n);
380                         BN_clear_free(n);
381                         break;
382
383                 case SSH_CMSG_AUTH_PASSWORD:
384                         if (!options.password_authentication) {
385                                 verbose("Password authentication disabled.");
386                                 break;
387                         }
388                         /*
389                          * Read user password.  It is in plain text, but was
390                          * transmitted over the encrypted channel so it is
391                          * not visible to an outside observer.
392                          */
393                         password = packet_get_string(&dlen);
394                         packet_check_eom();
395
396 #ifdef USE_PAM
397                         /* Do PAM auth with password */
398                         authenticated = auth_pam_password(pw, password);
399 #elif defined(HAVE_OSF_SIA)
400                         /* Do SIA auth with password */
401                         authenticated = auth_sia_password(authctxt->user, 
402                             password);
403 #else /* !USE_PAM && !HAVE_OSF_SIA */
404                         /* Try authentication with the password. */
405                         authenticated = auth_password(authctxt, password);
406 #endif /* USE_PAM */
407
408                         memset(password, 0, strlen(password));
409                         xfree(password);
410                         break;
411
412                 case SSH_CMSG_AUTH_TIS:
413                         debug("rcvd SSH_CMSG_AUTH_TIS");
414                         if (options.challenge_response_authentication == 1) {
415                                 char *challenge = get_challenge(authctxt);
416                                 if (challenge != NULL) {
417                                         debug("sending challenge '%s'", challenge);
418                                         packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
419                                         packet_put_cstring(challenge);
420                                         xfree(challenge);
421                                         packet_send();
422                                         packet_write_wait();
423                                         continue;
424                                 }
425                         }
426                         break;
427                 case SSH_CMSG_AUTH_TIS_RESPONSE:
428                         debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
429                         if (options.challenge_response_authentication == 1) {
430                                 char *response = packet_get_string(&dlen);
431                                 debug("got response '%s'", response);
432                                 packet_check_eom();
433                                 authenticated = verify_response(authctxt, response);
434                                 memset(response, 'r', dlen);
435                                 xfree(response);
436                         }
437                         break;
438
439                 default:
440                         /*
441                          * Any unknown messages will be ignored (and failure
442                          * returned) during authentication.
443                          */
444                         log("Unknown message during authentication: type %d", type);
445                         break;
446                 }
447 #ifdef BSD_AUTH
448                 if (authctxt->as) {
449                         auth_close(authctxt->as);
450                         authctxt->as = NULL;
451                 }
452 #endif
453                 if (!authctxt->valid && authenticated)
454                         fatal("INTERNAL ERROR: authenticated invalid user %s",
455                             authctxt->user);
456
457 #ifdef HAVE_CYGWIN
458                 if (authenticated &&
459                     !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) {
460                         packet_disconnect("Authentication rejected for uid %d.",
461                         pw == NULL ? -1 : pw->pw_uid);
462                         authenticated = 0;
463                 }
464 #else
465                 /* Special handling for root */
466                 if (authenticated && authctxt->pw->pw_uid == 0 &&
467                     !auth_root_allowed(get_authname(type)))
468                         authenticated = 0;
469 #endif
470 #ifdef USE_PAM
471                 if (authenticated && !do_pam_account(pw->pw_name, client_user))
472                         authenticated = 0;
473 #endif
474
475                 /* Log before sending the reply */
476                 auth_log(authctxt, authenticated, get_authname(type), info);
477
478                 if (client_user != NULL) {
479                         xfree(client_user);
480                         client_user = NULL;
481                 }
482
483                 if (authenticated)
484                         return;
485
486                 if (authctxt->failures++ > AUTH_FAIL_MAX) {
487 #ifdef WITH_AIXAUTHENTICATE
488                         loginfailed(authctxt->user,
489                             get_canonical_hostname(options.verify_reverse_mapping),
490                             "ssh");
491 #endif /* WITH_AIXAUTHENTICATE */
492                         packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
493                 }
494
495                 packet_start(SSH_SMSG_FAILURE);
496                 packet_send();
497                 packet_write_wait();
498         }
499 }
500
501 /*
502  * Performs authentication of an incoming connection.  Session key has already
503  * been exchanged and encryption is enabled.
504  */
505 void
506 do_authentication(void)
507 {
508         Authctxt *authctxt;
509         struct passwd *pw;
510         u_int ulen;
511         char *p, *user, *style = NULL;
512
513         /* Get the name of the user that we wish to log in as. */
514         packet_read_expect(SSH_CMSG_USER);
515
516         /* Get the user name. */
517         user = packet_get_string(&ulen);
518         packet_check_eom();
519
520 #ifdef GSSAPI
521   /* Parse GSSAPI identity from userstring */
522   user = ssh1_gssapi_parse_userstring(user);
523 #endif /* GSSAPI */
524
525         if ((style = strchr(user, ':')) != NULL)
526                 *style++ = '\0';
527
528         /* XXX - SSH.com Kerberos v5 braindeath. */
529         if ((p = strchr(user, '@')) != NULL)
530                 *p = '\0';
531
532         authctxt = authctxt_new();
533         authctxt->user = user;
534         authctxt->style = style;
535
536         /* Verify that the user is a valid user. */
537         pw = getpwnam(user);
538         if (pw && allowed_user(pw)) {
539                 authctxt->valid = 1;
540                 pw = pwcopy(pw);
541         } else {
542                 debug("do_authentication: illegal user %s", user);
543                 pw = NULL;
544         }
545         authctxt->pw = pw;
546
547         setproctitle("%s", pw ? user : "unknown");
548
549 #ifdef USE_PAM
550         start_pam(pw == NULL ? "NOUSER" : user);
551 #endif
552
553         /*
554          * If we are not running as root, the user must have the same uid as
555          * the server. (Unless you are running Windows)
556          */
557 #ifndef HAVE_CYGWIN
558         if (getuid() != 0 && pw && pw->pw_uid != getuid())
559                 packet_disconnect("Cannot change user when server not running as root.");
560 #endif
561
562         /*
563          * Loop until the user has been authenticated or the connection is
564          * closed, do_authloop() returns only if authentication is successful
565          */
566         do_authloop(authctxt);
567
568         /* The user has been authenticated and accepted. */
569         packet_start(SSH_SMSG_SUCCESS);
570         packet_send();
571         packet_write_wait();
572
573         /* Perform session preparation. */
574         do_authenticated(authctxt);
575 }
This page took 0.079161 seconds and 5 git commands to generate.