]> andersk Git - gssapi-openssh.git/blob - openssh/auth2.c
revision: solve the implicit user name problem of
[gssapi-openssh.git] / openssh / auth2.c
1 /*
2  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "includes.h"
26 RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $");
27
28 #include <openssl/evp.h>
29
30 #include "ssh2.h"
31 #include "ssh1.h"
32 #include "xmalloc.h"
33 #include "rsa.h"
34 #include "sshpty.h"
35 #include "packet.h"
36 #include "buffer.h"
37 #include "log.h"
38 #include "servconf.h"
39 #include "compat.h"
40 #include "channels.h"
41 #include "bufaux.h"
42 #include "auth.h"
43 #include "session.h"
44 #include "dispatch.h"
45 #include "key.h"
46 #include "cipher.h"
47 #include "kex.h"
48 #include "pathnames.h"
49 #include "uidswap.h"
50 #include "auth-options.h"
51 #include "misc.h"
52 #include "hostfile.h"
53 #include "canohost.h"
54 #include "match.h"
55
56 #ifdef GSSAPI
57 #include "ssh-gss.h"
58 #ifdef GSI
59 #include "globus_gss_assist.h"
60 char* olduser;
61 int  changeuser = 0;
62 #endif
63 #endif
64
65 /* import */
66 extern ServerOptions options;
67 extern u_char *session_id2;
68 extern int session_id2_len;
69
70 static Authctxt *x_authctxt = NULL;
71 static int one = 1;
72
73 typedef struct Authmethod Authmethod;
74 struct Authmethod {
75         char    *name;
76         int     (*userauth)(Authctxt *authctxt);
77         int     *enabled;
78 };
79
80 /* protocol */
81
82 static void input_service_request(int, u_int32_t, void *);
83 static void input_userauth_request(int, u_int32_t, void *);
84
85 /* helper */
86 static Authmethod *authmethod_lookup(const char *);
87 static char *authmethods_get(void);
88 static int user_key_allowed(struct passwd *, Key *);
89 static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
90
91 /* auth */
92 static void userauth_banner(void);
93 static int userauth_none(Authctxt *);
94 static int userauth_passwd(Authctxt *);
95 static int userauth_pubkey(Authctxt *);
96 static int userauth_hostbased(Authctxt *);
97 static int userauth_kbdint(Authctxt *);
98
99 #ifdef GSSAPI
100 int     userauth_external(Authctxt *authctxt);
101 int     userauth_gssapi(Authctxt *authctxt);
102 #endif
103
104 Authmethod authmethods[] = {
105         {"none",
106                 userauth_none,
107                 &one},
108 #ifdef GSSAPI
109         {"external-keyx",
110                 userauth_external,
111                 &options.gss_authentication},
112         {"gssapi",
113                 userauth_gssapi,
114                 &options.gss_authentication},
115 #endif
116         {"publickey",
117                 userauth_pubkey,
118                 &options.pubkey_authentication},
119         {"password",
120                 userauth_passwd,
121                 &options.password_authentication},
122         {"keyboard-interactive",
123                 userauth_kbdint,
124                 &options.kbd_interactive_authentication},
125         {"hostbased",
126                 userauth_hostbased,
127                 &options.hostbased_authentication},
128         {NULL, NULL, NULL}
129 };
130
131 /*
132  * loop until authctxt->success == TRUE
133  */
134
135 void
136 do_authentication2(void)
137 {
138         Authctxt *authctxt = authctxt_new();
139
140         x_authctxt = authctxt;          /*XXX*/
141
142         /* challenge-response is implemented via keyboard interactive */
143         if (options.challenge_response_authentication)
144                 options.kbd_interactive_authentication = 1;
145         if (options.pam_authentication_via_kbd_int)
146                 options.kbd_interactive_authentication = 1;
147
148         dispatch_init(&dispatch_protocol_error);
149         dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
150         dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
151         do_authenticated(authctxt);
152 }
153
154 static void
155 input_service_request(int type, u_int32_t seq, void *ctxt)
156 {
157         Authctxt *authctxt = ctxt;
158         u_int len;
159         int accept = 0;
160         char *service = packet_get_string(&len);
161         packet_check_eom();
162
163         if (authctxt == NULL)
164                 fatal("input_service_request: no authctxt");
165
166         if (strcmp(service, "ssh-userauth") == 0) {
167                 if (!authctxt->success) {
168                         accept = 1;
169                         /* now we can handle user-auth requests */
170                         dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
171                 }
172         }
173         /* XXX all other service requests are denied */
174
175         if (accept) {
176                 packet_start(SSH2_MSG_SERVICE_ACCEPT);
177                 packet_put_cstring(service);
178                 packet_send();
179                 packet_write_wait();
180         } else {
181                 debug("bad service request %s", service);
182                 packet_disconnect("bad service request %s", service);
183         }
184         xfree(service);
185 }
186
187 static void
188 input_userauth_request(int type, u_int32_t seq, void *ctxt)
189 {
190         Authctxt *authctxt = ctxt;
191         Authmethod *m = NULL;
192         char *user, *service, *method, *style = NULL;
193         int authenticated = 0;
194
195         if (authctxt == NULL)
196                 fatal("input_userauth_request: no authctxt");
197
198         user = packet_get_string(NULL);
199         service = packet_get_string(NULL);
200         method = packet_get_string(NULL);
201
202 #ifdef GSSAPI
203 #ifdef GSI
204         if(changeuser == 0 && (strcmp(method,"external-keyx") == 0 || strcmp(method,"gssapi") ==0) && strcmp(user,"") == 0) {
205                 char *gridmapped_name = NULL;
206                 struct passwd *pw = NULL;
207                 gssapi_setup_env();
208                 if(globus_gss_assist_gridmap(gssapi_client_name.value,
209                                      &gridmapped_name) == 0) {
210                         user = gridmapped_name;
211                         debug("I gridmapped and got %s", user);
212                         pw = getpwnam(user);
213                         if (pw && allowed_user(pw)) {
214                                 olduser = authctxt->user;
215                                 authctxt->user = user;
216                                 authctxt->pw = pwcopy(pw);
217                                 authctxt->valid = 1;
218                                 changeuser = 1;
219                         }
220
221                 } else {
222                 debug("I gridmapped and got null, reverting to %s", authctxt->user);
223                 user = authctxt->user;
224                 }
225         }
226         else if(changeuser) {
227                 struct passwd *pw = NULL;
228                 pw = getpwnam(user);
229                 if (pw && allowed_user(pw)) {
230                         authctxt->user = olduser;
231                         authctxt->pw = pwcopy(pw);
232                         authctxt->valid = 1;
233                         changeuser = 0;
234                 }
235         }
236
237 #endif  /* GSI */
238 #endif /* GSSAPI */
239
240         debug("userauth-request for user %s service %s method %s", user, service, method);
241         debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
242
243         if ((style = strchr(user, ':')) != NULL)
244                 *style++ = 0;
245
246         if (authctxt->attempt++ == 0) {
247                 /* setup auth context */
248                 struct passwd *pw = NULL;
249                 pw = getpwnam(user);
250                 if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
251                         authctxt->pw = pwcopy(pw);
252                         authctxt->valid = 1;
253                         debug2("input_userauth_request: setting up authctxt for %s", user);
254 #ifdef USE_PAM
255                         start_pam(pw->pw_name);
256 #endif
257                 } else {
258                         log("input_userauth_request: illegal user %s", user);
259 #ifdef USE_PAM
260                         start_pam("NOUSER");
261 #endif
262                 }
263                 setproctitle("%s", pw ? user : "unknown");
264                 authctxt->user = xstrdup(user);
265                 authctxt->service = xstrdup(service);
266                 authctxt->style = style ? xstrdup(style) : NULL;
267         } else if (strcmp(user, authctxt->user) != 0 ||
268             strcmp(service, authctxt->service) != 0) {
269                 packet_disconnect("Change of username or service not allowed: "
270                     "(%s,%s) -> (%s,%s)",
271                     authctxt->user, authctxt->service, user, service);
272         }
273         /* reset state */
274         auth2_challenge_stop(authctxt);
275
276 #ifdef GSSAPI
277         dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
278         dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
279 #endif
280
281         authctxt->postponed = 0;
282
283         /* try to authenticate user */
284         m = authmethod_lookup(method);
285         if (m != NULL) {
286                 debug2("input_userauth_request: try method %s", method);
287                 authenticated = m->userauth(authctxt);
288         }
289         userauth_finish(authctxt, authenticated, method);
290
291         xfree(service);
292         xfree(user);
293         xfree(method);
294 }
295
296 void
297 userauth_finish(Authctxt *authctxt, int authenticated, char *method)
298 {
299         char *methods;
300
301         if (!authctxt->valid && authenticated)
302                 fatal("INTERNAL ERROR: authenticated invalid user %s",
303                     authctxt->user);
304
305         /* Special handling for root */
306         if (authenticated && authctxt->pw->pw_uid == 0 &&
307             !auth_root_allowed(method))
308                 authenticated = 0;
309
310 #ifdef USE_PAM
311         if (authenticated && authctxt->user && !do_pam_account(authctxt->user,
312             NULL))
313                 authenticated = 0;
314 #endif /* USE_PAM */
315
316         /* Log before sending the reply */
317         if (!compat20)
318         auth_log(authctxt, authenticated, method, " ssh1");
319         else
320         auth_log(authctxt, authenticated, method, " ssh2");
321
322         if (authctxt->postponed)
323                 return;
324
325         /* XXX todo: check if multiple auth methods are needed */
326         if (authenticated == 1) {
327                 /* turn off userauth */
328                 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
329                 if (!compat20)
330                 packet_start(SSH_SMSG_SUCCESS);
331                 else
332                 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
333                 packet_send();
334                 packet_write_wait();
335                 /* now we can break out */
336                 authctxt->success = 1;
337         } else {
338                 if (authctxt->failures++ > AUTH_FAIL_MAX) {
339 #ifdef WITH_AIXAUTHENTICATE
340                         loginfailed(authctxt->user,
341                             get_canonical_hostname(options.verify_reverse_mapping),
342                             "ssh");
343 #endif /* WITH_AIXAUTHENTICATE */
344                         packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
345                 }
346                 if (!compat20) {
347                 /*
348                  * Break out of the dispatch loop now and go back to
349                  * SSH1 code.  We need to set the 'success' flag to
350                  * break out of the loop.  Set the 'postponed' flag to
351                  * tell the SSH1 code that authentication failed.  The
352                  * SSH1 code will handle sending SSH_SMSG_FAILURE.
353                 */
354                 authctxt->success = authctxt->postponed = 1;
355                 } else {
356                 methods = authmethods_get();
357                 packet_start(SSH2_MSG_USERAUTH_FAILURE);
358                 packet_put_cstring(methods);
359                 packet_put_char(0);     /* XXX partial success, unused */
360                 packet_send();
361                 packet_write_wait();
362                 xfree(methods);
363                 }
364         }
365 }
366
367 static void
368 userauth_banner(void)
369 {
370         struct stat st;
371         char *banner = NULL;
372         off_t len, n;
373         int fd;
374
375         if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
376                 return;
377         if ((fd = open(options.banner, O_RDONLY)) < 0)
378                 return;
379         if (fstat(fd, &st) < 0)
380                 goto done;
381         len = st.st_size;
382         banner = xmalloc(len + 1);
383         if ((n = read(fd, banner, len)) < 0)
384                 goto done;
385         banner[n] = '\0';
386         packet_start(SSH2_MSG_USERAUTH_BANNER);
387         packet_put_cstring(banner);
388         packet_put_cstring("");         /* language, unused */
389         packet_send();
390         debug("userauth_banner: sent");
391 done:
392         if (banner)
393                 xfree(banner);
394         close(fd);
395         return;
396 }
397
398 static int
399 userauth_none(Authctxt *authctxt)
400 {
401         /* disable method "none", only allowed one time */
402         Authmethod *m = authmethod_lookup("none");
403         if (m != NULL)
404                 m->enabled = NULL;
405         packet_check_eom();
406         userauth_banner();
407
408         if (authctxt->valid == 0)
409                 return(0);
410
411 #ifdef HAVE_CYGWIN
412         if (check_nt_auth(1, authctxt->pw) == 0)
413                 return(0);
414 #endif
415 #ifdef USE_PAM
416         return auth_pam_password(authctxt->pw, "");
417 #elif defined(HAVE_OSF_SIA)
418         return 0;
419 #else /* !HAVE_OSF_SIA && !USE_PAM */
420         return auth_password(authctxt, "");
421 #endif /* USE_PAM */
422 }
423
424 static int
425 userauth_passwd(Authctxt *authctxt)
426 {
427         char *password;
428         int authenticated = 0;
429         int change;
430         u_int len;
431         change = packet_get_char();
432         if (change)
433                 log("password change not supported");
434         password = packet_get_string(&len);
435         packet_check_eom();
436         if (authctxt->valid &&
437 #ifdef HAVE_CYGWIN
438             check_nt_auth(1, authctxt->pw) &&
439 #endif
440 #ifdef USE_PAM
441             auth_pam_password(authctxt->pw, password) == 1)
442 #elif defined(HAVE_OSF_SIA)
443             auth_sia_password(authctxt->user, password) == 1)
444 #else /* !USE_PAM && !HAVE_OSF_SIA */
445             auth_password(authctxt, password) == 1)
446 #endif /* USE_PAM */
447                 authenticated = 1;
448         memset(password, 0, len);
449         xfree(password);
450         return authenticated;
451 }
452
453 static int
454 userauth_kbdint(Authctxt *authctxt)
455 {
456         int authenticated = 0;
457         char *lang, *devs;
458
459         lang = packet_get_string(NULL);
460         devs = packet_get_string(NULL);
461         packet_check_eom();
462
463         debug("keyboard-interactive devs %s", devs);
464
465         if (options.challenge_response_authentication)
466                 authenticated = auth2_challenge(authctxt, devs);
467
468 #ifdef USE_PAM
469         if (authenticated == 0 && options.pam_authentication_via_kbd_int)
470                 authenticated = auth2_pam(authctxt);
471 #endif
472         xfree(devs);
473         xfree(lang);
474 #ifdef HAVE_CYGWIN
475         if (check_nt_auth(0, authctxt->pw) == 0)
476                 return(0);
477 #endif
478         return authenticated;
479 }
480
481 static int
482 userauth_pubkey(Authctxt *authctxt)
483 {
484         Buffer b;
485         Key *key = NULL;
486         char *pkalg;
487         u_char *pkblob, *sig;
488         u_int alen, blen, slen;
489         int have_sig, pktype;
490         int authenticated = 0;
491
492         if (!authctxt->valid) {
493                 debug2("userauth_pubkey: disabled because of invalid user");
494                 return 0;
495         }
496         have_sig = packet_get_char();
497         if (datafellows & SSH_BUG_PKAUTH) {
498                 debug2("userauth_pubkey: SSH_BUG_PKAUTH");
499                 /* no explicit pkalg given */
500                 pkblob = packet_get_string(&blen);
501                 buffer_init(&b);
502                 buffer_append(&b, pkblob, blen);
503                 /* so we have to extract the pkalg from the pkblob */
504                 pkalg = buffer_get_string(&b, &alen);
505                 buffer_free(&b);
506         } else {
507                 pkalg = packet_get_string(&alen);
508                 pkblob = packet_get_string(&blen);
509         }
510         pktype = key_type_from_name(pkalg);
511         if (pktype == KEY_UNSPEC) {
512                 /* this is perfectly legal */
513                 log("userauth_pubkey: unsupported public key algorithm: %s",
514                     pkalg);
515                 goto done;
516         }
517         key = key_from_blob(pkblob, blen);
518         if (key == NULL) {
519                 error("userauth_pubkey: cannot decode key: %s", pkalg);
520                 goto done;
521         }
522         if (key->type != pktype) {
523                 error("userauth_pubkey: type mismatch for decoded key "
524                     "(received %d, expected %d)", key->type, pktype);
525                 goto done;
526         }
527         if (have_sig) {
528                 sig = packet_get_string(&slen);
529                 packet_check_eom();
530                 buffer_init(&b);
531                 if (datafellows & SSH_OLD_SESSIONID) {
532                         buffer_append(&b, session_id2, session_id2_len);
533                 } else {
534                         buffer_put_string(&b, session_id2, session_id2_len);
535                 }
536                 /* reconstruct packet */
537                 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
538                 buffer_put_cstring(&b, authctxt->user);
539                 buffer_put_cstring(&b,
540                     datafellows & SSH_BUG_PKSERVICE ?
541                     "ssh-userauth" :
542                     authctxt->service);
543                 if (datafellows & SSH_BUG_PKAUTH) {
544                         buffer_put_char(&b, have_sig);
545                 } else {
546                         buffer_put_cstring(&b, "publickey");
547                         buffer_put_char(&b, have_sig);
548                         buffer_put_cstring(&b, pkalg);
549                 }
550                 buffer_put_string(&b, pkblob, blen);
551 #ifdef DEBUG_PK
552                 buffer_dump(&b);
553 #endif
554                 /* test for correct signature */
555                 if (user_key_allowed(authctxt->pw, key) &&
556                     key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
557                         authenticated = 1;
558                 buffer_clear(&b);
559                 xfree(sig);
560         } else {
561                 debug("test whether pkalg/pkblob are acceptable");
562                 packet_check_eom();
563
564                 /* XXX fake reply and always send PK_OK ? */
565                 /*
566                  * XXX this allows testing whether a user is allowed
567                  * to login: if you happen to have a valid pubkey this
568                  * message is sent. the message is NEVER sent at all
569                  * if a user is not allowed to login. is this an
570                  * issue? -markus
571                  */
572                 if (user_key_allowed(authctxt->pw, key)) {
573                         packet_start(SSH2_MSG_USERAUTH_PK_OK);
574                         packet_put_string(pkalg, alen);
575                         packet_put_string(pkblob, blen);
576                         packet_send();
577                         packet_write_wait();
578                         authctxt->postponed = 1;
579                 }
580         }
581         if (authenticated != 1)
582                 auth_clear_options();
583 done:
584         debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
585         if (key != NULL)
586                 key_free(key);
587         xfree(pkalg);
588         xfree(pkblob);
589 #ifdef HAVE_CYGWIN
590         if (check_nt_auth(0, authctxt->pw) == 0)
591                 return(0);
592 #endif
593         return authenticated;
594 }
595
596 static int
597 userauth_hostbased(Authctxt *authctxt)
598 {
599         Buffer b;
600         Key *key = NULL;
601         char *pkalg, *cuser, *chost, *service;
602         u_char *pkblob, *sig;
603         u_int alen, blen, slen;
604         int pktype;
605         int authenticated = 0;
606
607         if (!authctxt->valid) {
608                 debug2("userauth_hostbased: disabled because of invalid user");
609                 return 0;
610         }
611         pkalg = packet_get_string(&alen);
612         pkblob = packet_get_string(&blen);
613         chost = packet_get_string(NULL);
614         cuser = packet_get_string(NULL);
615         sig = packet_get_string(&slen);
616
617         debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
618             cuser, chost, pkalg, slen);
619 #ifdef DEBUG_PK
620         debug("signature:");
621         buffer_init(&b);
622         buffer_append(&b, sig, slen);
623         buffer_dump(&b);
624         buffer_free(&b);
625 #endif
626         pktype = key_type_from_name(pkalg);
627         if (pktype == KEY_UNSPEC) {
628                 /* this is perfectly legal */
629                 log("userauth_hostbased: unsupported "
630                     "public key algorithm: %s", pkalg);
631                 goto done;
632         }
633         key = key_from_blob(pkblob, blen);
634         if (key == NULL) {
635                 error("userauth_hostbased: cannot decode key: %s", pkalg);
636                 goto done;
637         }
638         if (key->type != pktype) {
639                 error("userauth_hostbased: type mismatch for decoded key "
640                     "(received %d, expected %d)", key->type, pktype);
641                 goto done;
642         }
643         service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
644             authctxt->service;
645         buffer_init(&b);
646         buffer_put_string(&b, session_id2, session_id2_len);
647         /* reconstruct packet */
648         buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
649         buffer_put_cstring(&b, authctxt->user);
650         buffer_put_cstring(&b, service);
651         buffer_put_cstring(&b, "hostbased");
652         buffer_put_string(&b, pkalg, alen);
653         buffer_put_string(&b, pkblob, blen);
654         buffer_put_cstring(&b, chost);
655         buffer_put_cstring(&b, cuser);
656 #ifdef DEBUG_PK
657         buffer_dump(&b);
658 #endif
659         /* test for allowed key and correct signature */
660         if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
661             key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
662                 authenticated = 1;
663
664         buffer_clear(&b);
665 done:
666         debug2("userauth_hostbased: authenticated %d", authenticated);
667         if (key != NULL)
668                 key_free(key);
669         xfree(pkalg);
670         xfree(pkblob);
671         xfree(cuser);
672         xfree(chost);
673         xfree(sig);
674         return authenticated;
675 }
676
677 /* get current user */
678
679 struct passwd*
680 auth_get_user(void)
681 {
682         return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
683 }
684
685 #define DELIM   ","
686
687 static char *
688 authmethods_get(void)
689 {
690         Authmethod *method = NULL;
691         Buffer b;
692         char *list;
693
694         buffer_init(&b);
695         for (method = authmethods; method->name != NULL; method++) {
696                 if (strcmp(method->name, "none") == 0)
697                         continue;
698                 if (method->enabled != NULL && *(method->enabled) != 0) {
699                         if (buffer_len(&b) > 0)
700                                 buffer_append(&b, ",", 1);
701                         buffer_append(&b, method->name, strlen(method->name));
702                 }
703         }
704         buffer_append(&b, "\0", 1);
705         list = xstrdup(buffer_ptr(&b));
706         buffer_free(&b);
707         return list;
708 }
709
710 static Authmethod *
711 authmethod_lookup(const char *name)
712 {
713         Authmethod *method = NULL;
714         if (name != NULL)
715                 for (method = authmethods; method->name != NULL; method++)
716                         if (method->enabled != NULL &&
717                             *(method->enabled) != 0 &&
718                             strcmp(name, method->name) == 0)
719                                 return method;
720         debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
721         return NULL;
722 }
723
724 /* return 1 if user allows given key */
725 static int
726 user_key_allowed2(struct passwd *pw, Key *key, char *file)
727 {
728         char line[8192];
729         int found_key = 0;
730         FILE *f;
731         u_long linenum = 0;
732         struct stat st;
733         Key *found;
734         char *fp;
735
736         if (pw == NULL)
737                 return 0;
738
739         /* Temporarily use the user's uid. */
740         temporarily_use_uid(pw);
741
742         debug("trying public key file %s", file);
743
744         /* Fail quietly if file does not exist */
745         if (stat(file, &st) < 0) {
746                 /* Restore the privileged uid. */
747                 restore_uid();
748                 return 0;
749         }
750         /* Open the file containing the authorized keys. */
751         f = fopen(file, "r");
752         if (!f) {
753                 /* Restore the privileged uid. */
754                 restore_uid();
755                 return 0;
756         }
757         if (options.strict_modes &&
758             secure_filename(f, file, pw, line, sizeof(line)) != 0) {
759                 fclose(f);
760                 log("Authentication refused: %s", line);
761                 restore_uid();
762                 return 0;
763         }
764
765         found_key = 0;
766         found = key_new(key->type);
767
768         while (fgets(line, sizeof(line), f)) {
769                 char *cp, *options = NULL;
770                 linenum++;
771                 /* Skip leading whitespace, empty and comment lines. */
772                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
773                         ;
774                 if (!*cp || *cp == '\n' || *cp == '#')
775                         continue;
776
777                 if (key_read(found, &cp) != 1) {
778                         /* no key?  check if there are options for this key */
779                         int quoted = 0;
780                         debug2("user_key_allowed: check options: '%s'", cp);
781                         options = cp;
782                         for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
783                                 if (*cp == '\\' && cp[1] == '"')
784                                         cp++;   /* Skip both */
785                                 else if (*cp == '"')
786                                         quoted = !quoted;
787                         }
788                         /* Skip remaining whitespace. */
789                         for (; *cp == ' ' || *cp == '\t'; cp++)
790                                 ;
791                         if (key_read(found, &cp) != 1) {
792                                 debug2("user_key_allowed: advance: '%s'", cp);
793                                 /* still no key?  advance to next line*/
794                                 continue;
795                         }
796                 }
797                 if (key_equal(found, key) &&
798                     auth_parse_options(pw, options, file, linenum) == 1) {
799                         found_key = 1;
800                         debug("matching key found: file %s, line %lu",
801                             file, linenum);
802                         fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
803                         verbose("Found matching %s key: %s",
804                             key_type(found), fp);
805                         xfree(fp);
806                         break;
807                 }
808         }
809         restore_uid();
810         fclose(f);
811         key_free(found);
812         if (!found_key)
813                 debug2("key not found");
814         return found_key;
815 }
816
817 /* check whether given key is in .ssh/authorized_keys* */
818 static int
819 user_key_allowed(struct passwd *pw, Key *key)
820 {
821         int success;
822         char *file;
823
824         file = authorized_keys_file(pw);
825         success = user_key_allowed2(pw, key, file);
826         xfree(file);
827         if (success)
828                 return success;
829
830         /* try suffix "2" for backward compat, too */
831         file = authorized_keys_file2(pw);
832         success = user_key_allowed2(pw, key, file);
833         xfree(file);
834         return success;
835 }
836
837 /* return 1 if given hostkey is allowed */
838 static int
839 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
840     Key *key)
841 {
842         const char *resolvedname, *ipaddr, *lookup;
843         HostStatus host_status;
844         int len;
845
846         resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
847         ipaddr = get_remote_ipaddr();
848
849         debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
850             chost, resolvedname, ipaddr);
851
852         if (options.hostbased_uses_name_from_packet_only) {
853                 if (auth_rhosts2(pw, cuser, chost, chost) == 0)
854                         return 0;
855                 lookup = chost;
856         } else {
857                 if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
858                         debug2("stripping trailing dot from chost %s", chost);
859                         chost[len - 1] = '\0';
860                 }
861                 if (strcasecmp(resolvedname, chost) != 0)
862                         log("userauth_hostbased mismatch: "
863                             "client sends %s, but we resolve %s to %s",
864                             chost, ipaddr, resolvedname);
865                 if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
866                         return 0;
867                 lookup = resolvedname;
868         }
869         debug2("userauth_hostbased: access allowed by auth_rhosts2");
870
871         host_status = check_key_in_hostfiles(pw, key, lookup,
872             _PATH_SSH_SYSTEM_HOSTFILE,
873             options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
874
875         /* backward compat if no key has been found. */
876         if (host_status == HOST_NEW)
877                 host_status = check_key_in_hostfiles(pw, key, lookup,
878                     _PATH_SSH_SYSTEM_HOSTFILE2,
879                     options.ignore_user_known_hosts ? NULL :
880                     _PATH_SSH_USER_HOSTFILE2);
881
882         return (host_status == HOST_OK);
883 }
This page took 0.114955 seconds and 5 git commands to generate.