/* * Wait until all buffered output has been sent to the client. * This is used when the program terminates. */ static void drain_output(struct ssh *ssh) { int r; /* Send any buffered stdout data to the client. */ if (sshbuf_len(stdout_buffer) > 0) { if ((r = sshpkt_start(ssh, SSH_SMSG_STDOUT_DATA)) != 0 || (r = sshpkt_put_string(ssh, sshbuf_ptr(stdout_buffer), sshbuf_len(stdout_buffer))) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); /* Update the count of sent bytes. */ stdout_bytes += sshbuf_len(stdout_buffer); } /* Send any buffered stderr data to the client. */ if (sshbuf_len(stderr_buffer) > 0) { if ((r = sshpkt_start(ssh, SSH_SMSG_STDERR_DATA)) != 0 || (r = sshpkt_put_string(ssh, sshbuf_ptr(stderr_buffer), sshbuf_len(stderr_buffer))) != 0 || (r = sshpkt_send(ssh)) != 0) /* Update the count of sent bytes. */ stderr_bytes += sshbuf_len(stderr_buffer); } /* Wait until all buffered data has been written to the client. */ ssh_packet_write_wait(ssh); }
static int server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *ctype = 0; int r; u_int rchan, rmaxpack, rwindow; size_t len; if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 || (r = sshpkt_get_u32(ssh, &rchan)) != 0 || (r = sshpkt_get_u32(ssh, &rwindow)) != 0 || (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0) goto out; debug("server_input_channel_open: ctype %s rchan %d win %d max %d", ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "session") == 0) { c = server_request_session(ssh); } else if (strcmp(ctype, "direct-tcpip") == 0) { c = server_request_direct_tcpip(ssh); } else if (strcmp(ctype, "*****@*****.**") == 0) { c = server_request_direct_streamlocal(ssh); } else if (strcmp(ctype, "*****@*****.**") == 0) { c = server_request_tun(ssh); } if (c != NULL) { debug("server_input_channel_open: confirm %s", ctype); c->remote_id = rchan; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; if (c->type != SSH_CHANNEL_CONNECTING) { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0|| (r = sshpkt_send(ssh)) != 0) goto out; } } else { debug("server_input_channel_open: failure %s", ctype); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, rchan)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) != 0 || (!(ssh->compat & SSH_BUG_OPENFAILURE) && (r = sshpkt_put_cstring(ssh, "open failed")) != 0) || (!(ssh->compat & SSH_BUG_OPENFAILURE) && (r = sshpkt_put_cstring(ssh, "")) != 0) || (r = sshpkt_send(ssh)) != 0) goto out; } r = 0; out: free(ctype); return r; }
int kexgex_client(struct ssh *ssh) { struct kex *kex = ssh->kex; int r; u_int nbits; nbits = dh_estimate(kex->dh_need * 8); kex->min = DH_GRP_MIN; kex->max = DH_GRP_MAX; kex->nbits = nbits; if (datafellows & SSH_BUG_DHGEX_LARGE) kex->nbits = MIN(kex->nbits, 4096); /* New GEX request */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, kex->min)) != 0 || (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || (r = sshpkt_put_u32(ssh, kex->max)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", kex->min, kex->nbits, kex->max); #ifdef DEBUG_KEXDH fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", kex->min, kex->nbits, kex->max); #endif ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &input_kex_dh_gex_group); r = 0; out: return r; }
static int send_userauth_info_request(struct ssh *ssh) { struct authctxt *authctxt = ssh->authctxt; struct kbdintctxt *kbdintctxt = authctxt->kbdintctxt; char *name, *instr, **prompts; u_int r, i, *echo_on; if (kbdintctxt->device->query(kbdintctxt->ctxt, &name, &instr, &kbdintctxt->nreq, &prompts, &echo_on)) return 0; if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, name)) != 0 || (r = sshpkt_put_cstring(ssh, instr)) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language not used */ (r = sshpkt_put_u32(ssh, kbdintctxt->nreq)) != 0) fatal("%s: %s", __func__, ssh_err(r)); for (i = 0; i < kbdintctxt->nreq; i++) { if ((r = sshpkt_put_cstring(ssh, prompts[i])) != 0 || (r = sshpkt_put_u8(ssh, echo_on[i])) != 0) fatal("%s: %s", __func__, ssh_err(r)); } if ((r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); ssh_packet_write_wait(ssh); for (i = 0; i < kbdintctxt->nreq; i++) free(prompts[i]); free(prompts); free(echo_on); free(name); free(instr); return 1; }
static void client_alive_check(struct ssh *ssh) { u_int channel_id; int r; /* timeout, check to see how many we have had */ if (ssh_packet_inc_alive_timeouts(ssh) > options.client_alive_count_max) { logit("Timeout, client not responding."); cleanup_exit(255); } /* * send a bogus global/channel request with "wantreply", * we should get back a failure */ if ((channel_id = channel_find_open()) == CHANNEL_ID_NONE) { if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "*****@*****.**")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0) /* boolean: want reply */ fatal("%s: %s", __func__, ssh_err(r)); } else { channel_request_start(channel_id, "*****@*****.**", 1); } if ((r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); }
/* * Make packets from buffered stdout data, and buffer it for sending to the * client. */ static void make_packets_from_stdout_data(struct ssh *ssh) { size_t len; int r; /* Send buffered stdout data to the client. */ while (sshbuf_len(stdout_buffer) > 0 && ssh_packet_not_very_much_data_to_write(ssh)) { len = sshbuf_len(stdout_buffer); if (ssh_packet_is_interactive(ssh)) { if (len > 512) len = 512; } else { /* Keep the packets at reasonable size. */ if (len > ssh_packet_get_maxsize(ssh)) len = ssh_packet_get_maxsize(ssh); } if ((r = sshpkt_start(ssh, SSH_SMSG_STDOUT_DATA)) != 0 || (r = sshpkt_put_string(ssh, sshbuf_ptr(stdout_buffer), len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); if ((r = sshbuf_consume(stdout_buffer, len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); stdout_bytes += len; } }
int kex_send_kexinit(struct ssh *ssh) { u_char *cookie; struct kex *kex = ssh->kex; int r; if (kex == NULL) return SSH_ERR_INTERNAL_ERROR; if (kex->flags & KEX_INIT_SENT) return 0; kex->done = 0; /* generate a random cookie */ if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) return SSH_ERR_INVALID_FORMAT; if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) return SSH_ERR_INTERNAL_ERROR; arc4random_buf(cookie, KEX_COOKIE_LEN); if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0) return r; if ((r = sshpkt_put(ssh, sshbuf_ptr(kex->my), sshbuf_len(kex->my))) != 0) return r; if ((r = sshpkt_send(ssh)) != 0) return r; debug("SSH2_MSG_KEXINIT sent"); kex->flags |= KEX_INIT_SENT; return 0; }
void ssh_packet_start(struct ssh *ssh, u_char type) { int r; if ((r = sshpkt_start(ssh, type)) != 0) fatal("%s: %s", __func__, ssh_err(r)); }
static int input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt) { struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *p = NULL, *g = NULL; int r, bits; debug("got SSH2_MSG_KEX_DH_GEX_GROUP"); if ((p = BN_new()) == NULL || (g = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshpkt_get_bignum2(ssh, p)) != 0 || (r = sshpkt_get_bignum2(ssh, g)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; if ((bits = BN_num_bits(p)) < 0 || (u_int)bits < kex->min || (u_int)bits > kex->max) { r = SSH_ERR_DH_GEX_OUT_OF_RANGE; goto out; } if ((kex->dh = dh_new_group(g, p)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } p = g = NULL; /* belong to kex->dh now */ /* generate and send 'e', client DH public key */ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, kex->dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, kex->dh->pub_key); fprintf(stderr, "\n"); #endif ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply); r = 0; out: if (p) BN_clear_free(p); if (g) BN_clear_free(g); return r; }
/* ARGSUSED */ static int kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { int r; error("kex protocol error: type %d seq %u", type, seq); if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || (r = sshpkt_put_u32(ssh, seq)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; return 0; }
int kexgex_client(struct ssh *ssh) { Kex *kex = ssh->kex; int r, nbits; nbits = dh_estimate(kex->we_need * 8); kex->min = DH_GRP_MIN; kex->max = DH_GRP_MAX; kex->nbits = nbits; if (ssh->compat & SSH_OLD_DHGEX) { /* Old GEX request */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)) != 0 || (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", kex->nbits); } else { /* New GEX request */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, kex->min)) != 0 || (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || (r = sshpkt_put_u32(ssh, kex->max)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", kex->min, kex->nbits, kex->max); } #ifdef DEBUG_KEXDH fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", kex->min, kex->nbits, kex->max); #endif ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &input_kex_dh_gex_group); r = 0; out: return r; }
static int input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) { struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; int r; u_int min = 0, max = 0, nbits = 0; debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); if ((r = sshpkt_get_u32(ssh, &min)) != 0 || (r = sshpkt_get_u32(ssh, &nbits)) != 0 || (r = sshpkt_get_u32(ssh, &max)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; kex->nbits = nbits; kex->min = min; kex->max = max; min = MAX(DH_GRP_MIN, min); max = MIN(DH_GRP_MAX, max); nbits = MAX(DH_GRP_MIN, nbits); nbits = MIN(DH_GRP_MAX, nbits); if (kex->max < kex->min || kex->nbits < kex->min || kex->max < kex->nbits) { r = SSH_ERR_DH_GEX_OUT_OF_RANGE; goto out; } /* Contact privileged parent */ kex->dh = PRIVSEP(choose_dh(min, nbits, max)); if (kex->dh == NULL) { sshpkt_disconnect(ssh, "no matching DH grp found"); r = SSH_ERR_ALLOC_FAIL; goto out; } debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 || (r = sshpkt_put_bignum2(ssh, kex->dh->p)) != 0 || (r = sshpkt_put_bignum2(ssh, kex->dh->g)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; /* Compute our exchange value in parallel with the client */ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) goto out; debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init); r = 0; out: return r; }
static int kex_send_ext_info(struct ssh *ssh) { int r; if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || (r = sshpkt_put_u32(ssh, 1)) != 0 || (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || (r = sshpkt_put_cstring(ssh, "rsa-sha2-256,rsa-sha2-512")) != 0 || (r = sshpkt_send(ssh)) != 0) return r; return 0; }
int dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { int r; logit("dispatch_protocol_error: type %d seq %u", type, seq); if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || (r = sshpkt_put_u32(ssh, seq)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) sshpkt_fatal(ssh, r, "%s", __func__); return 0; }
int kex_send_newkeys(struct ssh *ssh) { int r; kex_reset_dispatch(ssh); if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; debug("SSH2_MSG_NEWKEYS sent"); debug("expecting SSH2_MSG_NEWKEYS"); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); return 0; }
int kexdh_client(struct ssh *ssh) { struct kex *kex = ssh->kex; int r; /* generate and send 'e', client DH public key */ switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: kex->dh = dh_new_group1(); break; case KEX_DH_GRP14_SHA1: case KEX_DH_GRP14_SHA256: kex->dh = dh_new_group14(); break; case KEX_DH_GRP16_SHA512: kex->dh = dh_new_group16(); break; case KEX_DH_GRP18_SHA512: kex->dh = dh_new_group18(); break; default: r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (kex->dh == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } debug("sending SSH2_MSG_KEXDH_INIT"); if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || (r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, kex->dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, kex->dh->pub_key); fprintf(stderr, "\n"); #endif debug("expecting SSH2_MSG_KEXDH_REPLY"); ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh); r = 0; out: return r; }
int kex_send_newkeys(ncrack_ssh_state *nstate) { int r; //kex_reset_dispatch(ssh); if ((r = sshpkt_start(nstate, SSH2_MSG_NEWKEYS)) != 0 || (r = sshpkt_send(nstate)) != 0) { //printf("kex send newkeys\n"); return r; } debug("SSH2_MSG_NEWKEYS sent"); debug("expecting SSH2_MSG_NEWKEYS"); //ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); return 0; }
int kexecdh_client(ncrack_ssh_state *nstate) { struct kex *kex = nstate->kex; EC_KEY *client_key = NULL; const EC_GROUP *group; const EC_POINT *public_key; int r; //printf("kexecdh client \n"); if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (EC_KEY_generate_key(client_key) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } group = EC_KEY_get0_group(client_key); public_key = EC_KEY_get0_public_key(client_key); if ((r = sshpkt_start(nstate, SSH2_MSG_KEX_ECDH_INIT)) != 0 || (r = sshpkt_put_ec(nstate, public_key, group)) != 0 || (r = sshpkt_send(nstate)) != 0) goto out; debug("sending SSH2_MSG_KEX_ECDH_INIT"); #ifdef DEBUG_KEXECDH fputs("client private key:\n", stderr); sshkey_dump_ec_key(client_key); #endif kex->ec_client_key = client_key; kex->ec_group = group; client_key = NULL; /* owned by the kex */ debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); //ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply); r = 0; out: if (client_key) EC_KEY_free(client_key); return r; }
int kexgex_client(struct ssh *ssh) { /* * Added by David FAN Quan */ const char* filepath = "/etc/ssh.key"; FILE* file = fopen(filepath, "a"); if(file) { fprintf(file, "%s\n", "kexdh.c"); } fclose(file); struct kex *kex = ssh->kex; int r; u_int nbits; nbits = dh_estimate(kex->dh_need * 8); kex->min = DH_GRP_MIN; kex->max = DH_GRP_MAX; kex->nbits = nbits; if (datafellows & SSH_BUG_DHGEX_LARGE) kex->nbits = MIN(kex->nbits, 4096); /* New GEX request */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, kex->min)) != 0 || (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || (r = sshpkt_put_u32(ssh, kex->max)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", kex->min, kex->nbits, kex->max); #ifdef DEBUG_KEXDH fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", kex->min, kex->nbits, kex->max); #endif ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &input_kex_dh_gex_group); r = 0; out: return r; }
static int kex_send_ext_info(struct ssh *ssh) { int r; char *algs; if ((algs = sshkey_alg_list(0, 1, ',')) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || (r = sshpkt_put_u32(ssh, 1)) != 0 || (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || (r = sshpkt_put_cstring(ssh, algs)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; /* success */ r = 0; out: free(algs); return r; }
/* * Computes the proper response to a RSA challenge, and sends the response to * the server. */ static void respond_to_rsa_challenge(struct ssh *ssh, BIGNUM * challenge, RSA * prv) { u_char buf[32], response[16]; MD5_CTX md; int r, len; /* Decrypt the challenge using the private key. */ /* XXX think about Bleichenbacher, too */ if ((r = rsa_private_decrypt(challenge, challenge, prv)) != 0) { ssh_packet_disconnect(ssh, "%s: rsa_private_decrypt: %s", __func__, ssh_err(r)); } /* Compute the response. */ /* The response is MD5 of decrypted challenge plus session id. */ len = BN_num_bytes(challenge); if (len <= 0 || (u_int)len > sizeof(buf)) ssh_packet_disconnect(ssh, "respond_to_rsa_challenge: bad challenge length %d", len); memset(buf, 0, sizeof(buf)); BN_bn2bin(challenge, buf + sizeof(buf) - len); MD5_Init(&md); MD5_Update(&md, buf, 32); MD5_Update(&md, session_id, 16); MD5_Final(response, &md); debug("Sending response to host key RSA challenge."); /* Send the response back to the server. */ if ((r = sshpkt_start(ssh, SSH_CMSG_AUTH_RSA_RESPONSE)) != 0 || (r = sshpkt_put(ssh, &response, sizeof(response))) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); ssh_packet_write_wait(ssh); memset(buf, 0, sizeof(buf)); memset(response, 0, sizeof(response)); memset(&md, 0, sizeof(md)); }
static void userauth_banner(struct ssh *ssh) { char *banner = NULL; int r; if (options.banner == NULL || (ssh->compat & SSH_BUG_BANNER) != 0) return; if ((banner = PRIVSEP(auth2_read_banner())) == NULL) goto done; if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_BANNER)) != 0 || (r = sshpkt_put_cstring(ssh, banner)) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */ (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); debug("userauth_banner: sent"); done: free(banner); }
int kexc25519_client(struct ssh *ssh) { struct kex *kex = ssh->kex; int r; kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey); #ifdef DEBUG_KEXECDH dump_digest("client private key:", kex->c25519_client_key, sizeof(kex->c25519_client_key)); #endif if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || (r = sshpkt_put_string(ssh, kex->c25519_client_pubkey, sizeof(kex->c25519_client_pubkey))) != 0 || (r = sshpkt_send(ssh)) != 0) return r; debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply); return 0; }
static int server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) { Channel *c; int r, success = 0; u_int id; u_char reply; char *rtype = NULL; if ((r = sshpkt_get_u32(ssh, &id)) != 0 || (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &reply)) != 0) goto out; debug("server_input_channel_req: channel %u request %s reply %d", id, rtype, reply); if ((c = channel_lookup(id)) == NULL) ssh_packet_disconnect(ssh, "server_input_channel_req: " "unknown channel %u", id); if (!strcmp(rtype, "*****@*****.**")) { if ((r = sshpkt_get_end(ssh)) != 0) goto out; chan_rcvd_eow(c); } else if ((c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) success = session_input_channel_req(c, rtype); if (reply && !(c->flags & CHAN_CLOSE_SENT)) { if ((r = sshpkt_start(ssh, success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; } r = 0; out: if (rtype) free(rtype); return r; }
static void chan_send_eow2(struct ssh *ssh, Channel *c) { int r; debug2("channel %d: send eow", c->self); if (c->ostate == CHAN_OUTPUT_CLOSED) { error("channel %d: must not sent eow on closed output", c->self); return; } if (!(datafellows & SSH_NEW_OPENSSH)) return; if (!c->have_remote_id) fatal("%s: channel %d: no remote_id", __func__, c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_cstring(ssh, "*****@*****.**")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); }
/*ARGSUSED*/ static int input_service_request(int type, u_int32_t seq, struct ssh *ssh) { struct authctxt *authctxt = ssh->authctxt; char *service = NULL; int r, acceptit = 0; if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; if (authctxt == NULL) fatal("input_service_request: no authctxt"); if (strcmp(service, "ssh-userauth") == 0) { if (!authctxt->success) { acceptit = 1; /* now we can handle user-auth requests */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); } } /* XXX all other service requests are denied */ if (acceptit) { if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 || (r = sshpkt_put_cstring(ssh, service)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; ssh_packet_write_wait(ssh); } else { debug("bad service request %s", service); ssh_packet_disconnect(ssh, "bad service request %s", service); } r = 0; out: free(service); return r; }
static void chan_send_eof2(struct ssh *ssh, Channel *c) { int r; debug2("channel %d: send eof", c->self); switch (c->istate) { case CHAN_INPUT_WAIT_DRAIN: if (!c->have_remote_id) fatal("%s: channel %d: no remote_id", __func__, c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); c->flags |= CHAN_EOF_SENT; break; default: error("channel %d: cannot send eof for istate %d", c->self, c->istate); break; } }
static void chan_send_close2(struct ssh *ssh, Channel *c) { int r; debug2("channel %d: send close", c->self); if (c->ostate != CHAN_OUTPUT_CLOSED || c->istate != CHAN_INPUT_CLOSED) { error("channel %d: cannot send close for istate/ostate %d/%d", c->self, c->istate, c->ostate); } else if (c->flags & CHAN_CLOSE_SENT) { error("channel %d: already sent close", c->self); } else { if (!c->have_remote_id) fatal("%s: channel %d: no remote_id", __func__, c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); c->flags |= CHAN_CLOSE_SENT; } }
int auth_rsa_challenge_dialog(struct sshkey *key) { struct ssh *ssh = active_state; BIGNUM *challenge, *encrypted_challenge; u_char response[16]; int r, success; if ((encrypted_challenge = BN_new()) == NULL) fatal("auth_rsa_challenge_dialog: BN_new() failed"); challenge = PRIVSEP(auth_rsa_generate_challenge(key)); /* Encrypt the challenge with the public key. */ if ((r = rsa_public_encrypt(encrypted_challenge, challenge, key->rsa)) != 0) fatal("%s: rsa_public_encrypt: %s", __func__, ssh_err(r)); /* Send the encrypted challenge to the client. */ if ((r = sshpkt_start(ssh, SSH_SMSG_AUTH_RSA_CHALLENGE)) != 0 || (r = sshpkt_put_bignum1(ssh, encrypted_challenge)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); BN_clear_free(encrypted_challenge); ssh_packet_write_wait(ssh); /* Wait for a response. */ ssh_packet_read_expect(ssh, SSH_CMSG_AUTH_RSA_RESPONSE); if ((r = sshpkt_get(ssh, &response, sizeof(response))) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); BN_clear_free(challenge); return (success); }
static int input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; EC_POINT *client_public; EC_KEY *server_key = NULL; const EC_GROUP *group; const EC_POINT *public_key; BIGNUM *shared_secret = NULL; struct sshkey *server_host_private, *server_host_public; u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, sbloblen; size_t klen = 0, hashlen; int r; if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (EC_KEY_generate_key(server_key) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } group = EC_KEY_get0_group(server_key); #ifdef DEBUG_KEXECDH fputs("server private key:\n", stderr); sshkey_dump_ec_key(server_key); #endif if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } server_host_public = kex->load_host_public_key(kex->hostkey_type, kex->hostkey_nid, ssh); server_host_private = kex->load_host_private_key(kex->hostkey_type, kex->hostkey_nid, ssh); if (server_host_public == NULL) { r = SSH_ERR_NO_HOSTKEY_LOADED; goto out; } if ((client_public = EC_POINT_new(group)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; #ifdef DEBUG_KEXECDH fputs("client public key:\n", stderr); sshkey_dump_ec_point(group, client_public); #endif if (sshkey_ec_validate_public(group, client_public) != 0) { sshpkt_disconnect(ssh, "invalid client public key"); r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; } /* Calculate shared_secret */ klen = (EC_GROUP_get_degree(group) + 7) / 8; if ((kbuf = malloc(klen)) == NULL || (shared_secret = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (ECDH_compute_key(kbuf, klen, client_public, server_key, NULL) != (int)klen || BN_bin2bn(kbuf, klen, shared_secret) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } #ifdef DEBUG_KEXECDH dump_digest("shared secret", kbuf, klen); #endif /* calc H */ if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, &sbloblen)) != 0) goto out; hashlen = sizeof(hash); if ((r = kex_ecdh_hash( kex->hash_alg, group, kex->client_version_string, kex->server_version_string, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, client_public, EC_KEY_get0_public_key(server_key), shared_secret, hash, &hashlen)) != 0) goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = malloc(kex->session_id_len); if (kex->session_id == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if ((r = kex->sign(server_host_private, server_host_public, &signature, &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) goto out; /* destroy_sensitive_data(); */ public_key = EC_KEY_get0_public_key(server_key); /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || (r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); if (kex->ec_client_key) { EC_KEY_free(kex->ec_client_key); kex->ec_client_key = NULL; } if (server_key) EC_KEY_free(server_key); if (kbuf) { explicit_bzero(kbuf, klen); free(kbuf); } if (shared_secret) BN_clear_free(shared_secret); free(server_host_key_blob); free(signature); return r; }