diff options
Diffstat (limited to 'usr.bin/ssh/sshd.c')
-rw-r--r-- | usr.bin/ssh/sshd.c | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c index 76b7f2535be..c0b09330224 100644 --- a/usr.bin/ssh/sshd.c +++ b/usr.bin/ssh/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.403 2013/06/05 02:27:50 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.404 2013/07/19 07:37:48 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -90,6 +90,7 @@ #include "canohost.h" #include "hostfile.h" #include "auth.h" +#include "authfd.h" #include "misc.h" #include "msg.h" #include "dispatch.h" @@ -177,6 +178,10 @@ char *server_version_string = NULL; /* for rekeying XXX fixme */ Kex *xxx_kex; +/* Daemon's agent connection */ +AuthenticationConnection *auth_conn = NULL; +int have_agent = 0; + /* * Any really sensitive data in the application is contained in this * structure. The idea is that this structure could be locked into memory so @@ -189,6 +194,7 @@ struct { Key *server_key; /* ephemeral server key */ Key *ssh1_host_key; /* ssh1 host key */ Key **host_keys; /* all private host keys */ + Key **host_pubkeys; /* all public host keys */ Key **host_certificates; /* all public host certificates */ int have_ssh1_key; int have_ssh2_key; @@ -640,6 +646,8 @@ privsep_preauth(Authctxt *authctxt) debug2("Network child is on pid %ld", (long)pid); pmonitor->m_pid = pid; + if (have_agent) + auth_conn = ssh_get_authentication_connection(); if (box != NULL) ssh_sandbox_parent_preauth(box, pid); monitor_child_preauth(authctxt, pmonitor); @@ -750,6 +758,8 @@ list_hostkey_types(void) for (i = 0; i < options.num_host_key_files; i++) { key = sensitive_data.host_keys[i]; if (key == NULL) + key = sensitive_data.host_pubkeys[i]; + if (key == NULL) continue; switch (key->type) { case KEY_RSA: @@ -802,6 +812,8 @@ get_hostkey_by_type(int type, int need_private) break; default: key = sensitive_data.host_keys[i]; + if (key == NULL && !need_private) + key = sensitive_data.host_pubkeys[i]; break; } if (key != NULL && key->type == type) @@ -831,6 +843,14 @@ get_hostkey_by_index(int ind) return (sensitive_data.host_keys[ind]); } +Key * +get_hostkey_public_by_index(int ind) +{ + if (ind < 0 || ind >= options.num_host_key_files) + return (NULL); + return (sensitive_data.host_pubkeys[ind]); +} + int get_hostkey_index(Key *key) { @@ -843,6 +863,8 @@ get_hostkey_index(Key *key) } else { if (key == sensitive_data.host_keys[i]) return (i); + if (key == sensitive_data.host_pubkeys[i]) + return (i); } } return (-1); @@ -1310,6 +1332,8 @@ main(int ac, char **av) u_int64_t ibytes, obytes; mode_t new_umask; Key *key; + Key *pubkey; + int keytype; Authctxt *authctxt; struct connection_info *connection_info = get_connection_info(0, 0); @@ -1542,22 +1566,45 @@ main(int ac, char **av) debug("sshd version %s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); - /* load private host keys */ + /* load host keys */ sensitive_data.host_keys = xcalloc(options.num_host_key_files, sizeof(Key *)); - for (i = 0; i < options.num_host_key_files; i++) + sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, + sizeof(Key *)); + for (i = 0; i < options.num_host_key_files; i++) { sensitive_data.host_keys[i] = NULL; + sensitive_data.host_pubkeys[i] = NULL; + } + + if (options.host_key_agent) { + if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) + setenv(SSH_AUTHSOCKET_ENV_NAME, + options.host_key_agent, 1); + have_agent = ssh_agent_present(); + } for (i = 0; i < options.num_host_key_files; i++) { key = key_load_private(options.host_key_files[i], "", NULL); + pubkey = key_load_public(options.host_key_files[i], NULL); sensitive_data.host_keys[i] = key; - if (key == NULL) { + sensitive_data.host_pubkeys[i] = pubkey; + + if (key == NULL && pubkey != NULL && pubkey->type != KEY_RSA1 && + have_agent) { + debug("will rely on agent for hostkey %s", + options.host_key_files[i]); + keytype = pubkey->type; + } else if (key != NULL) { + keytype = key->type; + } else { error("Could not load host key: %s", options.host_key_files[i]); sensitive_data.host_keys[i] = NULL; + sensitive_data.host_pubkeys[i] = NULL; continue; } - switch (key->type) { + + switch (keytype) { case KEY_RSA1: sensitive_data.ssh1_host_key = key; sensitive_data.have_ssh1_key = 1; @@ -1568,8 +1615,8 @@ main(int ac, char **av) sensitive_data.have_ssh2_key = 1; break; } - debug("private host key: #%d type %d %s", i, key->type, - key_type(key)); + debug("private host key: #%d type %d %s", i, keytype, + key_type(key ? key : pubkey)); } if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { logit("Disabling protocol version 1. Could not load host key"); @@ -1906,9 +1953,11 @@ main(int ac, char **av) buffer_init(&loginmsg); auth_debug_reset(); - if (use_privsep) + if (use_privsep) { if (privsep_preauth(authctxt) == 1) goto authenticated; + } else if (compat20 && have_agent) + auth_conn = ssh_get_authentication_connection(); /* perform the key exchange */ /* authenticate user and start session */ @@ -2194,6 +2243,23 @@ do_ssh1_kex(void) packet_write_wait(); } +void +sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, + u_char *data, u_int dlen) +{ + if (privkey) { + if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0)) + fatal("%s: key_sign failed", __func__); + } else if (use_privsep) { + if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0) + fatal("%s: pubkey_sign failed", __func__); + } else { + if (ssh_agent_sign(auth_conn, pubkey, signature, slen, data, + dlen)) + fatal("%s: ssh_agent_sign failed", __func__); + } +} + /* * SSH2 key exchange: diffie-hellman-group1-sha1 */ @@ -2244,6 +2310,7 @@ do_ssh2_kex(void) kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; + kex->sign = sshd_hostkey_sign; xxx_kex = kex; |