Branch data Line data Source code
1 : : /* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm 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 : : #include <stdarg.h>
33 : :
34 : : #include "xmalloc.h"
35 : : #include "ssh2.h"
36 : : #include "packet.h"
37 : : #include "buffer.h"
38 : : #include "log.h"
39 : : #include "servconf.h"
40 : : #include "compat.h"
41 : : #include "key.h"
42 : : #include "hostfile.h"
43 : : #include "auth.h"
44 : : #include "canohost.h"
45 : : #ifdef GSSAPI
46 : : #include "ssh-gss.h"
47 : : #endif
48 : : #include "monitor_wrap.h"
49 : : #include "pathnames.h"
50 : :
51 : : /* import */
52 : : extern ServerOptions options;
53 : : extern u_char *session_id2;
54 : : extern u_int session_id2_len;
55 : :
56 : : static int
57 : 0 : userauth_hostbased(Authctxt *authctxt)
58 : : {
59 : : Buffer b;
60 : 0 : Key *key = NULL;
61 : : char *pkalg, *cuser, *chost, *service;
62 : : u_char *pkblob, *sig;
63 : : u_int alen, blen, slen;
64 : : int pktype;
65 : 0 : int authenticated = 0;
66 : :
67 [ # # ]: 0 : if (!authctxt->valid) {
68 : 0 : debug2("userauth_hostbased: disabled because of invalid user");
69 : 0 : return 0;
70 : : }
71 : 0 : pkalg = packet_get_string(&alen);
72 : 0 : pkblob = packet_get_string(&blen);
73 : 0 : chost = packet_get_string(NULL);
74 : 0 : cuser = packet_get_string(NULL);
75 : 0 : sig = packet_get_string(&slen);
76 : :
77 : 0 : debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
78 : : cuser, chost, pkalg, slen);
79 : : #ifdef DEBUG_PK
80 : : debug("signature:");
81 : : buffer_init(&b);
82 : : buffer_append(&b, sig, slen);
83 : : buffer_dump(&b);
84 : : buffer_free(&b);
85 : : #endif
86 : 0 : pktype = key_type_from_name(pkalg);
87 [ # # ]: 0 : if (pktype == KEY_UNSPEC) {
88 : : /* this is perfectly legal */
89 : 0 : logit("userauth_hostbased: unsupported "
90 : : "public key algorithm: %s", pkalg);
91 : 0 : goto done;
92 : : }
93 : 0 : key = key_from_blob(pkblob, blen);
94 [ # # ]: 0 : if (key == NULL) {
95 : 0 : error("userauth_hostbased: cannot decode key: %s", pkalg);
96 : 0 : goto done;
97 : : }
98 [ # # ]: 0 : if (key->type != pktype) {
99 : 0 : error("userauth_hostbased: type mismatch for decoded key "
100 : : "(received %d, expected %d)", key->type, pktype);
101 : 0 : goto done;
102 : : }
103 [ # # ][ # # ]: 0 : if (key_type_plain(key->type) == KEY_RSA &&
104 : 0 : (datafellows & SSH_BUG_RSASIGMD5) != 0) {
105 : 0 : error("Refusing RSA key because peer uses unsafe "
106 : : "signature format");
107 : 0 : goto done;
108 : : }
109 [ # # ]: 0 : service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
110 : : authctxt->service;
111 : 0 : buffer_init(&b);
112 : 0 : buffer_put_string(&b, session_id2, session_id2_len);
113 : : /* reconstruct packet */
114 : 0 : buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
115 : 0 : buffer_put_cstring(&b, authctxt->user);
116 : 0 : buffer_put_cstring(&b, service);
117 : 0 : buffer_put_cstring(&b, "hostbased");
118 : 0 : buffer_put_string(&b, pkalg, alen);
119 : 0 : buffer_put_string(&b, pkblob, blen);
120 : 0 : buffer_put_cstring(&b, chost);
121 : 0 : buffer_put_cstring(&b, cuser);
122 : : #ifdef DEBUG_PK
123 : : buffer_dump(&b);
124 : : #endif
125 : :
126 : 0 : pubkey_auth_info(authctxt, key,
127 : : "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
128 : :
129 : : /* test for allowed key and correct signature */
130 : 0 : authenticated = 0;
131 [ # # ][ # # ]: 0 : if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
[ # # ]
132 : 0 : PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
133 [ # # ]: 0 : buffer_len(&b))) == 1)
134 : 0 : authenticated = 1;
135 : :
136 : 0 : buffer_free(&b);
137 : : done:
138 : 0 : debug2("userauth_hostbased: authenticated %d", authenticated);
139 [ # # ]: 0 : if (key != NULL)
140 : 0 : key_free(key);
141 : 0 : free(pkalg);
142 : 0 : free(pkblob);
143 : 0 : free(cuser);
144 : 0 : free(chost);
145 : 0 : free(sig);
146 : 0 : return authenticated;
147 : : }
148 : :
149 : : /* return 1 if given hostkey is allowed */
150 : : int
151 : 0 : hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
152 : : Key *key)
153 : : {
154 : : const char *resolvedname, *ipaddr, *lookup, *reason;
155 : : HostStatus host_status;
156 : : int len;
157 : : char *fp;
158 : :
159 [ # # ]: 0 : if (auth_key_is_revoked(key))
160 : : return 0;
161 : :
162 : 0 : resolvedname = get_canonical_hostname(options.use_dns);
163 : 0 : ipaddr = get_remote_ipaddr();
164 : :
165 : 0 : debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
166 : : chost, resolvedname, ipaddr);
167 : :
168 [ # # ][ # # ]: 0 : if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
169 : 0 : debug2("stripping trailing dot from chost %s", chost);
170 : 0 : chost[len - 1] = '\0';
171 : : }
172 : :
173 [ # # ]: 0 : if (options.hostbased_uses_name_from_packet_only) {
174 [ # # ]: 0 : if (auth_rhosts2(pw, cuser, chost, chost) == 0)
175 : : return 0;
176 : : lookup = chost;
177 : : } else {
178 [ # # ]: 0 : if (strcasecmp(resolvedname, chost) != 0)
179 : 0 : logit("userauth_hostbased mismatch: "
180 : : "client sends %s, but we resolve %s to %s",
181 : : chost, ipaddr, resolvedname);
182 [ # # ]: 0 : if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
183 : : return 0;
184 : : lookup = resolvedname;
185 : : }
186 : 0 : debug2("userauth_hostbased: access allowed by auth_rhosts2");
187 : :
188 [ # # # # ]: 0 : if (key_is_cert(key) &&
189 : 0 : key_cert_check_authority(key, 1, 0, lookup, &reason)) {
190 : 0 : error("%s", reason);
191 : 0 : auth_debug_add("%s", reason);
192 : 0 : return 0;
193 : : }
194 : :
195 [ # # ]: 0 : host_status = check_key_in_hostfiles(pw, key, lookup,
196 : : _PATH_SSH_SYSTEM_HOSTFILE,
197 : 0 : options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
198 : :
199 : : /* backward compat if no key has been found. */
200 [ # # ]: 0 : if (host_status == HOST_NEW) {
201 [ # # ]: 0 : host_status = check_key_in_hostfiles(pw, key, lookup,
202 : : _PATH_SSH_SYSTEM_HOSTFILE2,
203 : 0 : options.ignore_user_known_hosts ? NULL :
204 : : _PATH_SSH_USER_HOSTFILE2);
205 : : }
206 : :
207 [ # # ]: 0 : if (host_status == HOST_OK) {
208 [ # # ]: 0 : if (key_is_cert(key)) {
209 : 0 : fp = key_fingerprint(key->cert->signature_key,
210 : : SSH_FP_MD5, SSH_FP_HEX);
211 : 0 : verbose("Accepted certificate ID \"%s\" signed by "
212 : 0 : "%s CA %s from %s@%s", key->cert->key_id,
213 : 0 : key_type(key->cert->signature_key), fp,
214 : : cuser, lookup);
215 : : } else {
216 : 0 : fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
217 : 0 : verbose("Accepted %s public key %s from %s@%s",
218 : : key_type(key), fp, cuser, lookup);
219 : : }
220 : 0 : free(fp);
221 : : }
222 : :
223 : 0 : return (host_status == HOST_OK);
224 : : }
225 : :
226 : : Authmethod method_hostbased = {
227 : : "hostbased",
228 : : userauth_hostbased,
229 : : &options.hostbased_authentication
230 : : };
|