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