/* * This function concats in a buffer the values needed to do a signature * verification. */ ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg, char *service) { /* The value of 'signature' is a signature by the corresponding private key over the following data, in the following order: string session identifier byte SSH_MSG_USERAUTH_REQUEST string user name string service name string "publickey" boolean TRUE string public key algorithm name string public key to be used for authentication */ struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto : session->next_crypto; ssh_buffer buffer = NULL; ssh_string session_id = NULL; uint8_t type = SSH2_MSG_USERAUTH_REQUEST; ssh_string username = ssh_string_from_char(msg->auth_request.username); ssh_string servicename = ssh_string_from_char(service); ssh_string method = ssh_string_from_char("publickey"); uint8_t has_sign = 1; ssh_string algo = ssh_string_from_char(msg->auth_request.public_key->type_c); ssh_string publickey = publickey_to_string(msg->auth_request.public_key); buffer = ssh_buffer_new(); if (buffer == NULL) { goto error; } session_id = ssh_string_new(SHA_DIGEST_LEN); if (session_id == NULL) { ssh_buffer_free(buffer); buffer = NULL; goto error; } ssh_string_fill(session_id, crypto->session_id, SHA_DIGEST_LEN); if(buffer_add_ssh_string(buffer, session_id) < 0 || buffer_add_u8(buffer, type) < 0 || buffer_add_ssh_string(buffer, username) < 0 || buffer_add_ssh_string(buffer, servicename) < 0 || buffer_add_ssh_string(buffer, method) < 0 || buffer_add_u8(buffer, has_sign) < 0 || buffer_add_ssh_string(buffer, algo) < 0 || buffer_add_ssh_string(buffer, publickey) < 0) { ssh_buffer_free(buffer); buffer = NULL; goto error; } error: if(session_id) ssh_string_free(session_id); if(username) ssh_string_free(username); if(servicename) ssh_string_free(servicename); if(method) ssh_string_free(method); if(algo) ssh_string_free(algo); if(publickey) ssh_string_free(publickey); return buffer; }
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; }
static int ssh_message_auth_reply_default(ssh_message msg,int partial) { ssh_session session = msg->session; char methods_c[128] = {0}; ssh_string methods = NULL; int rc = SSH_ERROR; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_FAILURE) < 0) { return rc; } if (session->auth_methods == 0) { session->auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD; } if (session->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { strcat(methods_c, "publickey,"); } if (session->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { strcat(methods_c, "keyboard-interactive,"); } if (session->auth_methods & SSH_AUTH_METHOD_PASSWORD) { strcat(methods_c, "password,"); } if (session->auth_methods & SSH_AUTH_METHOD_HOSTBASED) { strcat(methods_c, "hostbased,"); } /* Strip the comma. */ methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at ssh_log(session, SSH_LOG_PACKET, "Sending a auth failure. methods that can continue: %s", methods_c); methods = ssh_string_from_char(methods_c); if (methods == NULL) { goto error; } if (buffer_add_ssh_string(msg->session->out_buffer, methods) < 0) { goto error; } if (partial) { if (buffer_add_u8(session->out_buffer, 1) < 0) { goto error; } } else { if (buffer_add_u8(session->out_buffer, 0) < 0) { goto error; } } rc = packet_send(msg->session); error: ssh_string_free(methods); leave_function(); return rc; }
/* this function only sends the predefined set of kex methods */ int ssh_send_kex(ssh_session session, int server_kex) { struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex : &session->next_crypto->client_kex); ssh_string str = NULL; int i; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXINIT) < 0) { goto error; } if (buffer_add_data(session->out_buffer, kex->cookie, 16) < 0) { goto error; } if (hashbufout_add_cookie(session) < 0) { goto error; } ssh_list_kex(session, kex); for (i = 0; i < KEX_METHODS_SIZE; i++) { str = ssh_string_from_char(kex->methods[i]); if (str == NULL) { goto error; } if (buffer_add_ssh_string(session->out_hashbuf, str) < 0) { goto error; } if (buffer_add_ssh_string(session->out_buffer, str) < 0) { goto error; } ssh_string_free(str); } if (buffer_add_u8(session->out_buffer, 0) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, 0) < 0) { goto error; } if (packet_send(session) == SSH_ERROR) { leave_function(); return -1; } leave_function(); return 0; error: buffer_reinit(session->out_buffer); buffer_reinit(session->out_hashbuf); ssh_string_free(str); leave_function(); return -1; }
/* this function only sends the predefined set of kex methods */ int ssh_send_kex(SSH_SESSION *session, int server_kex) { KEX *kex = (server_kex ? &session->server_kex : &session->client_kex); STRING *str = NULL; int i; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXINIT) < 0) { goto error; } if (buffer_add_data(session->out_buffer, kex->cookie, 16) < 0) { goto error; } if (hashbufout_add_cookie(session) < 0) { goto error; } ssh_list_kex(session, kex); for (i = 0; i < 10; i++) { str = string_from_char(kex->methods[i]); if (str == NULL) { goto error; } if (buffer_add_ssh_string(session->out_hashbuf, str) < 0) { goto error; } if (buffer_add_ssh_string(session->out_buffer, str) < 0) { goto error; } string_free(str); } if (buffer_add_u8(session->out_buffer, 0) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, 0) < 0) { goto error; } if (packet_send(session) != SSH_OK) { leave_function(); return -1; } leave_function(); return 0; error: buffer_free(session->out_buffer); buffer_free(session->out_hashbuf); string_free(str); leave_function(); return -1; }
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col, int row) { ssh_session session = channel->session; ssh_string str = NULL; str = string_from_char(terminal); if (str == NULL) { return -1; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0 || buffer_add_ssh_string(session->out_buffer, str) < 0) { string_free(str); return -1; } 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"); if (packet_send(session) != SSH_OK || packet_read(session) != SSH_OK || packet_translate(session) != SSH_OK) { return -1; } switch (session->in_packet.type) { case SSH_SMSG_SUCCESS: ssh_log(session, SSH_LOG_RARE, "PTY: Success"); return 0; break; case SSH_SMSG_FAILURE: ssh_set_error(session, SSH_REQUEST_DENIED, "Server denied PTY allocation"); ssh_log(session, SSH_LOG_RARE, "PTY: denied\n"); break; default: ssh_log(session, SSH_LOG_RARE, "PTY: error\n"); ssh_set_error(session, SSH_FATAL, "Received unexpected packet type %d", session->in_packet.type); return -1; } return -1; }
int ssh_userauth_pubkey(SSH_SESSION *session, const char *username, STRING *publickey, PRIVATE_KEY *privatekey){ STRING *user; STRING *service; STRING *method; STRING *algo; STRING *sign; int err=SSH_AUTH_ERROR; enter_function(); // if(session->version==1) // return ssh_userauth1_pubkey(session,username,publickey,privatekey); if(!username) if(!(username=session->options->username)){ if(ssh_options_default_username(session->options)){ leave_function(); return err; } else username=session->options->username; } if(ask_userauth(session)){ leave_function(); return err; } user=string_from_char(username); service=string_from_char("ssh-connection"); method=string_from_char("publickey"); algo=string_from_char(ssh_type_to_char(privatekey->type)); /* we said previously the public key was accepted */ buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST); buffer_add_ssh_string(session->out_buffer,user); buffer_add_ssh_string(session->out_buffer,service); buffer_add_ssh_string(session->out_buffer,method); buffer_add_u8(session->out_buffer,1); buffer_add_ssh_string(session->out_buffer,algo); buffer_add_ssh_string(session->out_buffer,publickey); sign=ssh_do_sign(session,session->out_buffer,privatekey); if(sign){ buffer_add_ssh_string(session->out_buffer,sign); free(sign); packet_send(session); err=wait_auth_status(session,0); } free(user); free(service); free(method); free(algo); leave_function(); return err; }
int ssh_userauth_password(SSH_SESSION *session, const char *username, const char *password){ STRING *user; STRING *service; STRING *method; STRING *password_s; int err; enter_function(); #ifdef HAVE_SSH1 if(session->version==1){ err = ssh_userauth1_password(session,username,password); leave_function(); return err; } #endif if(!username) if(!(username=session->options->username)){ if(ssh_options_default_username(session->options)){ err = SSH_AUTH_ERROR; leave_function(); return err; } else username=session->options->username; } if(ask_userauth(session)){ leave_function(); return SSH_AUTH_ERROR; } user=string_from_char(username); service=string_from_char("ssh-connection"); method=string_from_char("password"); password_s=string_from_char(password); buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST); buffer_add_ssh_string(session->out_buffer,user); buffer_add_ssh_string(session->out_buffer,service); buffer_add_ssh_string(session->out_buffer,method); buffer_add_u8(session->out_buffer,0); buffer_add_ssh_string(session->out_buffer,password_s); free(user); free(service); free(method); memset(password_s,0,strlen(password)+4); free(password_s); packet_send(session); err=wait_auth_status(session,0); leave_function(); return err; }
int channel_write1(ssh_channel channel, const void *data, int len) { ssh_session session = channel->session; int origlen = len; int effectivelen; const unsigned char *ptr=data; while (len > 0) { if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) { return -1; } effectivelen = len > 32000 ? 32000 : len; if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 || buffer_add_data(session->out_buffer, ptr, effectivelen) < 0) { return -1; } ptr += effectivelen; len -= effectivelen; if (packet_send(session) != SSH_OK) { return -1; } } return origlen; }
/** @internal * @brief Starts ecdh-sha2-nistp256 key exchange */ int ssh_client_ecdh_init(ssh_session session){ EC_KEY *key=NULL; const EC_GROUP *group; const EC_POINT *pubkey; ssh_string client_pubkey; int len; int rc; bignum_CTX ctx=BN_CTX_new(); enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT) < 0) { goto error; } key = EC_KEY_new_by_curve_name(NISTP256); group = EC_KEY_get0_group(key); EC_KEY_generate_key(key); pubkey=EC_KEY_get0_public_key(key); len = EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED, NULL,0,ctx); client_pubkey=ssh_string_new(len); EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(client_pubkey),len,ctx); buffer_add_ssh_string(session->out_buffer,client_pubkey); BN_CTX_free(ctx); session->next_crypto->ecdh_privkey = key; session->next_crypto->ecdh_client_pubkey = client_pubkey; rc = packet_send(session); leave_function(); return rc; error: leave_function(); return SSH_ERROR; }
int ssh_message_auth_reply_success(ssh_message msg, int partial) { int r; if (msg == NULL) { return SSH_ERROR; } if (partial) { return ssh_message_auth_reply_default(msg, partial); } if (buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS) < 0) { return SSH_ERROR; } r = packet_send(msg->session); if(msg->session->current_crypto && msg->session->current_crypto->delayed_compress_out){ ssh_log(msg->session,SSH_LOG_PROTOCOL,"Enabling delayed compression OUT"); msg->session->current_crypto->do_compress_out=1; } if(msg->session->current_crypto && msg->session->current_crypto->delayed_compress_in){ ssh_log(msg->session,SSH_LOG_PROTOCOL,"Enabling delayed compression IN"); msg->session->current_crypto->do_compress_in=1; } return r; }
/** @internal * @brief Starts [email protected] key exchange */ int ssh_client_curve25519_init(ssh_session_t * session){ ssh_string_t * client_pubkey; int rc; rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); if (rc < 0) { return SSH_ERROR; } rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1); if (rc == 0){ ssh_set_error(session, SSH_FATAL, "PRNG error"); return SSH_ERROR; } crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey, session->next_crypto->curve25519_privkey); client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE); if (client_pubkey == NULL) { return SSH_ERROR; } ssh_string_fill(client_pubkey, session->next_crypto->curve25519_client_pubkey, CURVE25519_PUBKEY_SIZE); rc = buffer_add_ssh_string(session->out_buffer,client_pubkey); ssh_string_free(client_pubkey); if (rc < 0) { return SSH_ERROR; } rc = packet_send(session); return rc; }
/* this function sends the first packet as explained in section 3.1 * of the draft */ static int kbdauth_init(SSH_SESSION *session, const char *user, const char *submethods){ STRING *user_s=string_from_char(user); STRING *submethods_s=(submethods ? string_from_char(submethods): string_from_char("")); STRING *service=string_from_char("ssh-connection"); STRING *method=string_from_char("keyboard-interactive"); int err; enter_function(); buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST); buffer_add_ssh_string(session->out_buffer,user_s); buffer_add_ssh_string(session->out_buffer,service); buffer_add_ssh_string(session->out_buffer,method); buffer_add_u32(session->out_buffer,0); // language tag buffer_add_ssh_string(session->out_buffer,submethods_s); free(user_s); free(service); free(method); free(submethods_s); if(packet_send(session)){ leave_function(); return SSH_AUTH_ERROR; } err=wait_auth_status(session,1); leave_function(); return err; }
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 ssh_message_channel_request_open_reply_default(ssh_message msg) { SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a channel"); if (buffer_add_u8(msg->session->out_buffer , SSH2_MSG_CHANNEL_OPEN_FAILURE) < 0) { goto error; } if (buffer_add_u32(msg->session->out_buffer, htonl(msg->channel_request_open.sender)) < 0) { goto error; } if (buffer_add_u32(msg->session->out_buffer, htonl(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) < 0) { goto error; } /* reason is an empty string */ if (buffer_add_u32(msg->session->out_buffer, 0) < 0) { goto error; } /* language too */ if (buffer_add_u32(msg->session->out_buffer, 0) < 0) { goto error; } return packet_send(msg->session); error: return SSH_ERROR; }
int ssh_auth_reply_success(ssh_session session, int partial) { int r; if (session == NULL) { return SSH_ERROR; } if (partial) { return ssh_auth_reply_default(session, partial); } session->session_state = SSH_SESSION_STATE_AUTHENTICATED; session->flags |= SSH_SESSION_FLAG_AUTHENTICATED; if (buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS) < 0) { return SSH_ERROR; } r = packet_send(session); if(session->current_crypto && session->current_crypto->delayed_compress_out){ SSH_LOG(SSH_LOG_PROTOCOL,"Enabling delayed compression OUT"); session->current_crypto->do_compress_out=1; } if(session->current_crypto && session->current_crypto->delayed_compress_in){ SSH_LOG(SSH_LOG_PROTOCOL,"Enabling delayed compression IN"); session->current_crypto->do_compress_in=1; } return r; }
/** * @brief Send an end of file on the channel. * * This doesn't close the channel. You may still read from it but not write. * * @param channel The channel to send the eof to. * * @return SSH_SUCCESS on success\n * SSH_ERROR on error\n * * @see channel_close() * @see channel_free() */ int channel_send_eof(CHANNEL *channel){ SSH_SESSION *session = channel->session; int rc = SSH_ERROR; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_EOF) < 0) { goto error; } if (buffer_add_u32(session->out_buffer,htonl(channel->remote_channel)) < 0) { goto error; } rc = packet_send(session); ssh_log(session, SSH_LOG_PACKET, "Sent a EOF on client channel (%d:%d)", channel->local_channel, channel->remote_channel); channel->local_eof = 1; leave_function(); return rc; error: buffer_free(session->out_buffer); leave_function(); return rc; }
int channel_request_exec1(ssh_channel channel, const char *cmd) { ssh_session session; ssh_string command = NULL; if (channel == NULL) { return -1; } session = channel->session; command = ssh_string_from_char(cmd); if (command == NULL) { return -1; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXEC_CMD) < 0 || buffer_add_ssh_string(session->out_buffer, command) < 0) { ssh_string_free(command); return -1; } ssh_string_free(command); if(packet_send(session) == SSH_ERROR) { return -1; } ssh_log(session, SSH_LOG_RARE, "Executing %s ...", cmd); return 0; }
static int grow_window(SSH_SESSION *session, CHANNEL *channel, int minimumsize) { u32 new_window = minimumsize > WINDOWBASE ? minimumsize : WINDOWBASE; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_WINDOW_ADJUST) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0 || buffer_add_u32(session->out_buffer, htonl(new_window)) < 0) { goto error; } if (packet_send(session) != SSH_OK) { /* FIXME should we fail here or not? */ leave_function(); return 1; } ssh_log(session, SSH_LOG_PROTOCOL, "growing window (channel %d:%d) to %d bytes", channel->local_channel, channel->remote_channel, channel->local_window + new_window); channel->local_window += new_window; leave_function(); return 0; error: buffer_free(session->out_buffer); leave_function(); return -1; }
int hashbufout_add_cookie(ssh_session session) { session->out_hashbuf = ssh_buffer_new(); if (session->out_hashbuf == NULL) { return -1; } if (buffer_add_u8(session->out_hashbuf, 20) < 0) { ssh_buffer_reinit(session->out_hashbuf); return -1; } if (session->server) { if (ssh_buffer_add_data(session->out_hashbuf, session->next_crypto->server_kex.cookie, 16) < 0) { ssh_buffer_reinit(session->out_hashbuf); return -1; } } else { if (ssh_buffer_add_data(session->out_hashbuf, session->next_crypto->client_kex.cookie, 16) < 0) { ssh_buffer_reinit(session->out_hashbuf); return -1; } } return 0; }
int channel_write1(ssh_channel channel, const void *data, int len) { ssh_session session; int origlen = len; int effectivelen; const unsigned char *ptr=data; if (channel == NULL) { return -1; } session = channel->session; while (len > 0) { if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) { return -1; } effectivelen = len > 32000 ? 32000 : len; if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 || buffer_add_data(session->out_buffer, ptr, effectivelen) < 0) { return -1; } ptr += effectivelen; len -= effectivelen; if (packet_send(session) == SSH_ERROR) { return -1; } ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING); } if (ssh_blocking_flush(session,SSH_TIMEOUT_USER) == SSH_ERROR) return -1; return origlen; }
int ssh_message_channel_request_reply_success(ssh_message msg) { uint32_t channel; if (msg == NULL) { return SSH_ERROR; } if (msg->channel_request.want_reply) { channel = msg->channel_request.channel->remote_channel; ssh_log(msg->session, SSH_LOG_PACKET, "Sending a channel_request success to channel %d", channel); if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_CHANNEL_SUCCESS) < 0) { return SSH_ERROR; } if (buffer_add_u32(msg->session->out_buffer, htonl(channel)) < 0) { return SSH_ERROR; } return packet_send(msg->session); } ssh_log(msg->session, SSH_LOG_PACKET, "The client doesn't want to know the request succeeded"); return SSH_OK; }
int ssh_message_service_reply_success(ssh_message msg) { struct ssh_string_struct *service; ssh_session session; 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); if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) { return -1; } service=ssh_string_from_char(msg->service_request.service); if (service == NULL) { return -1; } if (buffer_add_ssh_string(session->out_buffer, service) < 0) { ssh_string_free(service); return -1; } ssh_string_free(service); return packet_send(msg->session); }
int ssh_userauth_offer_pubkey(SSH_SESSION *session, const char *username,int type, STRING *publickey){ STRING *user; STRING *service; STRING *method; STRING *algo; int err=SSH_AUTH_ERROR; enter_function(); #ifdef HAVE_SSH1 if(session->version==1){ err= ssh_userauth1_offer_pubkey(session,username,type,publickey); leave_function(); return err; } #endif if(!username) if(!(username=session->options->username)){ if(ssh_options_default_username(session->options)){ leave_function(); return SSH_AUTH_ERROR; } else username=session->options->username; } if(ask_userauth(session)){ leave_function(); return SSH_AUTH_ERROR; } user=string_from_char(username); service=string_from_char("ssh-connection"); method=string_from_char("publickey"); algo=string_from_char(ssh_type_to_char(type)); buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST); buffer_add_ssh_string(session->out_buffer,user); buffer_add_ssh_string(session->out_buffer,service); buffer_add_ssh_string(session->out_buffer,method); buffer_add_u8(session->out_buffer,0); buffer_add_ssh_string(session->out_buffer,algo); buffer_add_ssh_string(session->out_buffer,publickey); packet_send(session); err=wait_auth_status(session,0); free(user); free(method); free(service); free(algo); leave_function(); return err; }
/* this function sends the first packet as explained in section 3.1 * of the draft */ static int kbdauth_init(ssh_session session, const char *user, const char *submethods) { ssh_string usr = NULL; ssh_string sub = NULL; ssh_string service = NULL; ssh_string method = NULL; int rc = SSH_AUTH_ERROR; enter_function(); usr = string_from_char(user); if (usr == NULL) { goto error; } sub = (submethods ? string_from_char(submethods) : string_from_char("")); if (sub == NULL) { goto error; } service = string_from_char("ssh-connection"); if (service == NULL) { goto error; } method = string_from_char("keyboard-interactive"); if (method == NULL) { goto error; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST) < 0 || buffer_add_ssh_string(session->out_buffer, usr) < 0 || buffer_add_ssh_string(session->out_buffer, service) < 0 || buffer_add_ssh_string(session->out_buffer, method) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 || buffer_add_ssh_string(session->out_buffer, sub) < 0) { goto error; } string_free(usr); string_free(service); string_free(method); string_free(sub); if (packet_send(session) != SSH_OK) { leave_function(); return rc; } rc = wait_auth_status(session,1); leave_function(); return rc; error: buffer_reinit(session->out_buffer); string_free(usr); string_free(service); string_free(method); string_free(sub); leave_function(); return rc; }
/* TODO: make this function accept a ssh_channel */ ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) { ssh_session session; ssh_channel chan = NULL; enter_function(); if (msg == NULL) { leave_function(); return NULL; } session = msg->session; chan = ssh_channel_new(session); if (chan == NULL) { leave_function(); return NULL; } chan->local_channel = ssh_channel_new_id(session); chan->local_maxpacket = 35000; chan->local_window = 32000; chan->remote_channel = msg->channel_request_open.sender; chan->remote_maxpacket = msg->channel_request_open.packet_size; chan->remote_window = msg->channel_request_open.window; chan->state = SSH_CHANNEL_STATE_OPEN; if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, htonl(chan->remote_channel)) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, htonl(chan->local_channel)) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, htonl(chan->local_window)) < 0) { goto error; } if (buffer_add_u32(session->out_buffer, htonl(chan->local_maxpacket)) < 0) { goto error; } ssh_log(session, SSH_LOG_PACKET, "Accepting a channel request_open for chan %d", chan->remote_channel); if (packet_send(session) == SSH_ERROR) { goto error; } leave_function(); return chan; error: ssh_channel_free(chan); leave_function(); return NULL; }
static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid){ ssh_string str; int rc; int i; rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST); if (rc < 0) { goto fail; } /* username */ str = ssh_string_from_char(session->opts.username); if (str == NULL) { goto fail; } rc = buffer_add_ssh_string(session->out_buffer, str); ssh_string_free(str); if (rc < 0) { goto fail; } /* service */ str = ssh_string_from_char("ssh-connection"); if (str == NULL) { goto fail; } rc = buffer_add_ssh_string(session->out_buffer, str); ssh_string_free(str); if (rc < 0) { goto fail; } /* method */ str = ssh_string_from_char("gssapi-with-mic"); if (str == NULL) { goto fail; } rc = buffer_add_ssh_string(session->out_buffer, str); ssh_string_free(str); if (rc < 0) { goto fail; } rc = buffer_add_u32(session->out_buffer, htonl(n_oid)); if (rc < 0) { 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: buffer_reinit(session->out_buffer); return SSH_ERROR; }
/** @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 r; enter_function(); buffer_add_u8(session->out_buffer, SSH2_MSG_UNIMPLEMENTED); buffer_add_u32(session->out_buffer, htonl(seqnum)); r = packet_send(session); leave_function(); return r; }
/* this function only sends the predefined set of kex methods */ void ssh_send_kex(SSH_SESSION *session, int server_kex){ STRING *str; int i=0; KEX *kex=(server_kex ? &session->server_kex : &session->client_kex); packet_clear_out(session); buffer_add_u8(session->out_buffer,SSH2_MSG_KEXINIT); buffer_add_data(session->out_buffer,kex->cookie,16); hashbufout_add_cookie(session); ssh_list_kex(kex); for(i=0;i<10;i++){ str=string_from_char(kex->methods[i]); buffer_add_ssh_string(session->out_hashbuf,str); buffer_add_ssh_string(session->out_buffer,str); free(str); } i=0; buffer_add_u8(session->out_buffer,0); buffer_add_u32(session->out_buffer,0); packet_send(session); }
/** * @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) { ssh_string service_s = NULL; int rc=SSH_ERROR; if(session->auth_service_state != SSH_AUTH_SERVICE_NONE) goto pending; if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) { return SSH_ERROR; } service_s = ssh_string_from_char(service); if (service_s == NULL) { return SSH_ERROR; } if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) { ssh_string_free(service_s); return SSH_ERROR; } ssh_string_free(service_s); session->auth_service_state=SSH_AUTH_SERVICE_SENT; if (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; }