/* ARGSUSED */ int kex_input_kexinit(int type, u_int32_t seq, void *ctxt) { struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; const u_char *ptr; u_int i; size_t dlen; int r; debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) return SSH_ERR_INVALID_ARGUMENT; ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) if ((r = sshpkt_get_u8(ssh, NULL)) != 0) return r; for (i = 0; i < PROPOSAL_MAX; i++) if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) return r; /* * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported * KEX method has the server move first, but a server might be using * a custom method or one that we otherwise don't support. We should * be prepared to remember first_kex_follows here so we can eat a * packet later. * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means * for cases where the server *doesn't* go first. I guess we should * ignore it when it is set for these cases, which is what we do now. */ if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */ (r = sshpkt_get_end(ssh)) != 0) return r; if (!(kex->flags & KEX_INIT_SENT)) if ((r = kex_send_kexinit(ssh)) != 0) return r; if ((r = kex_choose_conf(ssh)) != 0) return r; if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) return (kex->kex[kex->kex_type])(ssh); return SSH_ERR_INTERNAL_ERROR; }
u_int ssh_packet_get_char(struct ssh *ssh) { u_char ch; int r; if ((r = sshpkt_get_u8(ssh, &ch)) != 0) fatal("%s: %s", __func__, ssh_err(r)); return ch; }
/* ARGSUSED */ int kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) { Kex *kex = ssh->kex; u_char *ptr; u_int i; size_t dlen; int r; debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) return SSH_ERR_INVALID_ARGUMENT; ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) if ((r = sshpkt_get_u8(ssh, NULL)) != 0) return r; for (i = 0; i < PROPOSAL_MAX; i++) if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) return r; if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || (r = sshpkt_get_u32(ssh, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) return r; if (!(kex->flags & KEX_INIT_SENT)) if ((r = kex_send_kexinit(ssh)) != 0) return r; if ((r = kex_choose_conf(ssh)) != 0) return r; if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) return (kex->kex[kex->kex_type])(ssh); return SSH_ERR_INTERNAL_ERROR; }
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 int userauth_passwd(struct ssh *ssh) { char *password; int authenticated = 0, r; u_char change; size_t len; if ((r = sshpkt_get_u8(ssh, &change)) != 0 || (r = sshpkt_get_cstring(ssh, &password, &len)) != 0 || (change && (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) || (r = sshpkt_get_end(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); if (change) logit("password change not supported"); else if (PRIVSEP(auth_password(ssh, password)) == 1) authenticated = 1; explicit_bzero(password, len); free(password); return authenticated; }
static int server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype = NULL; u_char want_reply; int r, success = 0, allocated_listen_port = 0; struct sshbuf *resp = NULL; if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) goto out; debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); /* -R style forwarding */ if (strcmp(rtype, "tcpip-forward") == 0) { struct authctxt *authctxt = ssh->authctxt; struct Forward fwd; if (authctxt->pw == NULL || !authctxt->valid) fatal("server_input_global_request: no/invalid user"); memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &fwd.listen_port)) != 0) goto out; debug("server_input_global_request: tcpip-forward listen %s port %d", fwd.listen_host, fwd.listen_port); /* check permissions */ if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || no_port_forwarding_flag || (!want_reply && fwd.listen_port == 0) || (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED && authctxt->pw->pw_uid != 0)) { success = 0; ssh_packet_send_debug(ssh, "Server has disabled port forwarding."); } else { /* Start listening on the port */ success = channel_setup_remote_fwd_listener(ssh, &fwd, &allocated_listen_port, &options.fwd_opts); } free(fwd.listen_host); if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new", __func__); if (allocated_listen_port != 0 && (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0) fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r)); } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &fwd.listen_port)) != 0) goto out; debug("%s: cancel-tcpip-forward addr %s port %d", __func__, fwd.listen_host, fwd.listen_port); success = channel_cancel_rport_listener(&fwd); free(fwd.listen_host); } else if (strcmp(rtype, "*****@*****.**") == 0) { struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) goto out; debug("server_input_global_request: streamlocal-forward listen path %s", fwd.listen_path); /* check permissions */ if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0 || no_port_forwarding_flag) { success = 0; ssh_packet_send_debug(ssh, "Server has disabled port forwarding."); } else { /* Start listening on the socket */ success = channel_setup_remote_fwd_listener(ssh, &fwd, NULL, &options.fwd_opts); } free(fwd.listen_path); } else if (strcmp(rtype, "*****@*****.**") == 0) { struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) goto out; debug("%s: cancel-streamlocal-forward path %s", __func__, fwd.listen_path); success = channel_cancel_rport_listener(&fwd); free(fwd.listen_path); } else if (strcmp(rtype, "*****@*****.**") == 0) { no_more_sessions = 1; success = 1; } else if (strcmp(rtype, "*****@*****.**") == 0) { success = server_input_hostkeys_prove(&resp); } if (want_reply) { if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 || (success && resp != NULL && (r = sshpkt_put(ssh, sshbuf_ptr(resp), sshbuf_len(resp))) != 0) || (r = sshpkt_send(ssh)) != 0) goto out; ssh_packet_write_wait(ssh); } r = 0; out: free(rtype); sshbuf_free(resp); return r; }