auth2-hostbased.c revision 181110
1168404Spjd/* $OpenBSD: auth2-hostbased.c,v 1.11 2006/08/03 03:34:41 deraadt Exp $ */ 2168404Spjd/* 3168404Spjd * Copyright (c) 2000 Markus Friedl. All rights reserved. 4168404Spjd * 5168404Spjd * Redistribution and use in source and binary forms, with or without 6168404Spjd * modification, are permitted provided that the following conditions 7168404Spjd * are met: 8168404Spjd * 1. Redistributions of source code must retain the above copyright 9168404Spjd * notice, this list of conditions and the following disclaimer. 10168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 11168404Spjd * notice, this list of conditions and the following disclaimer in the 12168404Spjd * documentation and/or other materials provided with the distribution. 13168404Spjd * 14168404Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15168404Spjd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16168404Spjd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17168404Spjd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18168404Spjd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19168404Spjd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20168404Spjd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21168404Spjd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22200724Sdelphij * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23168404Spjd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24168404Spjd */ 25168404Spjd 26168404Spjd#include "includes.h" 27263398Sdelphij 28263398Sdelphij#include <sys/types.h> 29263398Sdelphij 30263398Sdelphij#include <pwd.h> 31168404Spjd#include <string.h> 32168404Spjd#include <stdarg.h> 33168404Spjd 34168404Spjd#include "xmalloc.h" 35168404Spjd#include "ssh2.h" 36168404Spjd#include "packet.h" 37168404Spjd#include "buffer.h" 38168404Spjd#include "log.h" 39168404Spjd#include "servconf.h" 40168404Spjd#include "compat.h" 41168404Spjd#include "key.h" 42168404Spjd#include "hostfile.h" 43168404Spjd#include "auth.h" 44168404Spjd#include "canohost.h" 45168404Spjd#ifdef GSSAPI 46168404Spjd#include "ssh-gss.h" 47219089Spjd#endif 48219089Spjd#include "monitor_wrap.h" 49168404Spjd#include "pathnames.h" 50168404Spjd 51168404Spjd/* import */ 52168404Spjdextern ServerOptions options; 53168404Spjdextern u_char *session_id2; 54263398Sdelphijextern u_int session_id2_len; 55168404Spjd 56168404Spjdstatic int 57168404Spjduserauth_hostbased(Authctxt *authctxt) 58168404Spjd{ 59168404Spjd Buffer b; 60168404Spjd Key *key = NULL; 61168404Spjd char *pkalg, *cuser, *chost, *service; 62168404Spjd u_char *pkblob, *sig; 63219089Spjd u_int alen, blen, slen; 64219089Spjd int pktype; 65168404Spjd int authenticated = 0; 66219089Spjd 67168404Spjd if (!authctxt->valid) { 68219089Spjd debug2("userauth_hostbased: disabled because of invalid user"); 69219089Spjd return 0; 70219089Spjd } 71219089Spjd pkalg = packet_get_string(&alen); 72219089Spjd pkblob = packet_get_string(&blen); 73219089Spjd chost = packet_get_string(NULL); 74219089Spjd cuser = packet_get_string(NULL); 75219089Spjd sig = packet_get_string(&slen); 76219089Spjd 77219089Spjd debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", 78219089Spjd cuser, chost, pkalg, slen); 79219089Spjd#ifdef DEBUG_PK 80219089Spjd debug("signature:"); 81219089Spjd buffer_init(&b); 82219089Spjd buffer_append(&b, sig, slen); 83168404Spjd buffer_dump(&b); 84168404Spjd buffer_free(&b); 85219089Spjd#endif 86168404Spjd pktype = key_type_from_name(pkalg); 87168404Spjd if (pktype == KEY_UNSPEC) { 88168404Spjd /* this is perfectly legal */ 89168404Spjd logit("userauth_hostbased: unsupported " 90168404Spjd "public key algorithm: %s", pkalg); 91168404Spjd goto done; 92168404Spjd } 93168404Spjd key = key_from_blob(pkblob, blen); 94219089Spjd if (key == NULL) { 95168404Spjd error("userauth_hostbased: cannot decode key: %s", pkalg); 96168404Spjd goto done; 97168404Spjd } 98168404Spjd if (key->type != pktype) { 99168404Spjd error("userauth_hostbased: type mismatch for decoded key " 100168404Spjd "(received %d, expected %d)", key->type, pktype); 101168404Spjd goto done; 102219089Spjd } 103168404Spjd service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : 104168404Spjd authctxt->service; 105168404Spjd buffer_init(&b); 106168404Spjd buffer_put_string(&b, session_id2, session_id2_len); 107168404Spjd /* reconstruct packet */ 108168404Spjd buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 109168404Spjd buffer_put_cstring(&b, authctxt->user); 110168404Spjd buffer_put_cstring(&b, service); 111168404Spjd buffer_put_cstring(&b, "hostbased"); 112168404Spjd buffer_put_string(&b, pkalg, alen); 113168404Spjd buffer_put_string(&b, pkblob, blen); 114219089Spjd buffer_put_cstring(&b, chost); 115168404Spjd buffer_put_cstring(&b, cuser); 116219089Spjd#ifdef DEBUG_PK 117168404Spjd buffer_dump(&b); 118168404Spjd#endif 119168404Spjd /* test for allowed key and correct signature */ 120168404Spjd authenticated = 0; 121168404Spjd if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && 122168404Spjd PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), 123168404Spjd buffer_len(&b))) == 1) 124168404Spjd authenticated = 1; 125219089Spjd 126168404Spjd buffer_free(&b); 127168404Spjddone: 128168404Spjd debug2("userauth_hostbased: authenticated %d", authenticated); 129168404Spjd if (key != NULL) 130219089Spjd key_free(key); 131219089Spjd xfree(pkalg); 132219089Spjd xfree(pkblob); 133168404Spjd xfree(cuser); 134209962Smm xfree(chost); 135168404Spjd xfree(sig); 136168404Spjd return authenticated; 137168404Spjd} 138219089Spjd 139263398Sdelphij/* return 1 if given hostkey is allowed */ 140168404Spjdint 141168404Spjdhostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, 142219089Spjd Key *key) 143219089Spjd{ 144209962Smm const char *resolvedname, *ipaddr, *lookup; 145209962Smm HostStatus host_status; 146209962Smm int len; 147168404Spjd 148219089Spjd resolvedname = get_canonical_hostname(options.use_dns); 149219089Spjd ipaddr = get_remote_ipaddr(); 150219089Spjd 151219089Spjd debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", 152219089Spjd chost, resolvedname, ipaddr); 153219089Spjd 154219089Spjd if (options.hostbased_uses_name_from_packet_only) { 155168404Spjd if (auth_rhosts2(pw, cuser, chost, chost) == 0) 156219089Spjd return 0; 157219089Spjd lookup = chost; 158219089Spjd } else { 159168404Spjd if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { 160219089Spjd debug2("stripping trailing dot from chost %s", chost); 161219089Spjd chost[len - 1] = '\0'; 162219089Spjd } 163219089Spjd if (strcasecmp(resolvedname, chost) != 0) 164219089Spjd logit("userauth_hostbased mismatch: " 165219089Spjd "client sends %s, but we resolve %s to %s", 166168404Spjd chost, ipaddr, resolvedname); 167168404Spjd if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) 168168404Spjd return 0; 169168404Spjd lookup = resolvedname; 170168404Spjd } 171168404Spjd debug2("userauth_hostbased: access allowed by auth_rhosts2"); 172168404Spjd 173219089Spjd host_status = check_key_in_hostfiles(pw, key, lookup, 174168404Spjd _PATH_SSH_SYSTEM_HOSTFILE, 175168404Spjd options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); 176168404Spjd 177168404Spjd /* backward compat if no key has been found. */ 178168404Spjd if (host_status == HOST_NEW) 179168404Spjd host_status = check_key_in_hostfiles(pw, key, lookup, 180168404Spjd _PATH_SSH_SYSTEM_HOSTFILE2, 181168404Spjd options.ignore_user_known_hosts ? NULL : 182168404Spjd _PATH_SSH_USER_HOSTFILE2); 183168404Spjd 184168404Spjd return (host_status == HOST_OK); 185168404Spjd} 186168404Spjd 187168404SpjdAuthmethod method_hostbased = { 188219089Spjd "hostbased", 189168404Spjd userauth_hostbased, 190168404Spjd &options.hostbased_authentication 191168404Spjd}; 192168404Spjd