/** * \internal * \brief creates a new Socket object */ ssh_socket ssh_socket_new(ssh_session session) { ssh_socket s; s = malloc(sizeof(struct ssh_socket_struct)); if (s == NULL) { ssh_set_error_oom(session); return NULL; } s->fd_in = SSH_INVALID_SOCKET; s->fd_out= SSH_INVALID_SOCKET; s->last_errno = -1; s->fd_is_socket = 1; s->session = session; s->in_buffer = ssh_buffer_new(); if (s->in_buffer == NULL) { ssh_set_error_oom(session); SAFE_FREE(s); return NULL; } s->out_buffer=ssh_buffer_new(); if (s->out_buffer == NULL) { ssh_set_error_oom(session); ssh_buffer_free(s->in_buffer); SAFE_FREE(s); return NULL; } s->read_wontblock = 0; s->write_wontblock = 0; s->data_except = 0; s->poll_in=s->poll_out=NULL; s->state=SSH_SOCKET_NONE; return s; }
static ssh_buffer ssh_gssapi_build_mic(ssh_session session){ ssh_buffer mic_buffer; int rc; mic_buffer = ssh_buffer_new(); if (mic_buffer == NULL) { ssh_set_error_oom(session); return NULL; } rc = ssh_buffer_pack(mic_buffer, "dPbsss", session->current_crypto->digest_len, (size_t)session->current_crypto->digest_len, session->current_crypto->session_id, SSH2_MSG_USERAUTH_REQUEST, session->gssapi->user, "ssh-connection", "gssapi-with-mic"); if (rc != SSH_OK) { ssh_set_error_oom(session); ssh_buffer_free(mic_buffer); return NULL; } return mic_buffer; }
static int crypt_set_algorithms1(ssh_session session) { int i = 0; struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab(); /* right now, we force 3des-cbc to be taken */ while (ssh_ciphertab[i].name && strcmp(ssh_ciphertab[i].name, "3des-cbc-ssh1")) { i++; } if (ssh_ciphertab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "cipher 3des-cbc-ssh1 not found!"); return SSH_ERROR; } session->next_crypto->out_cipher = cipher_new(i); if (session->next_crypto->out_cipher == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } session->next_crypto->in_cipher = cipher_new(i); if (session->next_crypto->in_cipher == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } return SSH_OK; }
int ssh_send_keepalive(ssh_session session) { /* TODO check the reply and all that */ struct ssh_string_struct *req; int reply = 1; int rc = SSH_ERROR; enter_function(); req = ssh_string_from_char("*****@*****.**"); if (req == NULL) { ssh_set_error_oom(session); goto out; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 || buffer_add_ssh_string(session->out_buffer, req) < 0 || buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) { ssh_set_error_oom(session); goto out; } if (packet_send(session) == SSH_ERROR) goto out; ssh_handle_packets(session, 0); ssh_log(session, SSH_LOG_PACKET, "Sent a keepalive"); rc = SSH_OK; out: ssh_string_free(req); leave_function(); return rc; }
/** * @brief sets the key exchange parameters to be sent to the server, * in function of the options and available methods. */ int ssh_set_client_kex(ssh_session session) { struct ssh_kex_struct *client= &session->next_crypto->client_kex; const char *wanted; char *kex = NULL; char *kex_tmp = NULL; int ok; int i; size_t kex_len, len; ok = ssh_get_random(client->cookie, 16, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); return SSH_ERROR; } memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **)); /* first check if we have specific host key methods */ if (session->opts.wanted_methods[SSH_HOSTKEYS] == NULL) { /* Only if no override */ session->opts.wanted_methods[SSH_HOSTKEYS] = ssh_client_select_hostkeys(session); } for (i = 0; i < KEX_METHODS_SIZE; i++) { wanted = session->opts.wanted_methods[i]; if (wanted == NULL) wanted = default_methods[i]; client->methods[i] = strdup(wanted); if (client->methods[i] == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } } /* For rekeying, skip the extension negotiation */ if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { return SSH_OK; } /* Here we append ext-info-c to the list of kex algorithms */ kex = client->methods[SSH_KEX]; len = strlen(kex); if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) { /* Overflow */ return SSH_ERROR; } kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */ kex_tmp = realloc(kex, kex_len); if (kex_tmp == NULL) { free(kex); ssh_set_error_oom(session); return SSH_ERROR; } snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT); client->methods[SSH_KEX] = kex_tmp; return SSH_OK; }
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ int i; if (session == NULL){ ssh_set_error(sshbind, SSH_FATAL,"session is null"); return SSH_ERROR; } session->server = 1; session->version = 2; /* copy options */ for (i = 0; i < 10; ++i) { if (sshbind->wanted_methods[i]) { session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]); if (session->wanted_methods[i] == NULL) { return SSH_ERROR; } } } if (sshbind->bindaddr == NULL) session->bindaddr = NULL; else { SAFE_FREE(session->bindaddr); session->bindaddr = strdup(sshbind->bindaddr); if (session->bindaddr == NULL) { return SSH_ERROR; } } session->common.log_verbosity = sshbind->common.log_verbosity; ssh_socket_free(session->socket); session->socket = ssh_socket_new(session); if (session->socket == NULL) { /* perhaps it may be better to copy the error from session to sshbind */ ssh_set_error_oom(sshbind); return SSH_ERROR; } ssh_socket_set_fd(session->socket, fd); ssh_socket_get_poll_handle_out(session->socket); if (sshbind->dsa) { session->srv.dsa_key = ssh_key_dup(sshbind->dsa); if (session->srv.dsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } if (sshbind->rsa) { session->srv.rsa_key = ssh_key_dup(sshbind->rsa); if (session->srv.rsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } return SSH_OK; }
int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port) { int rc; SSH_LOG(SSH_LOG_FUNCTIONS, "Accepting a global request"); if (msg->global_request.want_reply) { if (buffer_add_u8(msg->session->out_buffer , SSH2_MSG_REQUEST_SUCCESS) < 0) { goto error; } if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD && msg->global_request.bind_port == 0) { rc = ssh_buffer_pack(msg->session->out_buffer, "d", bound_port); if (rc != SSH_ERROR) { ssh_set_error_oom(msg->session); goto error; } } return packet_send(msg->session); } if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD && msg->global_request.bind_port == 0) { SSH_LOG(SSH_LOG_PACKET, "The client doesn't want to know the remote port!"); } return SSH_OK; error: return SSH_ERROR; }
static int build_session_id1(ssh_session session, ssh_string servern, ssh_string hostn) { MD5CTX md5 = NULL; md5 = md5_init(); if (md5 == NULL) { return -1; } #ifdef DEBUG_CRYPTO ssh_print_hexa("host modulus",ssh_string_data(hostn),ssh_string_len(hostn)); ssh_print_hexa("server modulus",ssh_string_data(servern),ssh_string_len(servern)); #endif md5_update(md5,ssh_string_data(hostn),ssh_string_len(hostn)); md5_update(md5,ssh_string_data(servern),ssh_string_len(servern)); md5_update(md5,session->next_crypto->server_kex.cookie,8); if(session->next_crypto->session_id != NULL) SAFE_FREE(session->next_crypto->session_id); session->next_crypto->session_id = malloc(MD5_DIGEST_LEN); if(session->next_crypto->session_id == NULL){ ssh_set_error_oom(session); return SSH_ERROR; } md5_final(session->next_crypto->session_id,md5); #ifdef DEBUG_CRYPTO ssh_print_hexa("session_id",session->next_crypto->session_id,MD5_DIGEST_LEN); #endif return 0; }
static int ssh_add_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb, int prepend) { ssh_session session = NULL; int rc; if (channel == NULL || cb == NULL) { return SSH_ERROR; } session = channel->session; if (is_callback_valid(session, cb)) { ssh_set_error(session, SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; }; if (channel->callbacks == NULL) { channel->callbacks = ssh_list_new(); if (channel->callbacks == NULL){ ssh_set_error_oom(session); return SSH_ERROR; } } if (prepend) { rc = ssh_list_prepend(channel->callbacks, cb); } else { rc = ssh_list_append(channel->callbacks, cb); } return rc; }
static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid){ int rc; int i; rc = ssh_buffer_pack(session->out_buffer, "bsssd", SSH2_MSG_USERAUTH_REQUEST, session->opts.username, "ssh-connection", "gssapi-with-mic", n_oid); if (rc != SSH_OK) { ssh_set_error_oom(session); goto fail; } for (i=0; i<n_oid; ++i){ rc = buffer_add_ssh_string(session->out_buffer, oid_set[i]); if (rc < 0) { goto fail; } } session->auth_state = SSH_AUTH_STATE_GSSAPI_REQUEST_SENT; return packet_send(session); fail: ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; }
static int ssh_message_channel_request_reply_default(ssh_message msg) { uint32_t channel; int rc; if (msg->channel_request.want_reply) { channel = msg->channel_request.channel->remote_channel; SSH_LOG(SSH_LOG_PACKET, "Sending a default channel_request denied to channel %d", channel); rc = ssh_buffer_pack(msg->session->out_buffer, "bd", SSH2_MSG_CHANNEL_FAILURE, channel); if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } return packet_send(msg->session); } SSH_LOG(SSH_LOG_PACKET, "The client doesn't want to know the request failed!"); return SSH_OK; }
int ssh_send_keepalive(ssh_session session) { int rc; rc = ssh_buffer_pack(session->out_buffer, "bsb", SSH2_MSG_GLOBAL_REQUEST, "*****@*****.**", 1); if (rc != SSH_OK) { goto err; } if (packet_send(session) == SSH_ERROR) { goto err; } ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING); SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive"); return SSH_OK; err: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; }
static int ssh_gssapi_send_mic(ssh_session session){ OM_uint32 maj_stat, min_stat; gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER; ssh_buffer mic_buffer; int rc; SSH_LOG(SSH_LOG_PACKET,"Sending SSH_MSG_USERAUTH_GSSAPI_MIC"); mic_buffer = ssh_gssapi_build_mic(session); if (mic_buffer == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } mic_buf.length = ssh_buffer_get_len(mic_buffer); mic_buf.value = ssh_buffer_get_begin(mic_buffer); maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf); if (GSS_ERROR(maj_stat)){ ssh_buffer_free(mic_buffer); ssh_gssapi_log_error(0, "generating MIC", maj_stat); return SSH_ERROR; } rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_GSSAPI_MIC); if (rc < 0) { ssh_buffer_free(mic_buffer); ssh_set_error_oom(session); return SSH_ERROR; } rc = buffer_add_u32(session->out_buffer, htonl(mic_token_buf.length)); if (rc < 0) { ssh_buffer_free(mic_buffer); ssh_set_error_oom(session); return SSH_ERROR; } rc = buffer_add_data(session->out_buffer, mic_token_buf.value, mic_token_buf.length); ssh_buffer_free(mic_buffer); if (rc < 0) { ssh_set_error_oom(session); return SSH_ERROR; } return packet_send(session); }
ssh_pcap_context ssh_pcap_context_new(ssh_session session){ ssh_pcap_context ctx = (struct ssh_pcap_context_struct *) malloc(sizeof(struct ssh_pcap_context_struct)); if(ctx==NULL){ ssh_set_error_oom(session); return NULL; } ZERO_STRUCTP(ctx); ctx->session=session; return ctx; }
/** \internal * \brief buffered write of data * \returns SSH_OK, or SSH_ERROR * \warning has no effect on socket before a flush */ int ssh_socket_write(ssh_socket s, const void *buffer, int len) { if(len > 0) { if (ssh_buffer_add_data(s->out_buffer, buffer, len) < 0) { ssh_set_error_oom(s->session); return SSH_ERROR; } ssh_socket_nonblocking_flush(s); } return SSH_OK; }
/** @internal * @brief sends a SSH_MSG_USERAUTH_GSSAPI_RESPONSE packet * @param[in] oid the OID that was selected for authentication */ static int ssh_gssapi_send_response(ssh_session session, ssh_string oid){ if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE) < 0 || buffer_add_ssh_string(session->out_buffer,oid) < 0) { ssh_set_error_oom(session); return SSH_ERROR; } packet_send(session); SSH_LOG(SSH_LOG_PACKET, "Sent SSH_MSG_USERAUTH_GSSAPI_RESPONSE"); return SSH_OK; }
/** @brief sets the pcap file used to trace the session * @param current session * @param pcap an handler to a pcap file. A pcap file may be used in several * sessions. * @returns SSH_ERROR in case of error, SSH_OK otherwise. */ int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcap){ ssh_pcap_context ctx=ssh_pcap_context_new(session); if(ctx==NULL){ ssh_set_error_oom(session); return SSH_ERROR; } ctx->file=pcap; if(session->pcap_ctx) ssh_pcap_context_free(session->pcap_ctx); session->pcap_ctx=ctx; return SSH_OK; }
int ssh_get_key_params(ssh_session session, ssh_key *privkey){ ssh_key pubkey; ssh_string pubkey_blob; int rc; switch(session->srv.hostkey) { case SSH_KEYTYPE_DSS: *privkey = session->srv.dsa_key; break; case SSH_KEYTYPE_RSA: *privkey = session->srv.rsa_key; break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: *privkey = session->srv.ecdsa_key; break; case SSH_KEYTYPE_ED25519: *privkey = session->srv.ed25519_key; break; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: *privkey = NULL; } rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Could not get the public key from the private key"); return -1; } rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); ssh_key_free(pubkey); if (rc < 0) { ssh_set_error_oom(session); return -1; } rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); ssh_string_free(pubkey_blob); if (rc != 0) { ssh_set_error(session, SSH_FATAL, "Could not import server public key"); return -1; } return SSH_OK; }
/** @internal * replies to an SSH_AUTH packet with a default (denied) response. */ int ssh_auth_reply_default(ssh_session session,int partial) { char methods_c[128] = {0}; int rc = SSH_ERROR; if (session->auth_methods == 0) { session->auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD; } if (session->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { strncat(methods_c, "publickey,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC){ strncat(methods_c,"gssapi-with-mic,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { strncat(methods_c, "keyboard-interactive,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_PASSWORD) { strncat(methods_c, "password,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth_methods & SSH_AUTH_METHOD_HOSTBASED) { strncat(methods_c, "hostbased,", sizeof(methods_c) - strlen(methods_c) - 1); } if (methods_c[0] == '\0' || methods_c[strlen(methods_c)-1] != ',') { return SSH_ERROR; } /* Strip the comma. */ methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at SSH_LOG(SSH_LOG_PACKET, "Sending a auth failure. methods that can continue: %s", methods_c); rc = ssh_buffer_pack(session->out_buffer, "bsb", SSH2_MSG_USERAUTH_FAILURE, methods_c, partial ? 1 : 0); if (rc != SSH_OK){ ssh_set_error_oom(session); return SSH_ERROR; } rc = packet_send(session); return rc; }
static int ssh_gssapi_send_mic(ssh_session session){ OM_uint32 maj_stat, min_stat; gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER; ssh_buffer mic_buffer; int rc; SSH_LOG(SSH_LOG_PACKET,"Sending SSH_MSG_USERAUTH_GSSAPI_MIC"); mic_buffer = ssh_gssapi_build_mic(session); if (mic_buffer == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } mic_buf.length = ssh_buffer_get_len(mic_buffer); mic_buf.value = ssh_buffer_get_begin(mic_buffer); maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf); if (GSS_ERROR(maj_stat)){ ssh_buffer_free(mic_buffer); ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "generating MIC", maj_stat); return SSH_ERROR; } rc = ssh_buffer_pack(session->out_buffer, "bdP", SSH2_MSG_USERAUTH_GSSAPI_MIC, mic_token_buf.length, (size_t)mic_token_buf.length, mic_token_buf.value); if (rc != SSH_OK) { ssh_buffer_free(mic_buffer); ssh_set_error_oom(session); return SSH_ERROR; } return packet_send(session); }
/** @internal * @initializes a gssapi context for authentication */ static int ssh_gssapi_init(ssh_session session){ if (session->gssapi != NULL) return SSH_OK; session->gssapi = malloc(sizeof(struct ssh_gssapi_struct)); if(!session->gssapi){ ssh_set_error_oom(session); return SSH_ERROR; } ZERO_STRUCTP(session->gssapi); session->gssapi->server_creds = GSS_C_NO_CREDENTIAL; session->gssapi->client_creds = GSS_C_NO_CREDENTIAL; session->gssapi->ctx = GSS_C_NO_CONTEXT; session->gssapi->state = SSH_GSSAPI_STATE_NONE; return SSH_OK; }
/** @internal * @brief sends a SSH_MSG_UNIMPLEMENTED answer to an unhandled packet * @param session the SSH session * @param seqnum the sequence number of the unknown packet * @return SSH_ERROR on error, else SSH_OK */ int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum){ int rc; rc = ssh_buffer_pack(session->out_buffer, "bd", SSH2_MSG_UNIMPLEMENTED, seqnum); if (rc != SSH_OK) { ssh_set_error_oom(session); return SSH_ERROR; } rc = ssh_packet_send(session); return rc; }
/** * @internal * * @brief Request a service from the SSH server. * * Service requests are for example: ssh-userauth, ssh-connection, etc. * * @param session The session to use to ask for a service request. * @param service The service request. * * @return SSH_OK on success * @return SSH_ERROR on error * @return SSH_AGAIN No response received yet * @bug actually only works with ssh-userauth */ int ssh_service_request(ssh_session session, const char *service) { int rc=SSH_ERROR; if(session->auth_service_state != SSH_AUTH_SERVICE_NONE) goto pending; rc = ssh_buffer_pack(session->out_buffer, "bs", SSH2_MSG_SERVICE_REQUEST, service); if (rc != SSH_OK){ ssh_set_error_oom(session); return SSH_ERROR; } session->auth_service_state=SSH_AUTH_SERVICE_SENT; if (ssh_packet_send(session) == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Sending SSH2_MSG_SERVICE_REQUEST failed."); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service); pending: rc=ssh_handle_packets_termination(session,SSH_TIMEOUT_USER, ssh_service_request_termination, session); if (rc == SSH_ERROR) { return SSH_ERROR; } switch(session->auth_service_state){ case SSH_AUTH_SERVICE_DENIED: ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied"); break; case SSH_AUTH_SERVICE_ACCEPTED: rc=SSH_OK; break; case SSH_AUTH_SERVICE_SENT: rc=SSH_AGAIN; break; case SSH_AUTH_SERVICE_NONE: case SSH_AUTH_SERVICE_USER_SENT: /* Invalid state, SSH1 specific */ rc=SSH_ERROR; break; } return rc; }
/* Answer OK to a pubkey auth request */ int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey) { int rc; if (msg == NULL) { return SSH_ERROR; } rc = ssh_buffer_pack(msg->session->out_buffer, "bSS", SSH2_MSG_USERAUTH_PK_OK, algo, pubkey); if(rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } rc = packet_send(msg->session); return rc; }
static int ssh_message_channel_request_open_reply_default(ssh_message msg) { int rc; SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a channel"); rc = ssh_buffer_pack(msg->session->out_buffer, "bdddd", SSH2_MSG_CHANNEL_OPEN_FAILURE, msg->channel_request_open.sender, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, /* reason is empty string */ 0); /* language string */ if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } rc = packet_send(msg->session); return rc; }
int ssh_send_keepalive(ssh_session session) { struct ssh_string_struct *req; int rc; rc = buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST); if (rc < 0) { goto err; } req = ssh_string_from_char("*****@*****.**"); if (req == NULL) { goto err; } rc = buffer_add_ssh_string(session->out_buffer, req); ssh_string_free(req); if (rc < 0) { goto err; } rc = buffer_add_u8(session->out_buffer, 1); if (rc < 0) { goto err; } if (packet_send(session) == SSH_ERROR) { goto err; } ssh_handle_packets(session, 0); SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive"); return SSH_OK; err: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; }
int ssh_message_service_reply_success(ssh_message msg) { ssh_session session; int rc; if (msg == NULL) { return SSH_ERROR; } session = msg->session; SSH_LOG(SSH_LOG_PACKET, "Sending a SERVICE_ACCEPT for service %s", msg->service_request.service); rc = ssh_buffer_pack(session->out_buffer, "bs", SSH2_MSG_SERVICE_ACCEPT, msg->service_request.service); if (rc != SSH_OK){ ssh_set_error_oom(session); return SSH_ERROR; } rc = packet_send(msg->session); return rc; }
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col, int row) { ssh_session session; ssh_string str = NULL; if (channel == NULL) { return SSH_ERROR; } session = channel->session; if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){ ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state"); return SSH_ERROR; } str = ssh_string_from_char(terminal); if (str == NULL) { ssh_set_error_oom(session); return -1; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0 || buffer_add_ssh_string(session->out_buffer, str) < 0) { ssh_string_free(str); return -1; } ssh_string_free(str); if (buffer_add_u32(session->out_buffer, ntohl(row)) < 0 || buffer_add_u32(session->out_buffer, ntohl(col)) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 || /* x */ buffer_add_u32(session->out_buffer, 0) < 0 || /* y */ buffer_add_u8(session->out_buffer, 0) < 0) { /* tty things */ return -1; } ssh_log(session, SSH_LOG_FUNCTIONS, "Opening a ssh1 pty"); channel->request_state = SSH_CHANNEL_REQ_STATE_PENDING; if (packet_send(session) == SSH_ERROR) { return -1; } while (channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING) { ssh_handle_packets(session, SSH_TIMEOUT_INFINITE); } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_ERROR: case SSH_CHANNEL_REQ_STATE_PENDING: case SSH_CHANNEL_REQ_STATE_NONE: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; return SSH_ERROR; case SSH_CHANNEL_REQ_STATE_ACCEPTED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_log(session, SSH_LOG_RARE, "PTY: Success"); return SSH_OK; case SSH_CHANNEL_REQ_STATE_DENIED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_set_error(session, SSH_REQUEST_DENIED, "Server denied PTY allocation"); ssh_log(session, SSH_LOG_RARE, "PTY: denied\n"); return SSH_ERROR; } // Not reached return SSH_ERROR; }
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ int i, rc; if (session == NULL){ ssh_set_error(sshbind, SSH_FATAL,"session is null"); return SSH_ERROR; } session->server = 1; session->version = 2; /* copy options */ for (i = 0; i < 10; i++) { if (sshbind->wanted_methods[i]) { session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]); if (session->opts.wanted_methods[i] == NULL) { return SSH_ERROR; } } } if (sshbind->bindaddr == NULL) session->opts.bindaddr = NULL; else { SAFE_FREE(session->opts.bindaddr); session->opts.bindaddr = strdup(sshbind->bindaddr); if (session->opts.bindaddr == NULL) { return SSH_ERROR; } } session->common.log_verbosity = sshbind->common.log_verbosity; if(sshbind->banner != NULL) session->opts.custombanner = strdup(sshbind->banner); ssh_socket_free(session->socket); session->socket = ssh_socket_new(session); if (session->socket == NULL) { /* perhaps it may be better to copy the error from session to sshbind */ ssh_set_error_oom(sshbind); return SSH_ERROR; } ssh_socket_set_fd(session->socket, fd); ssh_socket_get_poll_handle_out(session->socket); /* We must try to import any keys that could be imported in case * we are not using ssh_bind_listen (which is the other place * where keys can be imported) on this ssh_bind and are instead * only using ssh_bind_accept_fd to manage sockets ourselves. */ rc = ssh_bind_import_keys(sshbind); if (rc != SSH_OK) { return SSH_ERROR; } #ifdef HAVE_ECC if (sshbind->ecdsa) { session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa); if (session->srv.ecdsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } #endif if (sshbind->dsa) { session->srv.dsa_key = ssh_key_dup(sshbind->dsa); if (session->srv.dsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } if (sshbind->rsa) { session->srv.rsa_key = ssh_key_dup(sshbind->rsa); if (session->srv.rsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } if (sshbind->ed25519 != NULL) { session->srv.ed25519_key = ssh_key_dup(sshbind->ed25519); if (session->srv.ed25519_key == NULL){ ssh_set_error_oom(sshbind); return SSH_ERROR; } } /* force PRNG to change state in case we fork after ssh_bind_accept */ ssh_reseed(); return SSH_OK; }
int ssh_message_auth_interactive_request(ssh_message msg, const char *name, const char *instruction, unsigned int num_prompts, const char **prompts, char *echo) { int rc; unsigned int i = 0; if(name == NULL || instruction == NULL) { return SSH_ERROR; } if(num_prompts > 0 && (prompts == NULL || echo == NULL)) { return SSH_ERROR; } rc = ssh_buffer_pack(msg->session->out_buffer, "bsssd", SSH2_MSG_USERAUTH_INFO_REQUEST, name, instruction, "", /* language tag */ num_prompts); if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } for(i = 0; i < num_prompts; i++) { rc = ssh_buffer_pack(msg->session->out_buffer, "sb", prompts[i], echo[1] ? 1 : 0); if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } } rc = packet_send(msg->session); /* fill in the kbdint structure */ if (msg->session->kbdint == NULL) { SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a " "keyboard-interactive response but it " "seems we didn't send the request."); msg->session->kbdint = ssh_kbdint_new(); if (msg->session->kbdint == NULL) { ssh_set_error_oom(msg->session); return SSH_ERROR; } } else { ssh_kbdint_clean(msg->session->kbdint); } msg->session->kbdint->name = strdup(name); if(msg->session->kbdint->name == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } msg->session->kbdint->instruction = strdup(instruction); if(msg->session->kbdint->instruction == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } msg->session->kbdint->nprompts = num_prompts; if(num_prompts > 0) { msg->session->kbdint->prompts = malloc(num_prompts * sizeof(char *)); if (msg->session->kbdint->prompts == NULL) { msg->session->kbdint->nprompts = 0; ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_ERROR; } msg->session->kbdint->echo = malloc(num_prompts * sizeof(unsigned char)); if (msg->session->kbdint->echo == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_ERROR; } for (i = 0; i < num_prompts; i++) { msg->session->kbdint->echo[i] = echo[i]; msg->session->kbdint->prompts[i] = strdup(prompts[i]); if (msg->session->kbdint->prompts[i] == NULL) { ssh_set_error_oom(msg->session); msg->session->kbdint->nprompts = i; ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } } } else { msg->session->kbdint->prompts = NULL; msg->session->kbdint->echo = NULL; } return rc; }