]> andersk Git - openssh.git/blob - auth2-hostbased.c
- stevesk@cvs.openbsd.org 2006/07/22 20:48:23
[openssh.git] / auth2-hostbased.c
1 /* $OpenBSD: auth2-hostbased.c,v 1.10 2006/07/22 20:48:22 stevesk Exp $ */
2 /*
3  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "includes.h"
27
28 #include <sys/types.h>
29
30 #include <pwd.h>
31 #include <string.h>
32
33 #include "ssh2.h"
34 #include "xmalloc.h"
35 #include "packet.h"
36 #include "buffer.h"
37 #include "log.h"
38 #include "servconf.h"
39 #include "compat.h"
40 #include "bufaux.h"
41 #include "auth.h"
42 #include "key.h"
43 #include "canohost.h"
44 #include "monitor_wrap.h"
45 #include "pathnames.h"
46
47 /* import */
48 extern ServerOptions options;
49 extern u_char *session_id2;
50 extern u_int session_id2_len;
51
52 static int
53 userauth_hostbased(Authctxt *authctxt)
54 {
55         Buffer b;
56         Key *key = NULL;
57         char *pkalg, *cuser, *chost, *service;
58         u_char *pkblob, *sig;
59         u_int alen, blen, slen;
60         int pktype;
61         int authenticated = 0;
62
63         if (!authctxt->valid) {
64                 debug2("userauth_hostbased: disabled because of invalid user");
65                 return 0;
66         }
67         pkalg = packet_get_string(&alen);
68         pkblob = packet_get_string(&blen);
69         chost = packet_get_string(NULL);
70         cuser = packet_get_string(NULL);
71         sig = packet_get_string(&slen);
72
73         debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
74             cuser, chost, pkalg, slen);
75 #ifdef DEBUG_PK
76         debug("signature:");
77         buffer_init(&b);
78         buffer_append(&b, sig, slen);
79         buffer_dump(&b);
80         buffer_free(&b);
81 #endif
82         pktype = key_type_from_name(pkalg);
83         if (pktype == KEY_UNSPEC) {
84                 /* this is perfectly legal */
85                 logit("userauth_hostbased: unsupported "
86                     "public key algorithm: %s", pkalg);
87                 goto done;
88         }
89         key = key_from_blob(pkblob, blen);
90         if (key == NULL) {
91                 error("userauth_hostbased: cannot decode key: %s", pkalg);
92                 goto done;
93         }
94         if (key->type != pktype) {
95                 error("userauth_hostbased: type mismatch for decoded key "
96                     "(received %d, expected %d)", key->type, pktype);
97                 goto done;
98         }
99         service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
100             authctxt->service;
101         buffer_init(&b);
102         buffer_put_string(&b, session_id2, session_id2_len);
103         /* reconstruct packet */
104         buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
105         buffer_put_cstring(&b, authctxt->user);
106         buffer_put_cstring(&b, service);
107         buffer_put_cstring(&b, "hostbased");
108         buffer_put_string(&b, pkalg, alen);
109         buffer_put_string(&b, pkblob, blen);
110         buffer_put_cstring(&b, chost);
111         buffer_put_cstring(&b, cuser);
112 #ifdef DEBUG_PK
113         buffer_dump(&b);
114 #endif
115         /* test for allowed key and correct signature */
116         authenticated = 0;
117         if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
118             PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
119                         buffer_len(&b))) == 1)
120                 authenticated = 1;
121
122         buffer_free(&b);
123 done:
124         debug2("userauth_hostbased: authenticated %d", authenticated);
125         if (key != NULL)
126                 key_free(key);
127         xfree(pkalg);
128         xfree(pkblob);
129         xfree(cuser);
130         xfree(chost);
131         xfree(sig);
132         return authenticated;
133 }
134
135 /* return 1 if given hostkey is allowed */
136 int
137 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
138     Key *key)
139 {
140         const char *resolvedname, *ipaddr, *lookup;
141         HostStatus host_status;
142         int len;
143
144         resolvedname = get_canonical_hostname(options.use_dns);
145         ipaddr = get_remote_ipaddr();
146
147         debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
148             chost, resolvedname, ipaddr);
149
150         if (options.hostbased_uses_name_from_packet_only) {
151                 if (auth_rhosts2(pw, cuser, chost, chost) == 0)
152                         return 0;
153                 lookup = chost;
154         } else {
155                 if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
156                         debug2("stripping trailing dot from chost %s", chost);
157                         chost[len - 1] = '\0';
158                 }
159                 if (strcasecmp(resolvedname, chost) != 0)
160                         logit("userauth_hostbased mismatch: "
161                             "client sends %s, but we resolve %s to %s",
162                             chost, ipaddr, resolvedname);
163                 if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
164                         return 0;
165                 lookup = resolvedname;
166         }
167         debug2("userauth_hostbased: access allowed by auth_rhosts2");
168
169         host_status = check_key_in_hostfiles(pw, key, lookup,
170             _PATH_SSH_SYSTEM_HOSTFILE,
171             options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
172
173         /* backward compat if no key has been found. */
174         if (host_status == HOST_NEW)
175                 host_status = check_key_in_hostfiles(pw, key, lookup,
176                     _PATH_SSH_SYSTEM_HOSTFILE2,
177                     options.ignore_user_known_hosts ? NULL :
178                     _PATH_SSH_USER_HOSTFILE2);
179
180         return (host_status == HOST_OK);
181 }
182
183 Authmethod method_hostbased = {
184         "hostbased",
185         userauth_hostbased,
186         &options.hostbased_authentication
187 };
This page took 0.061448 seconds and 5 git commands to generate.