1*e9778795SPeter Avalos /* $OpenBSD: ssh_api.c,v 1.7 2016/05/04 14:22:33 markus Exp $ */ 2*e9778795SPeter Avalos /* 3*e9778795SPeter Avalos * Copyright (c) 2012 Markus Friedl. All rights reserved. 4*e9778795SPeter Avalos * 5*e9778795SPeter Avalos * Permission to use, copy, modify, and distribute this software for any 6*e9778795SPeter Avalos * purpose with or without fee is hereby granted, provided that the above 7*e9778795SPeter Avalos * copyright notice and this permission notice appear in all copies. 8*e9778795SPeter Avalos * 9*e9778795SPeter Avalos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*e9778795SPeter Avalos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*e9778795SPeter Avalos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*e9778795SPeter Avalos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*e9778795SPeter Avalos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*e9778795SPeter Avalos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*e9778795SPeter Avalos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*e9778795SPeter Avalos */ 17*e9778795SPeter Avalos 18*e9778795SPeter Avalos #include "includes.h" 19*e9778795SPeter Avalos 20*e9778795SPeter Avalos #include "ssh_api.h" 21*e9778795SPeter Avalos #include "compat.h" 22*e9778795SPeter Avalos #include "log.h" 23*e9778795SPeter Avalos #include "authfile.h" 24*e9778795SPeter Avalos #include "sshkey.h" 25*e9778795SPeter Avalos #include "misc.h" 26*e9778795SPeter Avalos #include "ssh2.h" 27*e9778795SPeter Avalos #include "version.h" 28*e9778795SPeter Avalos #include "myproposal.h" 29*e9778795SPeter Avalos #include "ssherr.h" 30*e9778795SPeter Avalos #include "sshbuf.h" 31*e9778795SPeter Avalos 32*e9778795SPeter Avalos #include <string.h> 33*e9778795SPeter Avalos 34*e9778795SPeter Avalos int _ssh_exchange_banner(struct ssh *); 35*e9778795SPeter Avalos int _ssh_send_banner(struct ssh *, char **); 36*e9778795SPeter Avalos int _ssh_read_banner(struct ssh *, char **); 37*e9778795SPeter Avalos int _ssh_order_hostkeyalgs(struct ssh *); 38*e9778795SPeter Avalos int _ssh_verify_host_key(struct sshkey *, struct ssh *); 39*e9778795SPeter Avalos struct sshkey *_ssh_host_public_key(int, int, struct ssh *); 40*e9778795SPeter Avalos struct sshkey *_ssh_host_private_key(int, int, struct ssh *); 41*e9778795SPeter Avalos int _ssh_host_key_sign(struct sshkey *, struct sshkey *, 42*e9778795SPeter Avalos u_char **, size_t *, const u_char *, size_t, const char *, u_int); 43*e9778795SPeter Avalos 44*e9778795SPeter Avalos /* 45*e9778795SPeter Avalos * stubs for the server side implementation of kex. 46*e9778795SPeter Avalos * disable privsep so our stubs will never be called. 47*e9778795SPeter Avalos */ 48*e9778795SPeter Avalos int use_privsep = 0; 49*e9778795SPeter Avalos int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, 50*e9778795SPeter Avalos u_char *, u_int, char *, u_int); 51*e9778795SPeter Avalos DH *mm_choose_dh(int, int, int); 52*e9778795SPeter Avalos 53*e9778795SPeter Avalos /* Define these two variables here so that they are part of the library */ 54*e9778795SPeter Avalos u_char *session_id2 = NULL; 55*e9778795SPeter Avalos u_int session_id2_len = 0; 56*e9778795SPeter Avalos 57*e9778795SPeter Avalos int 58*e9778795SPeter Avalos mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp, 59*e9778795SPeter Avalos u_char *data, u_int datalen, char *alg, u_int compat) 60*e9778795SPeter Avalos { 61*e9778795SPeter Avalos return (-1); 62*e9778795SPeter Avalos } 63*e9778795SPeter Avalos 64*e9778795SPeter Avalos DH * 65*e9778795SPeter Avalos mm_choose_dh(int min, int nbits, int max) 66*e9778795SPeter Avalos { 67*e9778795SPeter Avalos return (NULL); 68*e9778795SPeter Avalos } 69*e9778795SPeter Avalos 70*e9778795SPeter Avalos /* API */ 71*e9778795SPeter Avalos 72*e9778795SPeter Avalos int 73*e9778795SPeter Avalos ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) 74*e9778795SPeter Avalos { 75*e9778795SPeter Avalos char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 76*e9778795SPeter Avalos struct ssh *ssh; 77*e9778795SPeter Avalos char **proposal; 78*e9778795SPeter Avalos static int called; 79*e9778795SPeter Avalos int r; 80*e9778795SPeter Avalos 81*e9778795SPeter Avalos if (!called) { 82*e9778795SPeter Avalos #ifdef WITH_OPENSSL 83*e9778795SPeter Avalos OpenSSL_add_all_algorithms(); 84*e9778795SPeter Avalos #endif /* WITH_OPENSSL */ 85*e9778795SPeter Avalos called = 1; 86*e9778795SPeter Avalos } 87*e9778795SPeter Avalos 88*e9778795SPeter Avalos if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL) 89*e9778795SPeter Avalos return SSH_ERR_ALLOC_FAIL; 90*e9778795SPeter Avalos if (is_server) 91*e9778795SPeter Avalos ssh_packet_set_server(ssh); 92*e9778795SPeter Avalos 93*e9778795SPeter Avalos /* Initialize key exchange */ 94*e9778795SPeter Avalos proposal = kex_params ? kex_params->proposal : myproposal; 95*e9778795SPeter Avalos if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) { 96*e9778795SPeter Avalos ssh_free(ssh); 97*e9778795SPeter Avalos return r; 98*e9778795SPeter Avalos } 99*e9778795SPeter Avalos ssh->kex->server = is_server; 100*e9778795SPeter Avalos if (is_server) { 101*e9778795SPeter Avalos #ifdef WITH_OPENSSL 102*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 103*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 104*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; 105*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; 106*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; 107*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 108*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 109*e9778795SPeter Avalos # ifdef OPENSSL_HAS_ECC 110*e9778795SPeter Avalos ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 111*e9778795SPeter Avalos # endif 112*e9778795SPeter Avalos #endif /* WITH_OPENSSL */ 113*e9778795SPeter Avalos ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server; 114*e9778795SPeter Avalos ssh->kex->load_host_public_key=&_ssh_host_public_key; 115*e9778795SPeter Avalos ssh->kex->load_host_private_key=&_ssh_host_private_key; 116*e9778795SPeter Avalos ssh->kex->sign=&_ssh_host_key_sign; 117*e9778795SPeter Avalos } else { 118*e9778795SPeter Avalos #ifdef WITH_OPENSSL 119*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 120*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 121*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; 122*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; 123*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; 124*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 125*e9778795SPeter Avalos ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 126*e9778795SPeter Avalos # ifdef OPENSSL_HAS_ECC 127*e9778795SPeter Avalos ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 128*e9778795SPeter Avalos # endif 129*e9778795SPeter Avalos #endif /* WITH_OPENSSL */ 130*e9778795SPeter Avalos ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; 131*e9778795SPeter Avalos ssh->kex->verify_host_key =&_ssh_verify_host_key; 132*e9778795SPeter Avalos } 133*e9778795SPeter Avalos *sshp = ssh; 134*e9778795SPeter Avalos return 0; 135*e9778795SPeter Avalos } 136*e9778795SPeter Avalos 137*e9778795SPeter Avalos void 138*e9778795SPeter Avalos ssh_free(struct ssh *ssh) 139*e9778795SPeter Avalos { 140*e9778795SPeter Avalos struct key_entry *k; 141*e9778795SPeter Avalos 142*e9778795SPeter Avalos ssh_packet_close(ssh); 143*e9778795SPeter Avalos /* 144*e9778795SPeter Avalos * we've only created the public keys variants in case we 145*e9778795SPeter Avalos * are a acting as a server. 146*e9778795SPeter Avalos */ 147*e9778795SPeter Avalos while ((k = TAILQ_FIRST(&ssh->public_keys)) != NULL) { 148*e9778795SPeter Avalos TAILQ_REMOVE(&ssh->public_keys, k, next); 149*e9778795SPeter Avalos if (ssh->kex && ssh->kex->server) 150*e9778795SPeter Avalos sshkey_free(k->key); 151*e9778795SPeter Avalos free(k); 152*e9778795SPeter Avalos } 153*e9778795SPeter Avalos while ((k = TAILQ_FIRST(&ssh->private_keys)) != NULL) { 154*e9778795SPeter Avalos TAILQ_REMOVE(&ssh->private_keys, k, next); 155*e9778795SPeter Avalos free(k); 156*e9778795SPeter Avalos } 157*e9778795SPeter Avalos if (ssh->kex) 158*e9778795SPeter Avalos kex_free(ssh->kex); 159*e9778795SPeter Avalos free(ssh); 160*e9778795SPeter Avalos } 161*e9778795SPeter Avalos 162*e9778795SPeter Avalos void 163*e9778795SPeter Avalos ssh_set_app_data(struct ssh *ssh, void *app_data) 164*e9778795SPeter Avalos { 165*e9778795SPeter Avalos ssh->app_data = app_data; 166*e9778795SPeter Avalos } 167*e9778795SPeter Avalos 168*e9778795SPeter Avalos void * 169*e9778795SPeter Avalos ssh_get_app_data(struct ssh *ssh) 170*e9778795SPeter Avalos { 171*e9778795SPeter Avalos return ssh->app_data; 172*e9778795SPeter Avalos } 173*e9778795SPeter Avalos 174*e9778795SPeter Avalos /* Returns < 0 on error, 0 otherwise */ 175*e9778795SPeter Avalos int 176*e9778795SPeter Avalos ssh_add_hostkey(struct ssh *ssh, struct sshkey *key) 177*e9778795SPeter Avalos { 178*e9778795SPeter Avalos struct sshkey *pubkey = NULL; 179*e9778795SPeter Avalos struct key_entry *k = NULL, *k_prv = NULL; 180*e9778795SPeter Avalos int r; 181*e9778795SPeter Avalos 182*e9778795SPeter Avalos if (ssh->kex->server) { 183*e9778795SPeter Avalos if ((r = sshkey_from_private(key, &pubkey)) != 0) 184*e9778795SPeter Avalos return r; 185*e9778795SPeter Avalos if ((k = malloc(sizeof(*k))) == NULL || 186*e9778795SPeter Avalos (k_prv = malloc(sizeof(*k_prv))) == NULL) { 187*e9778795SPeter Avalos free(k); 188*e9778795SPeter Avalos sshkey_free(pubkey); 189*e9778795SPeter Avalos return SSH_ERR_ALLOC_FAIL; 190*e9778795SPeter Avalos } 191*e9778795SPeter Avalos k_prv->key = key; 192*e9778795SPeter Avalos TAILQ_INSERT_TAIL(&ssh->private_keys, k_prv, next); 193*e9778795SPeter Avalos 194*e9778795SPeter Avalos /* add the public key, too */ 195*e9778795SPeter Avalos k->key = pubkey; 196*e9778795SPeter Avalos TAILQ_INSERT_TAIL(&ssh->public_keys, k, next); 197*e9778795SPeter Avalos r = 0; 198*e9778795SPeter Avalos } else { 199*e9778795SPeter Avalos if ((k = malloc(sizeof(*k))) == NULL) 200*e9778795SPeter Avalos return SSH_ERR_ALLOC_FAIL; 201*e9778795SPeter Avalos k->key = key; 202*e9778795SPeter Avalos TAILQ_INSERT_TAIL(&ssh->public_keys, k, next); 203*e9778795SPeter Avalos r = 0; 204*e9778795SPeter Avalos } 205*e9778795SPeter Avalos 206*e9778795SPeter Avalos return r; 207*e9778795SPeter Avalos } 208*e9778795SPeter Avalos 209*e9778795SPeter Avalos int 210*e9778795SPeter Avalos ssh_set_verify_host_key_callback(struct ssh *ssh, 211*e9778795SPeter Avalos int (*cb)(struct sshkey *, struct ssh *)) 212*e9778795SPeter Avalos { 213*e9778795SPeter Avalos if (cb == NULL || ssh->kex == NULL) 214*e9778795SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 215*e9778795SPeter Avalos 216*e9778795SPeter Avalos ssh->kex->verify_host_key = cb; 217*e9778795SPeter Avalos 218*e9778795SPeter Avalos return 0; 219*e9778795SPeter Avalos } 220*e9778795SPeter Avalos 221*e9778795SPeter Avalos int 222*e9778795SPeter Avalos ssh_input_append(struct ssh *ssh, const u_char *data, size_t len) 223*e9778795SPeter Avalos { 224*e9778795SPeter Avalos return sshbuf_put(ssh_packet_get_input(ssh), data, len); 225*e9778795SPeter Avalos } 226*e9778795SPeter Avalos 227*e9778795SPeter Avalos int 228*e9778795SPeter Avalos ssh_packet_next(struct ssh *ssh, u_char *typep) 229*e9778795SPeter Avalos { 230*e9778795SPeter Avalos int r; 231*e9778795SPeter Avalos u_int32_t seqnr; 232*e9778795SPeter Avalos u_char type; 233*e9778795SPeter Avalos 234*e9778795SPeter Avalos /* 235*e9778795SPeter Avalos * Try to read a packet. Return SSH_MSG_NONE if no packet or not 236*e9778795SPeter Avalos * enough data. 237*e9778795SPeter Avalos */ 238*e9778795SPeter Avalos *typep = SSH_MSG_NONE; 239*e9778795SPeter Avalos if (ssh->kex->client_version_string == NULL || 240*e9778795SPeter Avalos ssh->kex->server_version_string == NULL) 241*e9778795SPeter Avalos return _ssh_exchange_banner(ssh); 242*e9778795SPeter Avalos /* 243*e9778795SPeter Avalos * If we enough data and a dispatch function then 244*e9778795SPeter Avalos * call the function and get the next packet. 245*e9778795SPeter Avalos * Otherwise return the packet type to the caller so it 246*e9778795SPeter Avalos * can decide how to go on. 247*e9778795SPeter Avalos * 248*e9778795SPeter Avalos * We will only call the dispatch function for: 249*e9778795SPeter Avalos * 20-29 Algorithm negotiation 250*e9778795SPeter Avalos * 30-49 Key exchange method specific (numbers can be reused for 251*e9778795SPeter Avalos * different authentication methods) 252*e9778795SPeter Avalos */ 253*e9778795SPeter Avalos for (;;) { 254*e9778795SPeter Avalos if ((r = ssh_packet_read_poll2(ssh, &type, &seqnr)) != 0) 255*e9778795SPeter Avalos return r; 256*e9778795SPeter Avalos if (type > 0 && type < DISPATCH_MAX && 257*e9778795SPeter Avalos type >= SSH2_MSG_KEXINIT && type <= SSH2_MSG_TRANSPORT_MAX && 258*e9778795SPeter Avalos ssh->dispatch[type] != NULL) { 259*e9778795SPeter Avalos if ((r = (*ssh->dispatch[type])(type, seqnr, ssh)) != 0) 260*e9778795SPeter Avalos return r; 261*e9778795SPeter Avalos } else { 262*e9778795SPeter Avalos *typep = type; 263*e9778795SPeter Avalos return 0; 264*e9778795SPeter Avalos } 265*e9778795SPeter Avalos } 266*e9778795SPeter Avalos } 267*e9778795SPeter Avalos 268*e9778795SPeter Avalos const u_char * 269*e9778795SPeter Avalos ssh_packet_payload(struct ssh *ssh, size_t *lenp) 270*e9778795SPeter Avalos { 271*e9778795SPeter Avalos return sshpkt_ptr(ssh, lenp); 272*e9778795SPeter Avalos } 273*e9778795SPeter Avalos 274*e9778795SPeter Avalos int 275*e9778795SPeter Avalos ssh_packet_put(struct ssh *ssh, int type, const u_char *data, size_t len) 276*e9778795SPeter Avalos { 277*e9778795SPeter Avalos int r; 278*e9778795SPeter Avalos 279*e9778795SPeter Avalos if ((r = sshpkt_start(ssh, type)) != 0 || 280*e9778795SPeter Avalos (r = sshpkt_put(ssh, data, len)) != 0 || 281*e9778795SPeter Avalos (r = sshpkt_send(ssh)) != 0) 282*e9778795SPeter Avalos return r; 283*e9778795SPeter Avalos return 0; 284*e9778795SPeter Avalos } 285*e9778795SPeter Avalos 286*e9778795SPeter Avalos const u_char * 287*e9778795SPeter Avalos ssh_output_ptr(struct ssh *ssh, size_t *len) 288*e9778795SPeter Avalos { 289*e9778795SPeter Avalos struct sshbuf *output = ssh_packet_get_output(ssh); 290*e9778795SPeter Avalos 291*e9778795SPeter Avalos *len = sshbuf_len(output); 292*e9778795SPeter Avalos return sshbuf_ptr(output); 293*e9778795SPeter Avalos } 294*e9778795SPeter Avalos 295*e9778795SPeter Avalos int 296*e9778795SPeter Avalos ssh_output_consume(struct ssh *ssh, size_t len) 297*e9778795SPeter Avalos { 298*e9778795SPeter Avalos return sshbuf_consume(ssh_packet_get_output(ssh), len); 299*e9778795SPeter Avalos } 300*e9778795SPeter Avalos 301*e9778795SPeter Avalos int 302*e9778795SPeter Avalos ssh_output_space(struct ssh *ssh, size_t len) 303*e9778795SPeter Avalos { 304*e9778795SPeter Avalos return (0 == sshbuf_check_reserve(ssh_packet_get_output(ssh), len)); 305*e9778795SPeter Avalos } 306*e9778795SPeter Avalos 307*e9778795SPeter Avalos int 308*e9778795SPeter Avalos ssh_input_space(struct ssh *ssh, size_t len) 309*e9778795SPeter Avalos { 310*e9778795SPeter Avalos return (0 == sshbuf_check_reserve(ssh_packet_get_input(ssh), len)); 311*e9778795SPeter Avalos } 312*e9778795SPeter Avalos 313*e9778795SPeter Avalos /* Read other side's version identification. */ 314*e9778795SPeter Avalos int 315*e9778795SPeter Avalos _ssh_read_banner(struct ssh *ssh, char **bannerp) 316*e9778795SPeter Avalos { 317*e9778795SPeter Avalos struct sshbuf *input; 318*e9778795SPeter Avalos const char *s; 319*e9778795SPeter Avalos char buf[256], remote_version[256]; /* must be same size! */ 320*e9778795SPeter Avalos const char *mismatch = "Protocol mismatch.\r\n"; 321*e9778795SPeter Avalos int r, remote_major, remote_minor; 322*e9778795SPeter Avalos size_t i, n, j, len; 323*e9778795SPeter Avalos 324*e9778795SPeter Avalos *bannerp = NULL; 325*e9778795SPeter Avalos input = ssh_packet_get_input(ssh); 326*e9778795SPeter Avalos len = sshbuf_len(input); 327*e9778795SPeter Avalos s = (const char *)sshbuf_ptr(input); 328*e9778795SPeter Avalos for (j = n = 0;;) { 329*e9778795SPeter Avalos for (i = 0; i < sizeof(buf) - 1; i++) { 330*e9778795SPeter Avalos if (j >= len) 331*e9778795SPeter Avalos return (0); 332*e9778795SPeter Avalos buf[i] = s[j++]; 333*e9778795SPeter Avalos if (buf[i] == '\r') { 334*e9778795SPeter Avalos buf[i] = '\n'; 335*e9778795SPeter Avalos buf[i + 1] = 0; 336*e9778795SPeter Avalos continue; /**XXX wait for \n */ 337*e9778795SPeter Avalos } 338*e9778795SPeter Avalos if (buf[i] == '\n') { 339*e9778795SPeter Avalos buf[i + 1] = 0; 340*e9778795SPeter Avalos break; 341*e9778795SPeter Avalos } 342*e9778795SPeter Avalos } 343*e9778795SPeter Avalos buf[sizeof(buf) - 1] = 0; 344*e9778795SPeter Avalos if (strncmp(buf, "SSH-", 4) == 0) 345*e9778795SPeter Avalos break; 346*e9778795SPeter Avalos debug("ssh_exchange_identification: %s", buf); 347*e9778795SPeter Avalos if (ssh->kex->server || ++n > 65536) { 348*e9778795SPeter Avalos if ((r = sshbuf_put(ssh_packet_get_output(ssh), 349*e9778795SPeter Avalos mismatch, strlen(mismatch))) != 0) 350*e9778795SPeter Avalos return r; 351*e9778795SPeter Avalos return SSH_ERR_NO_PROTOCOL_VERSION; 352*e9778795SPeter Avalos } 353*e9778795SPeter Avalos } 354*e9778795SPeter Avalos if ((r = sshbuf_consume(input, j)) != 0) 355*e9778795SPeter Avalos return r; 356*e9778795SPeter Avalos 357*e9778795SPeter Avalos /* 358*e9778795SPeter Avalos * Check that the versions match. In future this might accept 359*e9778795SPeter Avalos * several versions and set appropriate flags to handle them. 360*e9778795SPeter Avalos */ 361*e9778795SPeter Avalos if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", 362*e9778795SPeter Avalos &remote_major, &remote_minor, remote_version) != 3) 363*e9778795SPeter Avalos return SSH_ERR_INVALID_FORMAT; 364*e9778795SPeter Avalos debug("Remote protocol version %d.%d, remote software version %.100s", 365*e9778795SPeter Avalos remote_major, remote_minor, remote_version); 366*e9778795SPeter Avalos 367*e9778795SPeter Avalos ssh->compat = compat_datafellows(remote_version); 368*e9778795SPeter Avalos if (remote_major == 1 && remote_minor == 99) { 369*e9778795SPeter Avalos remote_major = 2; 370*e9778795SPeter Avalos remote_minor = 0; 371*e9778795SPeter Avalos } 372*e9778795SPeter Avalos if (remote_major != 2) 373*e9778795SPeter Avalos return SSH_ERR_PROTOCOL_MISMATCH; 374*e9778795SPeter Avalos enable_compat20(); 375*e9778795SPeter Avalos chop(buf); 376*e9778795SPeter Avalos debug("Remote version string %.100s", buf); 377*e9778795SPeter Avalos if ((*bannerp = strdup(buf)) == NULL) 378*e9778795SPeter Avalos return SSH_ERR_ALLOC_FAIL; 379*e9778795SPeter Avalos return 0; 380*e9778795SPeter Avalos } 381*e9778795SPeter Avalos 382*e9778795SPeter Avalos /* Send our own protocol version identification. */ 383*e9778795SPeter Avalos int 384*e9778795SPeter Avalos _ssh_send_banner(struct ssh *ssh, char **bannerp) 385*e9778795SPeter Avalos { 386*e9778795SPeter Avalos char buf[256]; 387*e9778795SPeter Avalos int r; 388*e9778795SPeter Avalos 389*e9778795SPeter Avalos snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION); 390*e9778795SPeter Avalos if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0) 391*e9778795SPeter Avalos return r; 392*e9778795SPeter Avalos chop(buf); 393*e9778795SPeter Avalos debug("Local version string %.100s", buf); 394*e9778795SPeter Avalos if ((*bannerp = strdup(buf)) == NULL) 395*e9778795SPeter Avalos return SSH_ERR_ALLOC_FAIL; 396*e9778795SPeter Avalos return 0; 397*e9778795SPeter Avalos } 398*e9778795SPeter Avalos 399*e9778795SPeter Avalos int 400*e9778795SPeter Avalos _ssh_exchange_banner(struct ssh *ssh) 401*e9778795SPeter Avalos { 402*e9778795SPeter Avalos struct kex *kex = ssh->kex; 403*e9778795SPeter Avalos int r; 404*e9778795SPeter Avalos 405*e9778795SPeter Avalos /* 406*e9778795SPeter Avalos * if _ssh_read_banner() cannot parse a full version string 407*e9778795SPeter Avalos * it will return NULL and we end up calling it again. 408*e9778795SPeter Avalos */ 409*e9778795SPeter Avalos 410*e9778795SPeter Avalos r = 0; 411*e9778795SPeter Avalos if (kex->server) { 412*e9778795SPeter Avalos if (kex->server_version_string == NULL) 413*e9778795SPeter Avalos r = _ssh_send_banner(ssh, &kex->server_version_string); 414*e9778795SPeter Avalos if (r == 0 && 415*e9778795SPeter Avalos kex->server_version_string != NULL && 416*e9778795SPeter Avalos kex->client_version_string == NULL) 417*e9778795SPeter Avalos r = _ssh_read_banner(ssh, &kex->client_version_string); 418*e9778795SPeter Avalos } else { 419*e9778795SPeter Avalos if (kex->server_version_string == NULL) 420*e9778795SPeter Avalos r = _ssh_read_banner(ssh, &kex->server_version_string); 421*e9778795SPeter Avalos if (r == 0 && 422*e9778795SPeter Avalos kex->server_version_string != NULL && 423*e9778795SPeter Avalos kex->client_version_string == NULL) 424*e9778795SPeter Avalos r = _ssh_send_banner(ssh, &kex->client_version_string); 425*e9778795SPeter Avalos } 426*e9778795SPeter Avalos if (r != 0) 427*e9778795SPeter Avalos return r; 428*e9778795SPeter Avalos /* start initial kex as soon as we have exchanged the banners */ 429*e9778795SPeter Avalos if (kex->server_version_string != NULL && 430*e9778795SPeter Avalos kex->client_version_string != NULL) { 431*e9778795SPeter Avalos if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 || 432*e9778795SPeter Avalos (r = kex_send_kexinit(ssh)) != 0) 433*e9778795SPeter Avalos return r; 434*e9778795SPeter Avalos } 435*e9778795SPeter Avalos return 0; 436*e9778795SPeter Avalos } 437*e9778795SPeter Avalos 438*e9778795SPeter Avalos struct sshkey * 439*e9778795SPeter Avalos _ssh_host_public_key(int type, int nid, struct ssh *ssh) 440*e9778795SPeter Avalos { 441*e9778795SPeter Avalos struct key_entry *k; 442*e9778795SPeter Avalos 443*e9778795SPeter Avalos debug3("%s: need %d", __func__, type); 444*e9778795SPeter Avalos TAILQ_FOREACH(k, &ssh->public_keys, next) { 445*e9778795SPeter Avalos debug3("%s: check %s", __func__, sshkey_type(k->key)); 446*e9778795SPeter Avalos if (k->key->type == type && 447*e9778795SPeter Avalos (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) 448*e9778795SPeter Avalos return (k->key); 449*e9778795SPeter Avalos } 450*e9778795SPeter Avalos return (NULL); 451*e9778795SPeter Avalos } 452*e9778795SPeter Avalos 453*e9778795SPeter Avalos struct sshkey * 454*e9778795SPeter Avalos _ssh_host_private_key(int type, int nid, struct ssh *ssh) 455*e9778795SPeter Avalos { 456*e9778795SPeter Avalos struct key_entry *k; 457*e9778795SPeter Avalos 458*e9778795SPeter Avalos debug3("%s: need %d", __func__, type); 459*e9778795SPeter Avalos TAILQ_FOREACH(k, &ssh->private_keys, next) { 460*e9778795SPeter Avalos debug3("%s: check %s", __func__, sshkey_type(k->key)); 461*e9778795SPeter Avalos if (k->key->type == type && 462*e9778795SPeter Avalos (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) 463*e9778795SPeter Avalos return (k->key); 464*e9778795SPeter Avalos } 465*e9778795SPeter Avalos return (NULL); 466*e9778795SPeter Avalos } 467*e9778795SPeter Avalos 468*e9778795SPeter Avalos int 469*e9778795SPeter Avalos _ssh_verify_host_key(struct sshkey *hostkey, struct ssh *ssh) 470*e9778795SPeter Avalos { 471*e9778795SPeter Avalos struct key_entry *k; 472*e9778795SPeter Avalos 473*e9778795SPeter Avalos debug3("%s: need %s", __func__, sshkey_type(hostkey)); 474*e9778795SPeter Avalos TAILQ_FOREACH(k, &ssh->public_keys, next) { 475*e9778795SPeter Avalos debug3("%s: check %s", __func__, sshkey_type(k->key)); 476*e9778795SPeter Avalos if (sshkey_equal_public(hostkey, k->key)) 477*e9778795SPeter Avalos return (0); /* ok */ 478*e9778795SPeter Avalos } 479*e9778795SPeter Avalos return (-1); /* failed */ 480*e9778795SPeter Avalos } 481*e9778795SPeter Avalos 482*e9778795SPeter Avalos /* offer hostkey algorithms in kexinit depending on registered keys */ 483*e9778795SPeter Avalos int 484*e9778795SPeter Avalos _ssh_order_hostkeyalgs(struct ssh *ssh) 485*e9778795SPeter Avalos { 486*e9778795SPeter Avalos struct key_entry *k; 487*e9778795SPeter Avalos char *orig, *avail, *oavail = NULL, *alg, *replace = NULL; 488*e9778795SPeter Avalos char **proposal; 489*e9778795SPeter Avalos size_t maxlen; 490*e9778795SPeter Avalos int ktype, r; 491*e9778795SPeter Avalos 492*e9778795SPeter Avalos /* XXX we de-serialize ssh->kex->my, modify it, and change it */ 493*e9778795SPeter Avalos if ((r = kex_buf2prop(ssh->kex->my, NULL, &proposal)) != 0) 494*e9778795SPeter Avalos return r; 495*e9778795SPeter Avalos orig = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; 496*e9778795SPeter Avalos if ((oavail = avail = strdup(orig)) == NULL) { 497*e9778795SPeter Avalos r = SSH_ERR_ALLOC_FAIL; 498*e9778795SPeter Avalos goto out; 499*e9778795SPeter Avalos } 500*e9778795SPeter Avalos maxlen = strlen(avail) + 1; 501*e9778795SPeter Avalos if ((replace = calloc(1, maxlen)) == NULL) { 502*e9778795SPeter Avalos r = SSH_ERR_ALLOC_FAIL; 503*e9778795SPeter Avalos goto out; 504*e9778795SPeter Avalos } 505*e9778795SPeter Avalos *replace = '\0'; 506*e9778795SPeter Avalos while ((alg = strsep(&avail, ",")) && *alg != '\0') { 507*e9778795SPeter Avalos if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) 508*e9778795SPeter Avalos continue; 509*e9778795SPeter Avalos TAILQ_FOREACH(k, &ssh->public_keys, next) { 510*e9778795SPeter Avalos if (k->key->type == ktype || 511*e9778795SPeter Avalos (sshkey_is_cert(k->key) && k->key->type == 512*e9778795SPeter Avalos sshkey_type_plain(ktype))) { 513*e9778795SPeter Avalos if (*replace != '\0') 514*e9778795SPeter Avalos strlcat(replace, ",", maxlen); 515*e9778795SPeter Avalos strlcat(replace, alg, maxlen); 516*e9778795SPeter Avalos break; 517*e9778795SPeter Avalos } 518*e9778795SPeter Avalos } 519*e9778795SPeter Avalos } 520*e9778795SPeter Avalos if (*replace != '\0') { 521*e9778795SPeter Avalos debug2("%s: orig/%d %s", __func__, ssh->kex->server, orig); 522*e9778795SPeter Avalos debug2("%s: replace/%d %s", __func__, ssh->kex->server, replace); 523*e9778795SPeter Avalos free(orig); 524*e9778795SPeter Avalos proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = replace; 525*e9778795SPeter Avalos replace = NULL; /* owned by proposal */ 526*e9778795SPeter Avalos r = kex_prop2buf(ssh->kex->my, proposal); 527*e9778795SPeter Avalos } 528*e9778795SPeter Avalos out: 529*e9778795SPeter Avalos free(oavail); 530*e9778795SPeter Avalos free(replace); 531*e9778795SPeter Avalos kex_prop_free(proposal); 532*e9778795SPeter Avalos return r; 533*e9778795SPeter Avalos } 534*e9778795SPeter Avalos 535*e9778795SPeter Avalos int 536*e9778795SPeter Avalos _ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey, 537*e9778795SPeter Avalos u_char **signature, size_t *slen, const u_char *data, size_t dlen, 538*e9778795SPeter Avalos const char *alg, u_int compat) 539*e9778795SPeter Avalos { 540*e9778795SPeter Avalos return sshkey_sign(privkey, signature, slen, data, dlen, alg, compat); 541*e9778795SPeter Avalos } 542