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