1*874e263eSdtucker /* $OpenBSD: sshd-auth.c,v 1.3 2025/01/16 06:37:10 dtucker Exp $ */ 2856b6ee8Sdjm /* 3856b6ee8Sdjm * SSH2 implementation: 4856b6ee8Sdjm * Privilege Separation: 5856b6ee8Sdjm * 6856b6ee8Sdjm * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. 7856b6ee8Sdjm * Copyright (c) 2002 Niels Provos. All rights reserved. 8856b6ee8Sdjm * 9856b6ee8Sdjm * Redistribution and use in source and binary forms, with or without 10856b6ee8Sdjm * modification, are permitted provided that the following conditions 11856b6ee8Sdjm * are met: 12856b6ee8Sdjm * 1. Redistributions of source code must retain the above copyright 13856b6ee8Sdjm * notice, this list of conditions and the following disclaimer. 14856b6ee8Sdjm * 2. Redistributions in binary form must reproduce the above copyright 15856b6ee8Sdjm * notice, this list of conditions and the following disclaimer in the 16856b6ee8Sdjm * documentation and/or other materials provided with the distribution. 17856b6ee8Sdjm * 18856b6ee8Sdjm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19856b6ee8Sdjm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20856b6ee8Sdjm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21856b6ee8Sdjm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22856b6ee8Sdjm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23856b6ee8Sdjm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24856b6ee8Sdjm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25856b6ee8Sdjm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26856b6ee8Sdjm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27856b6ee8Sdjm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28856b6ee8Sdjm */ 29856b6ee8Sdjm 30856b6ee8Sdjm #include <sys/types.h> 31856b6ee8Sdjm #include <sys/ioctl.h> 32856b6ee8Sdjm #include <sys/wait.h> 33856b6ee8Sdjm #include <sys/tree.h> 34856b6ee8Sdjm #include <sys/stat.h> 35856b6ee8Sdjm #include <sys/socket.h> 36856b6ee8Sdjm #include <sys/time.h> 37856b6ee8Sdjm #include <sys/queue.h> 38856b6ee8Sdjm 39856b6ee8Sdjm #include <errno.h> 40856b6ee8Sdjm #include <fcntl.h> 41856b6ee8Sdjm #include <netdb.h> 42856b6ee8Sdjm #include <paths.h> 43856b6ee8Sdjm #include <pwd.h> 44856b6ee8Sdjm #include <signal.h> 45856b6ee8Sdjm #include <stdio.h> 46856b6ee8Sdjm #include <stdlib.h> 47856b6ee8Sdjm #include <string.h> 48856b6ee8Sdjm #include <stdarg.h> 49856b6ee8Sdjm #include <unistd.h> 50856b6ee8Sdjm #include <limits.h> 51856b6ee8Sdjm 52856b6ee8Sdjm #ifdef WITH_OPENSSL 53856b6ee8Sdjm #include <openssl/bn.h> 54856b6ee8Sdjm #include <openssl/evp.h> 55856b6ee8Sdjm #endif 56856b6ee8Sdjm 57856b6ee8Sdjm #include "xmalloc.h" 58856b6ee8Sdjm #include "ssh.h" 59856b6ee8Sdjm #include "ssh2.h" 60856b6ee8Sdjm #include "sshpty.h" 61856b6ee8Sdjm #include "packet.h" 62856b6ee8Sdjm #include "log.h" 63856b6ee8Sdjm #include "sshbuf.h" 64856b6ee8Sdjm #include "misc.h" 65856b6ee8Sdjm #include "match.h" 66856b6ee8Sdjm #include "servconf.h" 67856b6ee8Sdjm #include "uidswap.h" 68856b6ee8Sdjm #include "compat.h" 69856b6ee8Sdjm #include "cipher.h" 70856b6ee8Sdjm #include "digest.h" 71856b6ee8Sdjm #include "sshkey.h" 72856b6ee8Sdjm #include "kex.h" 73856b6ee8Sdjm #include "authfile.h" 74856b6ee8Sdjm #include "pathnames.h" 75856b6ee8Sdjm #include "atomicio.h" 76856b6ee8Sdjm #include "canohost.h" 77856b6ee8Sdjm #include "hostfile.h" 78856b6ee8Sdjm #include "auth.h" 79856b6ee8Sdjm #include "authfd.h" 80856b6ee8Sdjm #include "msg.h" 81856b6ee8Sdjm #include "dispatch.h" 82856b6ee8Sdjm #include "channels.h" 83856b6ee8Sdjm #include "session.h" 84856b6ee8Sdjm #include "monitor.h" 85856b6ee8Sdjm #ifdef GSSAPI 86856b6ee8Sdjm #include "ssh-gss.h" 87856b6ee8Sdjm #endif 88856b6ee8Sdjm #include "monitor_wrap.h" 89856b6ee8Sdjm #include "auth-options.h" 90856b6ee8Sdjm #include "version.h" 91856b6ee8Sdjm #include "ssherr.h" 92856b6ee8Sdjm #include "sk-api.h" 93856b6ee8Sdjm #include "srclimit.h" 94856b6ee8Sdjm #include "dh.h" 95856b6ee8Sdjm 96856b6ee8Sdjm /* Privsep fds */ 97856b6ee8Sdjm #define PRIVSEP_MONITOR_FD (STDERR_FILENO + 1) 98856b6ee8Sdjm #define PRIVSEP_LOG_FD (STDERR_FILENO + 2) 99856b6ee8Sdjm #define PRIVSEP_MIN_FREE_FD (STDERR_FILENO + 3) 100856b6ee8Sdjm 101856b6ee8Sdjm extern char *__progname; 102856b6ee8Sdjm 103856b6ee8Sdjm /* Server configuration options. */ 104856b6ee8Sdjm ServerOptions options; 105856b6ee8Sdjm 106856b6ee8Sdjm /* Name of the server configuration file. */ 107856b6ee8Sdjm char *config_file_name = _PATH_SERVER_CONFIG_FILE; 108856b6ee8Sdjm 109856b6ee8Sdjm /* 110856b6ee8Sdjm * Debug mode flag. This can be set on the command line. If debug 111856b6ee8Sdjm * mode is enabled, extra debugging output will be sent to the system 112856b6ee8Sdjm * log, the daemon will not go to background, and will exit after processing 113856b6ee8Sdjm * the first connection. 114856b6ee8Sdjm */ 115856b6ee8Sdjm int debug_flag = 0; 116856b6ee8Sdjm 117856b6ee8Sdjm /* Flag indicating that the daemon is being started from inetd. */ 118856b6ee8Sdjm static int inetd_flag = 0; 119856b6ee8Sdjm 120856b6ee8Sdjm /* Saved arguments to main(). */ 121856b6ee8Sdjm static char **saved_argv; 122856b6ee8Sdjm 123856b6ee8Sdjm /* Daemon's agent connection */ 124856b6ee8Sdjm int auth_sock = -1; 125856b6ee8Sdjm static int have_agent = 0; 126856b6ee8Sdjm 127856b6ee8Sdjm u_int num_hostkeys; 128856b6ee8Sdjm struct sshkey **host_pubkeys; /* all public host keys */ 129856b6ee8Sdjm struct sshkey **host_certificates; /* all public host certificates */ 130856b6ee8Sdjm 131856b6ee8Sdjm /* record remote hostname or ip */ 132856b6ee8Sdjm u_int utmp_len = HOST_NAME_MAX+1; 133856b6ee8Sdjm 134856b6ee8Sdjm /* variables used for privilege separation */ 135856b6ee8Sdjm struct monitor *pmonitor = NULL; 136856b6ee8Sdjm int privsep_is_preauth = 1; 137856b6ee8Sdjm 138856b6ee8Sdjm /* global connection state and authentication contexts */ 139856b6ee8Sdjm Authctxt *the_authctxt = NULL; 140856b6ee8Sdjm struct ssh *the_active_state; 141856b6ee8Sdjm 142856b6ee8Sdjm /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ 143856b6ee8Sdjm struct sshauthopt *auth_opts = NULL; 144856b6ee8Sdjm 145856b6ee8Sdjm /* sshd_config buffer */ 146856b6ee8Sdjm struct sshbuf *cfg; 147856b6ee8Sdjm 148856b6ee8Sdjm /* Included files from the configuration file */ 149856b6ee8Sdjm struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); 150856b6ee8Sdjm 151856b6ee8Sdjm /* message to be displayed after login */ 152856b6ee8Sdjm struct sshbuf *loginmsg; 153856b6ee8Sdjm 154856b6ee8Sdjm /* Prototypes for various functions defined later in this file. */ 155856b6ee8Sdjm static void do_ssh2_kex(struct ssh *); 156856b6ee8Sdjm 157856b6ee8Sdjm /* XXX stub */ 158856b6ee8Sdjm int 159856b6ee8Sdjm mm_is_monitor(void) 160856b6ee8Sdjm { 161856b6ee8Sdjm return 0; 162856b6ee8Sdjm } 163856b6ee8Sdjm 164856b6ee8Sdjm static void 165856b6ee8Sdjm privsep_child_demote(void) 166856b6ee8Sdjm { 167856b6ee8Sdjm gid_t gidset[1]; 168856b6ee8Sdjm struct passwd *pw; 169856b6ee8Sdjm 170856b6ee8Sdjm /* Demote the child */ 171856b6ee8Sdjm if (getuid() == 0 || geteuid() == 0) { 172856b6ee8Sdjm if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) 173856b6ee8Sdjm fatal("Privilege separation user %s does not exist", 174856b6ee8Sdjm SSH_PRIVSEP_USER); 175856b6ee8Sdjm pw = pwcopy(pw); /* Ensure mutable */ 176856b6ee8Sdjm endpwent(); 177856b6ee8Sdjm freezero(pw->pw_passwd, strlen(pw->pw_passwd)); 178856b6ee8Sdjm 179856b6ee8Sdjm /* Change our root directory */ 180856b6ee8Sdjm if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) 181856b6ee8Sdjm fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, 182856b6ee8Sdjm strerror(errno)); 183856b6ee8Sdjm if (chdir("/") == -1) 184856b6ee8Sdjm fatal("chdir(\"/\"): %s", strerror(errno)); 185856b6ee8Sdjm 186856b6ee8Sdjm /* 187856b6ee8Sdjm * Drop our privileges 188856b6ee8Sdjm * NB. Can't use setusercontext() after chroot. 189856b6ee8Sdjm */ 190856b6ee8Sdjm debug3("privsep user:group %u:%u", (u_int)pw->pw_uid, 191856b6ee8Sdjm (u_int)pw->pw_gid); 192856b6ee8Sdjm gidset[0] = pw->pw_gid; 193856b6ee8Sdjm if (setgroups(1, gidset) == -1) 194856b6ee8Sdjm fatal("setgroups: %.100s", strerror(errno)); 195856b6ee8Sdjm permanently_set_uid(pw); 196856b6ee8Sdjm } 197856b6ee8Sdjm 198856b6ee8Sdjm /* sandbox ourselves */ 199856b6ee8Sdjm if (pledge("stdio", NULL) == -1) 200856b6ee8Sdjm fatal_f("pledge()"); 201856b6ee8Sdjm } 202856b6ee8Sdjm 203856b6ee8Sdjm static void 204856b6ee8Sdjm append_hostkey_type(struct sshbuf *b, const char *s) 205856b6ee8Sdjm { 206856b6ee8Sdjm int r; 207856b6ee8Sdjm 208856b6ee8Sdjm if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) { 209856b6ee8Sdjm debug3_f("%s key not permitted by HostkeyAlgorithms", s); 210856b6ee8Sdjm return; 211856b6ee8Sdjm } 212856b6ee8Sdjm if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0) 213856b6ee8Sdjm fatal_fr(r, "sshbuf_putf"); 214856b6ee8Sdjm } 215856b6ee8Sdjm 216856b6ee8Sdjm static char * 217856b6ee8Sdjm list_hostkey_types(void) 218856b6ee8Sdjm { 219856b6ee8Sdjm struct sshbuf *b; 220856b6ee8Sdjm struct sshkey *key; 221856b6ee8Sdjm char *ret; 222856b6ee8Sdjm u_int i; 223856b6ee8Sdjm 224856b6ee8Sdjm if ((b = sshbuf_new()) == NULL) 225856b6ee8Sdjm fatal_f("sshbuf_new failed"); 226856b6ee8Sdjm for (i = 0; i < options.num_host_key_files; i++) { 227856b6ee8Sdjm key = host_pubkeys[i]; 228856b6ee8Sdjm if (key == NULL) 229856b6ee8Sdjm continue; 230856b6ee8Sdjm switch (key->type) { 231856b6ee8Sdjm case KEY_RSA: 232856b6ee8Sdjm /* for RSA we also support SHA2 signatures */ 233856b6ee8Sdjm append_hostkey_type(b, "rsa-sha2-512"); 234856b6ee8Sdjm append_hostkey_type(b, "rsa-sha2-256"); 235856b6ee8Sdjm /* FALLTHROUGH */ 236856b6ee8Sdjm case KEY_DSA: 237856b6ee8Sdjm case KEY_ECDSA: 238856b6ee8Sdjm case KEY_ED25519: 239856b6ee8Sdjm case KEY_ECDSA_SK: 240856b6ee8Sdjm case KEY_ED25519_SK: 241856b6ee8Sdjm case KEY_XMSS: 242856b6ee8Sdjm append_hostkey_type(b, sshkey_ssh_name(key)); 243856b6ee8Sdjm break; 244856b6ee8Sdjm } 245856b6ee8Sdjm /* If the private key has a cert peer, then list that too */ 246856b6ee8Sdjm key = host_certificates[i]; 247856b6ee8Sdjm if (key == NULL) 248856b6ee8Sdjm continue; 249856b6ee8Sdjm switch (key->type) { 250856b6ee8Sdjm case KEY_RSA_CERT: 251856b6ee8Sdjm /* for RSA we also support SHA2 signatures */ 252856b6ee8Sdjm append_hostkey_type(b, 253856b6ee8Sdjm "rsa-sha2-512-cert-v01@openssh.com"); 254856b6ee8Sdjm append_hostkey_type(b, 255856b6ee8Sdjm "rsa-sha2-256-cert-v01@openssh.com"); 256856b6ee8Sdjm /* FALLTHROUGH */ 257856b6ee8Sdjm case KEY_DSA_CERT: 258856b6ee8Sdjm case KEY_ECDSA_CERT: 259856b6ee8Sdjm case KEY_ED25519_CERT: 260856b6ee8Sdjm case KEY_ECDSA_SK_CERT: 261856b6ee8Sdjm case KEY_ED25519_SK_CERT: 262856b6ee8Sdjm case KEY_XMSS_CERT: 263856b6ee8Sdjm append_hostkey_type(b, sshkey_ssh_name(key)); 264856b6ee8Sdjm break; 265856b6ee8Sdjm } 266856b6ee8Sdjm } 267856b6ee8Sdjm if ((ret = sshbuf_dup_string(b)) == NULL) 268856b6ee8Sdjm fatal_f("sshbuf_dup_string failed"); 269856b6ee8Sdjm sshbuf_free(b); 270856b6ee8Sdjm debug_f("%s", ret); 271856b6ee8Sdjm return ret; 272856b6ee8Sdjm } 273856b6ee8Sdjm 274856b6ee8Sdjm struct sshkey * 275856b6ee8Sdjm get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) 276856b6ee8Sdjm { 277856b6ee8Sdjm u_int i; 278856b6ee8Sdjm struct sshkey *key; 279856b6ee8Sdjm 280856b6ee8Sdjm for (i = 0; i < options.num_host_key_files; i++) { 281856b6ee8Sdjm switch (type) { 282856b6ee8Sdjm case KEY_RSA_CERT: 283856b6ee8Sdjm case KEY_DSA_CERT: 284856b6ee8Sdjm case KEY_ECDSA_CERT: 285856b6ee8Sdjm case KEY_ED25519_CERT: 286856b6ee8Sdjm case KEY_ECDSA_SK_CERT: 287856b6ee8Sdjm case KEY_ED25519_SK_CERT: 288856b6ee8Sdjm case KEY_XMSS_CERT: 289856b6ee8Sdjm key = host_certificates[i]; 290856b6ee8Sdjm break; 291856b6ee8Sdjm default: 292856b6ee8Sdjm key = host_pubkeys[i]; 293856b6ee8Sdjm break; 294856b6ee8Sdjm } 295856b6ee8Sdjm if (key == NULL || key->type != type) 296856b6ee8Sdjm continue; 297856b6ee8Sdjm switch (type) { 298856b6ee8Sdjm case KEY_ECDSA: 299856b6ee8Sdjm case KEY_ECDSA_SK: 300856b6ee8Sdjm case KEY_ECDSA_CERT: 301856b6ee8Sdjm case KEY_ECDSA_SK_CERT: 302856b6ee8Sdjm if (key->ecdsa_nid != nid) 303856b6ee8Sdjm continue; 304856b6ee8Sdjm /* FALLTHROUGH */ 305856b6ee8Sdjm default: 306856b6ee8Sdjm return key; 307856b6ee8Sdjm } 308856b6ee8Sdjm } 309856b6ee8Sdjm return NULL; 310856b6ee8Sdjm } 311856b6ee8Sdjm 312856b6ee8Sdjm /* XXX remove */ 313856b6ee8Sdjm struct sshkey * 314856b6ee8Sdjm get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) 315856b6ee8Sdjm { 316856b6ee8Sdjm return NULL; 317856b6ee8Sdjm } 318856b6ee8Sdjm 319856b6ee8Sdjm /* XXX remove */ 320856b6ee8Sdjm struct sshkey * 321856b6ee8Sdjm get_hostkey_by_index(int ind) 322856b6ee8Sdjm { 323856b6ee8Sdjm return NULL; 324856b6ee8Sdjm } 325856b6ee8Sdjm 326856b6ee8Sdjm struct sshkey * 327856b6ee8Sdjm get_hostkey_public_by_index(int ind, struct ssh *ssh) 328856b6ee8Sdjm { 329856b6ee8Sdjm if (ind < 0 || (u_int)ind >= options.num_host_key_files) 330856b6ee8Sdjm return (NULL); 331856b6ee8Sdjm return host_pubkeys[ind]; 332856b6ee8Sdjm } 333856b6ee8Sdjm 334856b6ee8Sdjm int 335856b6ee8Sdjm get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) 336856b6ee8Sdjm { 337856b6ee8Sdjm u_int i; 338856b6ee8Sdjm 339856b6ee8Sdjm for (i = 0; i < options.num_host_key_files; i++) { 340856b6ee8Sdjm if (sshkey_is_cert(key)) { 341856b6ee8Sdjm if (key == host_certificates[i] || 342856b6ee8Sdjm (compare && host_certificates[i] && 343856b6ee8Sdjm sshkey_equal(key, host_certificates[i]))) 344856b6ee8Sdjm return (i); 345856b6ee8Sdjm } else { 346856b6ee8Sdjm if (key == host_pubkeys[i] || 347856b6ee8Sdjm (compare && host_pubkeys[i] && 348856b6ee8Sdjm sshkey_equal(key, host_pubkeys[i]))) 349856b6ee8Sdjm return (i); 350856b6ee8Sdjm } 351856b6ee8Sdjm } 352856b6ee8Sdjm return (-1); 353856b6ee8Sdjm } 354856b6ee8Sdjm 355856b6ee8Sdjm static void 356856b6ee8Sdjm usage(void) 357856b6ee8Sdjm { 358856b6ee8Sdjm fprintf(stderr, "%s, %s\n", SSH_VERSION, SSH_OPENSSL_VERSION); 359856b6ee8Sdjm fprintf(stderr, 360856b6ee8Sdjm "usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n" 361856b6ee8Sdjm " [-E log_file] [-f config_file] [-g login_grace_time]\n" 362856b6ee8Sdjm " [-h host_key_file] [-o option] [-p port] [-u len]\n" 363856b6ee8Sdjm ); 364856b6ee8Sdjm exit(1); 365856b6ee8Sdjm } 366856b6ee8Sdjm 367856b6ee8Sdjm static void 368856b6ee8Sdjm parse_hostkeys(struct sshbuf *hostkeys) 369856b6ee8Sdjm { 370856b6ee8Sdjm int r; 371856b6ee8Sdjm u_int num_keys = 0; 372856b6ee8Sdjm struct sshkey *k; 373856b6ee8Sdjm const u_char *cp; 374856b6ee8Sdjm size_t len; 375856b6ee8Sdjm 376856b6ee8Sdjm while (sshbuf_len(hostkeys) != 0) { 377856b6ee8Sdjm if (num_keys > 2048) 378856b6ee8Sdjm fatal_f("too many hostkeys"); 379856b6ee8Sdjm host_pubkeys = xrecallocarray(host_pubkeys, 380856b6ee8Sdjm num_keys, num_keys + 1, sizeof(*host_pubkeys)); 381856b6ee8Sdjm host_certificates = xrecallocarray(host_certificates, 382856b6ee8Sdjm num_keys, num_keys + 1, sizeof(*host_certificates)); 383856b6ee8Sdjm /* public key */ 384856b6ee8Sdjm k = NULL; 385856b6ee8Sdjm if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0) 386856b6ee8Sdjm fatal_fr(r, "extract pubkey"); 387856b6ee8Sdjm if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0) 388856b6ee8Sdjm fatal_fr(r, "parse pubkey"); 389856b6ee8Sdjm host_pubkeys[num_keys] = k; 390856b6ee8Sdjm if (k) 391856b6ee8Sdjm debug2_f("key %u: %s", num_keys, sshkey_ssh_name(k)); 392856b6ee8Sdjm /* certificate */ 393856b6ee8Sdjm k = NULL; 394856b6ee8Sdjm if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0) 395856b6ee8Sdjm fatal_fr(r, "extract pubkey"); 396856b6ee8Sdjm if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0) 397856b6ee8Sdjm fatal_fr(r, "parse pubkey"); 398856b6ee8Sdjm host_certificates[num_keys] = k; 399856b6ee8Sdjm if (k) 400856b6ee8Sdjm debug2_f("cert %u: %s", num_keys, sshkey_ssh_name(k)); 401856b6ee8Sdjm num_keys++; 402856b6ee8Sdjm } 403856b6ee8Sdjm num_hostkeys = num_keys; 404856b6ee8Sdjm } 405856b6ee8Sdjm 406856b6ee8Sdjm static void 407856b6ee8Sdjm recv_privsep_state(struct ssh *ssh, struct sshbuf *conf, 408856b6ee8Sdjm uint64_t *timing_secretp) 409856b6ee8Sdjm { 410856b6ee8Sdjm struct sshbuf *hostkeys; 411856b6ee8Sdjm 412856b6ee8Sdjm debug3_f("begin"); 413856b6ee8Sdjm 414856b6ee8Sdjm mm_get_state(ssh, &includes, conf, NULL, timing_secretp, 415856b6ee8Sdjm &hostkeys, NULL, NULL, NULL, NULL); 416856b6ee8Sdjm parse_hostkeys(hostkeys); 417856b6ee8Sdjm 418856b6ee8Sdjm sshbuf_free(hostkeys); 419856b6ee8Sdjm 420856b6ee8Sdjm debug3_f("done"); 421856b6ee8Sdjm } 422856b6ee8Sdjm 423856b6ee8Sdjm /* 424856b6ee8Sdjm * Main program for the daemon. 425856b6ee8Sdjm */ 426856b6ee8Sdjm int 427856b6ee8Sdjm main(int ac, char **av) 428856b6ee8Sdjm { 429856b6ee8Sdjm struct ssh *ssh = NULL; 430856b6ee8Sdjm extern char *optarg; 431856b6ee8Sdjm extern int optind; 432856b6ee8Sdjm int r, opt, have_key = 0; 433856b6ee8Sdjm int sock_in = -1, sock_out = -1, rexeced_flag = 0; 434856b6ee8Sdjm char *line, *logfile = NULL; 435856b6ee8Sdjm u_int i; 436856b6ee8Sdjm mode_t new_umask; 437856b6ee8Sdjm Authctxt *authctxt; 438856b6ee8Sdjm struct connection_info *connection_info = NULL; 439856b6ee8Sdjm sigset_t sigmask; 440856b6ee8Sdjm uint64_t timing_secret = 0; 441856b6ee8Sdjm 442856b6ee8Sdjm closefrom(PRIVSEP_MIN_FREE_FD); 443856b6ee8Sdjm sigemptyset(&sigmask); 444856b6ee8Sdjm sigprocmask(SIG_SETMASK, &sigmask, NULL); 445856b6ee8Sdjm 446856b6ee8Sdjm /* Save argv. */ 447856b6ee8Sdjm saved_argv = av; 448856b6ee8Sdjm 449856b6ee8Sdjm /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 450856b6ee8Sdjm sanitise_stdfd(); 451856b6ee8Sdjm 452856b6ee8Sdjm /* Initialize configuration options to their default values. */ 453856b6ee8Sdjm initialize_server_options(&options); 454856b6ee8Sdjm 455856b6ee8Sdjm /* Parse command-line arguments. */ 456856b6ee8Sdjm while ((opt = getopt(ac, av, 457856b6ee8Sdjm "C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) { 458856b6ee8Sdjm switch (opt) { 459856b6ee8Sdjm case '4': 460856b6ee8Sdjm options.address_family = AF_INET; 461856b6ee8Sdjm break; 462856b6ee8Sdjm case '6': 463856b6ee8Sdjm options.address_family = AF_INET6; 464856b6ee8Sdjm break; 465856b6ee8Sdjm case 'f': 466856b6ee8Sdjm config_file_name = optarg; 467856b6ee8Sdjm break; 468856b6ee8Sdjm case 'c': 469856b6ee8Sdjm servconf_add_hostcert("[command-line]", 0, 470856b6ee8Sdjm &options, optarg); 471856b6ee8Sdjm break; 472856b6ee8Sdjm case 'd': 473856b6ee8Sdjm if (debug_flag == 0) { 474856b6ee8Sdjm debug_flag = 1; 475856b6ee8Sdjm options.log_level = SYSLOG_LEVEL_DEBUG1; 476856b6ee8Sdjm } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) 477856b6ee8Sdjm options.log_level++; 478856b6ee8Sdjm break; 479856b6ee8Sdjm case 'D': 480856b6ee8Sdjm /* ignore */ 481856b6ee8Sdjm break; 482856b6ee8Sdjm case 'E': 483856b6ee8Sdjm logfile = optarg; 484856b6ee8Sdjm /* FALLTHROUGH */ 485856b6ee8Sdjm case 'e': 486856b6ee8Sdjm /* ignore */ 487856b6ee8Sdjm break; 488856b6ee8Sdjm case 'i': 489856b6ee8Sdjm inetd_flag = 1; 490856b6ee8Sdjm break; 491856b6ee8Sdjm case 'r': 492856b6ee8Sdjm /* ignore */ 493856b6ee8Sdjm break; 494856b6ee8Sdjm case 'R': 495856b6ee8Sdjm rexeced_flag = 1; 496856b6ee8Sdjm break; 497856b6ee8Sdjm case 'Q': 498856b6ee8Sdjm /* ignored */ 499856b6ee8Sdjm break; 500856b6ee8Sdjm case 'q': 501856b6ee8Sdjm options.log_level = SYSLOG_LEVEL_QUIET; 502856b6ee8Sdjm break; 503856b6ee8Sdjm case 'b': 504856b6ee8Sdjm /* protocol 1, ignored */ 505856b6ee8Sdjm break; 506856b6ee8Sdjm case 'p': 507856b6ee8Sdjm options.ports_from_cmdline = 1; 508856b6ee8Sdjm if (options.num_ports >= MAX_PORTS) { 509856b6ee8Sdjm fprintf(stderr, "too many ports.\n"); 510856b6ee8Sdjm exit(1); 511856b6ee8Sdjm } 512856b6ee8Sdjm options.ports[options.num_ports++] = a2port(optarg); 513856b6ee8Sdjm if (options.ports[options.num_ports-1] <= 0) { 514856b6ee8Sdjm fprintf(stderr, "Bad port number.\n"); 515856b6ee8Sdjm exit(1); 516856b6ee8Sdjm } 517856b6ee8Sdjm break; 518856b6ee8Sdjm case 'g': 519856b6ee8Sdjm if ((options.login_grace_time = convtime(optarg)) == -1) { 520856b6ee8Sdjm fprintf(stderr, "Invalid login grace time.\n"); 521856b6ee8Sdjm exit(1); 522856b6ee8Sdjm } 523856b6ee8Sdjm break; 524856b6ee8Sdjm case 'k': 525856b6ee8Sdjm /* protocol 1, ignored */ 526856b6ee8Sdjm break; 527856b6ee8Sdjm case 'h': 528856b6ee8Sdjm servconf_add_hostkey("[command-line]", 0, 529856b6ee8Sdjm &options, optarg, 1); 530856b6ee8Sdjm break; 531856b6ee8Sdjm case 't': 532856b6ee8Sdjm case 'T': 533856b6ee8Sdjm case 'G': 534856b6ee8Sdjm fatal("test/dump modes not supported"); 535856b6ee8Sdjm break; 536856b6ee8Sdjm case 'C': 537856b6ee8Sdjm connection_info = server_get_connection_info(ssh, 0, 0); 538856b6ee8Sdjm if (parse_server_match_testspec(connection_info, 539856b6ee8Sdjm optarg) == -1) 540856b6ee8Sdjm exit(1); 541856b6ee8Sdjm break; 542856b6ee8Sdjm case 'u': 543856b6ee8Sdjm utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL); 544856b6ee8Sdjm if (utmp_len > HOST_NAME_MAX+1) { 545856b6ee8Sdjm fprintf(stderr, "Invalid utmp length.\n"); 546856b6ee8Sdjm exit(1); 547856b6ee8Sdjm } 548856b6ee8Sdjm break; 549856b6ee8Sdjm case 'o': 550856b6ee8Sdjm line = xstrdup(optarg); 551856b6ee8Sdjm if (process_server_config_line(&options, line, 552856b6ee8Sdjm "command-line", 0, NULL, NULL, &includes) != 0) 553856b6ee8Sdjm exit(1); 554856b6ee8Sdjm free(line); 555856b6ee8Sdjm break; 556856b6ee8Sdjm case 'V': 557856b6ee8Sdjm fprintf(stderr, "%s, %s\n", 558856b6ee8Sdjm SSH_VERSION, SSH_OPENSSL_VERSION); 559856b6ee8Sdjm exit(0); 560856b6ee8Sdjm default: 561856b6ee8Sdjm usage(); 562856b6ee8Sdjm break; 563856b6ee8Sdjm } 564856b6ee8Sdjm } 565856b6ee8Sdjm 566856b6ee8Sdjm if (!rexeced_flag) 567856b6ee8Sdjm fatal("sshd-auth should not be executed directly"); 568856b6ee8Sdjm 569856b6ee8Sdjm #ifdef WITH_OPENSSL 570856b6ee8Sdjm OpenSSL_add_all_algorithms(); 571856b6ee8Sdjm #endif 572856b6ee8Sdjm 573856b6ee8Sdjm /* If requested, redirect the logs to the specified logfile. */ 574856b6ee8Sdjm if (logfile != NULL) { 575856b6ee8Sdjm char *cp, pid_s[32]; 576856b6ee8Sdjm 577856b6ee8Sdjm snprintf(pid_s, sizeof(pid_s), "%ld", (unsigned long)getpid()); 578856b6ee8Sdjm cp = percent_expand(logfile, 579856b6ee8Sdjm "p", pid_s, 580856b6ee8Sdjm "P", "sshd-auth", 581856b6ee8Sdjm (char *)NULL); 582856b6ee8Sdjm log_redirect_stderr_to(cp); 583856b6ee8Sdjm free(cp); 584856b6ee8Sdjm } 585856b6ee8Sdjm 586856b6ee8Sdjm log_init(__progname, 587856b6ee8Sdjm options.log_level == SYSLOG_LEVEL_NOT_SET ? 588856b6ee8Sdjm SYSLOG_LEVEL_INFO : options.log_level, 589856b6ee8Sdjm options.log_facility == SYSLOG_FACILITY_NOT_SET ? 590856b6ee8Sdjm SYSLOG_FACILITY_AUTH : options.log_facility, 1); 591856b6ee8Sdjm 592856b6ee8Sdjm /* XXX can't use monitor_init(); it makes fds */ 593856b6ee8Sdjm pmonitor = xcalloc(1, sizeof(*pmonitor)); 594856b6ee8Sdjm pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; 595856b6ee8Sdjm pmonitor->m_recvfd = PRIVSEP_MONITOR_FD; 596856b6ee8Sdjm pmonitor->m_log_sendfd = PRIVSEP_LOG_FD; 597856b6ee8Sdjm set_log_handler(mm_log_handler, pmonitor); 598856b6ee8Sdjm 599856b6ee8Sdjm /* Check that there are no remaining arguments. */ 600856b6ee8Sdjm if (optind < ac) { 601856b6ee8Sdjm fprintf(stderr, "Extra argument %s.\n", av[optind]); 602856b6ee8Sdjm exit(1); 603856b6ee8Sdjm } 604856b6ee8Sdjm 605856b6ee8Sdjm /* Connection passed by stdin/out */ 606856b6ee8Sdjm if (inetd_flag) { 607856b6ee8Sdjm /* 608856b6ee8Sdjm * NB. must be different fd numbers for the !socket case, 609856b6ee8Sdjm * as packet_connection_is_on_socket() depends on this. 610856b6ee8Sdjm */ 611856b6ee8Sdjm sock_in = dup(STDIN_FILENO); 612856b6ee8Sdjm sock_out = dup(STDOUT_FILENO); 613856b6ee8Sdjm } else { 614856b6ee8Sdjm /* rexec case; accept()ed socket in ancestor listener */ 615856b6ee8Sdjm sock_in = sock_out = dup(STDIN_FILENO); 616856b6ee8Sdjm } 617856b6ee8Sdjm 618856b6ee8Sdjm if (stdfd_devnull(1, 1, 0) == -1) 619856b6ee8Sdjm error("stdfd_devnull failed"); 620856b6ee8Sdjm debug("network sockets: %d, %d", sock_in, sock_out); 621856b6ee8Sdjm 622856b6ee8Sdjm /* 623856b6ee8Sdjm * Register our connection. This turns encryption off because we do 624856b6ee8Sdjm * not have a key. 625856b6ee8Sdjm */ 626856b6ee8Sdjm if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) 627856b6ee8Sdjm fatal("Unable to create connection"); 628856b6ee8Sdjm the_active_state = ssh; 629856b6ee8Sdjm ssh_packet_set_server(ssh); 630856b6ee8Sdjm pmonitor->m_pkex = &ssh->kex; 631856b6ee8Sdjm 632856b6ee8Sdjm /* Fetch our configuration */ 633856b6ee8Sdjm if ((cfg = sshbuf_new()) == NULL) 634856b6ee8Sdjm fatal("sshbuf_new config buf failed"); 635856b6ee8Sdjm setproctitle("%s", "[session-auth early]"); 636856b6ee8Sdjm recv_privsep_state(ssh, cfg, &timing_secret); 637856b6ee8Sdjm parse_server_config(&options, "rexec", cfg, &includes, NULL, 1); 638856b6ee8Sdjm /* Fill in default values for those options not explicitly set. */ 639856b6ee8Sdjm fill_default_server_options(&options); 640856b6ee8Sdjm options.timing_secret = timing_secret; /* XXX eliminate from unpriv */ 641856b6ee8Sdjm 642*874e263eSdtucker /* Reinit logging in case config set Level, Facility or Verbose. */ 643*874e263eSdtucker log_init(__progname, options.log_level, options.log_facility, 1); 644*874e263eSdtucker 645*874e263eSdtucker debug("sshd-auth version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); 646*874e263eSdtucker 647856b6ee8Sdjm #ifdef WITH_OPENSSL 648856b6ee8Sdjm if (options.moduli_file != NULL) 649856b6ee8Sdjm dh_set_moduli_file(options.moduli_file); 650856b6ee8Sdjm #endif 651856b6ee8Sdjm 652856b6ee8Sdjm if (options.host_key_agent) { 653856b6ee8Sdjm if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) 654856b6ee8Sdjm setenv(SSH_AUTHSOCKET_ENV_NAME, 655856b6ee8Sdjm options.host_key_agent, 1); 656856b6ee8Sdjm if ((r = ssh_get_authentication_socket(NULL)) == 0) 657856b6ee8Sdjm have_agent = 1; 658856b6ee8Sdjm else 659856b6ee8Sdjm error_r(r, "Could not connect to agent \"%s\"", 660856b6ee8Sdjm options.host_key_agent); 661856b6ee8Sdjm } 662856b6ee8Sdjm 663856b6ee8Sdjm if (options.num_host_key_files != num_hostkeys) { 664856b6ee8Sdjm fatal("internal error: hostkeys confused (config %u recvd %u)", 665856b6ee8Sdjm options.num_host_key_files, num_hostkeys); 666856b6ee8Sdjm } 667856b6ee8Sdjm 668856b6ee8Sdjm for (i = 0; i < options.num_host_key_files; i++) { 669856b6ee8Sdjm if (host_pubkeys[i] != NULL) { 670856b6ee8Sdjm have_key = 1; 671856b6ee8Sdjm break; 672856b6ee8Sdjm } 673856b6ee8Sdjm } 674856b6ee8Sdjm if (!have_key) 6753bb7d5b0Sjsg fatal("internal error: received no hostkeys"); 676856b6ee8Sdjm 677856b6ee8Sdjm /* Ensure that umask disallows at least group and world write */ 678856b6ee8Sdjm new_umask = umask(0077) | 0022; 679856b6ee8Sdjm (void) umask(new_umask); 680856b6ee8Sdjm 681856b6ee8Sdjm /* Initialize the log (it is reinitialized below in case we forked). */ 682856b6ee8Sdjm log_init(__progname, options.log_level, options.log_facility, 1); 683856b6ee8Sdjm set_log_handler(mm_log_handler, pmonitor); 684856b6ee8Sdjm for (i = 0; i < options.num_log_verbose; i++) 685856b6ee8Sdjm log_verbose_add(options.log_verbose[i]); 686856b6ee8Sdjm 687856b6ee8Sdjm /* 688856b6ee8Sdjm * Chdir to the root directory so that the current disk can be 689856b6ee8Sdjm * unmounted if desired. 690856b6ee8Sdjm */ 691856b6ee8Sdjm if (chdir("/") == -1) 692856b6ee8Sdjm error("chdir(\"/\"): %s", strerror(errno)); 693856b6ee8Sdjm 694856b6ee8Sdjm /* This is the child authenticating a new connection. */ 695856b6ee8Sdjm setproctitle("%s", "[session-auth]"); 696856b6ee8Sdjm 697856b6ee8Sdjm /* Executed child processes don't need these. */ 698856b6ee8Sdjm fcntl(sock_out, F_SETFD, FD_CLOEXEC); 699856b6ee8Sdjm fcntl(sock_in, F_SETFD, FD_CLOEXEC); 700856b6ee8Sdjm 701856b6ee8Sdjm ssh_signal(SIGPIPE, SIG_IGN); 702856b6ee8Sdjm ssh_signal(SIGALRM, SIG_DFL); 703856b6ee8Sdjm ssh_signal(SIGHUP, SIG_DFL); 704856b6ee8Sdjm ssh_signal(SIGTERM, SIG_DFL); 705856b6ee8Sdjm ssh_signal(SIGQUIT, SIG_DFL); 706856b6ee8Sdjm ssh_signal(SIGCHLD, SIG_DFL); 707856b6ee8Sdjm 708856b6ee8Sdjm /* Prepare the channels layer */ 709856b6ee8Sdjm channel_init_channels(ssh); 710856b6ee8Sdjm channel_set_af(ssh, options.address_family); 711856b6ee8Sdjm server_process_channel_timeouts(ssh); 712856b6ee8Sdjm server_process_permitopen(ssh); 713856b6ee8Sdjm 714856b6ee8Sdjm ssh_packet_set_nonblocking(ssh); 715856b6ee8Sdjm 716856b6ee8Sdjm /* allocate authentication context */ 717856b6ee8Sdjm authctxt = xcalloc(1, sizeof(*authctxt)); 718856b6ee8Sdjm ssh->authctxt = authctxt; 719856b6ee8Sdjm 720856b6ee8Sdjm /* XXX global for cleanup, access from other modules */ 721856b6ee8Sdjm the_authctxt = authctxt; 722856b6ee8Sdjm 723856b6ee8Sdjm /* Set default key authentication options */ 724856b6ee8Sdjm if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL) 725856b6ee8Sdjm fatal("allocation failed"); 726856b6ee8Sdjm 727856b6ee8Sdjm /* prepare buffer to collect messages to display to user after login */ 728856b6ee8Sdjm if ((loginmsg = sshbuf_new()) == NULL) 729856b6ee8Sdjm fatal("sshbuf_new loginmsg failed"); 730856b6ee8Sdjm auth_debug_reset(); 731856b6ee8Sdjm 732856b6ee8Sdjm /* Enable challenge-response authentication for privilege separation */ 733856b6ee8Sdjm privsep_challenge_enable(); 734856b6ee8Sdjm 735856b6ee8Sdjm #ifdef GSSAPI 736856b6ee8Sdjm /* Cache supported mechanism OIDs for later use */ 737856b6ee8Sdjm ssh_gssapi_prepare_supported_oids(); 738856b6ee8Sdjm #endif 739856b6ee8Sdjm 740856b6ee8Sdjm privsep_child_demote(); 741856b6ee8Sdjm 742856b6ee8Sdjm /* perform the key exchange */ 743856b6ee8Sdjm /* authenticate user and start session */ 744856b6ee8Sdjm do_ssh2_kex(ssh); 745856b6ee8Sdjm do_authentication2(ssh); 746856b6ee8Sdjm 747856b6ee8Sdjm /* 748856b6ee8Sdjm * The unprivileged child now transfers the current keystate and exits. 749856b6ee8Sdjm */ 750856b6ee8Sdjm mm_send_keystate(ssh, pmonitor); 751856b6ee8Sdjm ssh_packet_clear_keys(ssh); 752856b6ee8Sdjm exit(0); 753856b6ee8Sdjm } 754856b6ee8Sdjm 755856b6ee8Sdjm int 756856b6ee8Sdjm sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, 757856b6ee8Sdjm struct sshkey *pubkey, u_char **signature, size_t *slenp, 758856b6ee8Sdjm const u_char *data, size_t dlen, const char *alg) 759856b6ee8Sdjm { 760856b6ee8Sdjm if (privkey) { 761856b6ee8Sdjm if (mm_sshkey_sign(ssh, privkey, signature, slenp, 762856b6ee8Sdjm data, dlen, alg, options.sk_provider, NULL, 763856b6ee8Sdjm ssh->compat) < 0) 764856b6ee8Sdjm fatal_f("privkey sign failed"); 765856b6ee8Sdjm } else { 766856b6ee8Sdjm if (mm_sshkey_sign(ssh, pubkey, signature, slenp, 767856b6ee8Sdjm data, dlen, alg, options.sk_provider, NULL, 768856b6ee8Sdjm ssh->compat) < 0) 769856b6ee8Sdjm fatal_f("pubkey sign failed"); 770856b6ee8Sdjm } 771856b6ee8Sdjm return 0; 772856b6ee8Sdjm } 773856b6ee8Sdjm 774856b6ee8Sdjm /* SSH2 key exchange */ 775856b6ee8Sdjm static void 776856b6ee8Sdjm do_ssh2_kex(struct ssh *ssh) 777856b6ee8Sdjm { 778856b6ee8Sdjm char *hkalgs = NULL, *myproposal[PROPOSAL_MAX]; 779856b6ee8Sdjm const char *compression = NULL; 780856b6ee8Sdjm struct kex *kex; 781856b6ee8Sdjm int r; 782856b6ee8Sdjm 783856b6ee8Sdjm if (options.rekey_limit || options.rekey_interval) 784856b6ee8Sdjm ssh_packet_set_rekey_limits(ssh, options.rekey_limit, 785856b6ee8Sdjm options.rekey_interval); 786856b6ee8Sdjm 787856b6ee8Sdjm if (options.compression == COMP_NONE) 788856b6ee8Sdjm compression = "none"; 789856b6ee8Sdjm hkalgs = list_hostkey_types(); 790856b6ee8Sdjm 791856b6ee8Sdjm kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms, 792856b6ee8Sdjm options.ciphers, options.macs, compression, hkalgs); 793856b6ee8Sdjm 794856b6ee8Sdjm free(hkalgs); 795856b6ee8Sdjm 796856b6ee8Sdjm /* start key exchange */ 797856b6ee8Sdjm if ((r = kex_setup(ssh, myproposal)) != 0) 798856b6ee8Sdjm fatal_r(r, "kex_setup"); 799856b6ee8Sdjm kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos); 800856b6ee8Sdjm kex = ssh->kex; 801856b6ee8Sdjm 802856b6ee8Sdjm #ifdef WITH_OPENSSL 803856b6ee8Sdjm kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; 804856b6ee8Sdjm kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; 805856b6ee8Sdjm kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; 806856b6ee8Sdjm kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; 807856b6ee8Sdjm kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; 808856b6ee8Sdjm kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 809856b6ee8Sdjm kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 810856b6ee8Sdjm kex->kex[KEX_ECDH_SHA2] = kex_gen_server; 811856b6ee8Sdjm #endif 812856b6ee8Sdjm kex->kex[KEX_C25519_SHA256] = kex_gen_server; 813856b6ee8Sdjm kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; 814856b6ee8Sdjm kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; 815856b6ee8Sdjm kex->load_host_public_key=&get_hostkey_public_by_type; 816856b6ee8Sdjm kex->load_host_private_key=&get_hostkey_private_by_type; 817856b6ee8Sdjm kex->host_key_index=&get_hostkey_index; 818856b6ee8Sdjm kex->sign = sshd_hostkey_sign; 819856b6ee8Sdjm 820856b6ee8Sdjm ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); 821856b6ee8Sdjm kex_proposal_free_entries(myproposal); 822856b6ee8Sdjm 823856b6ee8Sdjm #ifdef DEBUG_KEXDH 824856b6ee8Sdjm /* send 1st encrypted/maced/compressed message */ 825856b6ee8Sdjm if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || 826856b6ee8Sdjm (r = sshpkt_put_cstring(ssh, "markus")) != 0 || 827856b6ee8Sdjm (r = sshpkt_send(ssh)) != 0 || 828856b6ee8Sdjm (r = ssh_packet_write_wait(ssh)) != 0) 829856b6ee8Sdjm fatal_fr(r, "send test"); 830856b6ee8Sdjm #endif 831856b6ee8Sdjm debug("KEX done"); 832856b6ee8Sdjm } 833856b6ee8Sdjm 834856b6ee8Sdjm /* server specific fatal cleanup */ 835856b6ee8Sdjm void 836856b6ee8Sdjm cleanup_exit(int i) 837856b6ee8Sdjm { 838856b6ee8Sdjm _exit(i); 839856b6ee8Sdjm } 840