Annotation of src/usr.bin/ssh/auth2-hostbased.c, Revision 1.7
1.1 markus 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:
27: #include "ssh2.h"
28: #include "xmalloc.h"
29: #include "packet.h"
30: #include "buffer.h"
31: #include "log.h"
32: #include "servconf.h"
33: #include "compat.h"
34: #include "bufaux.h"
35: #include "auth.h"
36: #include "key.h"
37: #include "canohost.h"
38: #include "monitor_wrap.h"
39: #include "pathnames.h"
40:
41: /* import */
42: extern ServerOptions options;
43: extern u_char *session_id2;
1.5 markus 44: extern u_int session_id2_len;
1.1 markus 45:
1.2 markus 46: static int
1.1 markus 47: userauth_hostbased(Authctxt *authctxt)
48: {
49: Buffer b;
50: Key *key = NULL;
51: char *pkalg, *cuser, *chost, *service;
52: u_char *pkblob, *sig;
53: u_int alen, blen, slen;
54: int pktype;
55: int authenticated = 0;
56:
57: if (!authctxt->valid) {
58: debug2("userauth_hostbased: disabled because of invalid user");
59: return 0;
60: }
61: pkalg = packet_get_string(&alen);
62: pkblob = packet_get_string(&blen);
63: chost = packet_get_string(NULL);
64: cuser = packet_get_string(NULL);
65: sig = packet_get_string(&slen);
66:
67: debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
68: cuser, chost, pkalg, slen);
69: #ifdef DEBUG_PK
70: debug("signature:");
71: buffer_init(&b);
72: buffer_append(&b, sig, slen);
73: buffer_dump(&b);
74: buffer_free(&b);
75: #endif
76: pktype = key_type_from_name(pkalg);
77: if (pktype == KEY_UNSPEC) {
78: /* this is perfectly legal */
1.3 itojun 79: logit("userauth_hostbased: unsupported "
1.1 markus 80: "public key algorithm: %s", pkalg);
81: goto done;
82: }
83: key = key_from_blob(pkblob, blen);
84: if (key == NULL) {
85: error("userauth_hostbased: cannot decode key: %s", pkalg);
86: goto done;
87: }
88: if (key->type != pktype) {
89: error("userauth_hostbased: type mismatch for decoded key "
90: "(received %d, expected %d)", key->type, pktype);
91: goto done;
92: }
93: service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
94: authctxt->service;
95: buffer_init(&b);
96: buffer_put_string(&b, session_id2, session_id2_len);
97: /* reconstruct packet */
98: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
99: buffer_put_cstring(&b, authctxt->user);
100: buffer_put_cstring(&b, service);
101: buffer_put_cstring(&b, "hostbased");
102: buffer_put_string(&b, pkalg, alen);
103: buffer_put_string(&b, pkblob, blen);
104: buffer_put_cstring(&b, chost);
105: buffer_put_cstring(&b, cuser);
106: #ifdef DEBUG_PK
107: buffer_dump(&b);
108: #endif
109: /* test for allowed key and correct signature */
110: authenticated = 0;
111: if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
112: PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
113: buffer_len(&b))) == 1)
114: authenticated = 1;
115:
1.6 markus 116: buffer_free(&b);
1.1 markus 117: done:
118: debug2("userauth_hostbased: authenticated %d", authenticated);
119: if (key != NULL)
120: key_free(key);
121: xfree(pkalg);
122: xfree(pkblob);
123: xfree(cuser);
124: xfree(chost);
125: xfree(sig);
126: return authenticated;
127: }
128:
129: /* return 1 if given hostkey is allowed */
130: int
131: hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
132: Key *key)
133: {
134: const char *resolvedname, *ipaddr, *lookup;
135: HostStatus host_status;
136: int len;
137:
1.4 markus 138: resolvedname = get_canonical_hostname(options.use_dns);
1.1 markus 139: ipaddr = get_remote_ipaddr();
140:
141: debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
142: chost, resolvedname, ipaddr);
143:
144: if (options.hostbased_uses_name_from_packet_only) {
145: if (auth_rhosts2(pw, cuser, chost, chost) == 0)
146: return 0;
147: lookup = chost;
148: } else {
149: if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
150: debug2("stripping trailing dot from chost %s", chost);
151: chost[len - 1] = '\0';
152: }
153: if (strcasecmp(resolvedname, chost) != 0)
1.3 itojun 154: logit("userauth_hostbased mismatch: "
1.1 markus 155: "client sends %s, but we resolve %s to %s",
156: chost, ipaddr, resolvedname);
157: if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
158: return 0;
159: lookup = resolvedname;
160: }
161: debug2("userauth_hostbased: access allowed by auth_rhosts2");
162:
163: host_status = check_key_in_hostfiles(pw, key, lookup,
164: _PATH_SSH_SYSTEM_HOSTFILE,
165: options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
166:
167: /* backward compat if no key has been found. */
168: if (host_status == HOST_NEW)
169: host_status = check_key_in_hostfiles(pw, key, lookup,
170: _PATH_SSH_SYSTEM_HOSTFILE2,
171: options.ignore_user_known_hosts ? NULL :
172: _PATH_SSH_USER_HOSTFILE2);
173:
174: return (host_status == HOST_OK);
175: }
1.2 markus 176:
177: Authmethod method_hostbased = {
178: "hostbased",
179: userauth_hostbased,
180: &options.hostbased_authentication
181: };