/** @internal * @brief dispatch the call of packet handlers callbacks for a received packet * @param type type of packet */ void ssh_packet_process(ssh_session session, uint8_t type){ struct ssh_iterator *i; int r=SSH_PACKET_NOT_USED; ssh_packet_callbacks cb; enter_function(); ssh_log(session,SSH_LOG_PACKET, "Dispatching handler for packet type %d",type); if(session->packet_callbacks == NULL){ ssh_log(session,SSH_LOG_RARE,"Packet callback is not initialized !"); goto error; } i=ssh_list_get_iterator(session->packet_callbacks); while(i != NULL){ cb=ssh_iterator_value(ssh_packet_callbacks,i); i=i->next; if(!cb) continue; if(cb->start > type) continue; if(cb->start + cb->n_callbacks <= type) continue; if(cb->callbacks[type - cb->start]==NULL) continue; r=cb->callbacks[type - cb->start](session,type,session->in_buffer,cb->user); if(r==SSH_PACKET_USED) break; } if(r==SSH_PACKET_NOT_USED){ ssh_log(session,SSH_LOG_RARE,"Couldn't do anything with packet type %d",type); ssh_packet_send_unimplemented(session, session->recv_seq-1); } error: leave_function(); }
int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port) { ssh_log(msg->session, 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) { if (buffer_add_u32(msg->session->out_buffer, htonl(bound_port)) < 0) { 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(msg->session, SSH_LOG_PACKET, "The client doesn't want to know the remote port!"); } return SSH_OK; error: return SSH_ERROR; }
static void channel_rcv_change_window(SSH_SESSION *session) { CHANNEL *channel; u32 bytes; int rc; enter_function(); channel = channel_from_msg(session); if (channel == NULL) { ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session)); } rc = buffer_get_u32(session->in_buffer, &bytes); if (channel == NULL || rc != sizeof(u32)) { ssh_log(session, SSH_LOG_PACKET, "Error getting a window adjust message: invalid packet"); leave_function(); return; } bytes = ntohl(bytes); ssh_log(session, SSH_LOG_PROTOCOL, "Adding %d bytes to channel (%d:%d) (from %d bytes)", bytes, channel->local_channel, channel->remote_channel, channel->remote_window); channel->remote_window += bytes; leave_function(); }
/* * channel_handle() is called by packet_wait(), for example when there is * channel informations to handle. */ void channel_handle(SSH_SESSION *session, int type){ enter_function(); ssh_log(session, SSH_LOG_PROTOCOL, "Channel_handle(%d)", type); switch(type) { case SSH2_MSG_CHANNEL_WINDOW_ADJUST: channel_rcv_change_window(session); break; case SSH2_MSG_CHANNEL_DATA: channel_rcv_data(session,0); break; case SSH2_MSG_CHANNEL_EXTENDED_DATA: channel_rcv_data(session,1); break; case SSH2_MSG_CHANNEL_EOF: channel_rcv_eof(session); break; case SSH2_MSG_CHANNEL_CLOSE: channel_rcv_close(session); break; case SSH2_MSG_CHANNEL_REQUEST: channel_rcv_request(session); break; default: ssh_log(session, SSH_LOG_FUNCTIONS, "Unexpected message %d", type); } leave_function(); }
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_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; }
static int crypt_set_algorithms2(SSH_SESSION *session){ const char *wanted; int i = 0; /* we must scan the kex entries to find crypto algorithms and set their appropriate structure */ /* out */ wanted = session->client_kex.methods[SSH_CRYPT_C_S]; while (ssh_ciphertab[i].name && strcmp(wanted, ssh_ciphertab[i].name)) { i++; } if (ssh_ciphertab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "Crypt_set_algorithms2: no crypto algorithm function found for %s", wanted); return SSH_ERROR; } ssh_log(session, SSH_LOG_PACKET, "Set output algorithm to %s", wanted); session->next_crypto->out_cipher = cipher_new(i); if (session->next_crypto->out_cipher == NULL) { ssh_set_error(session, SSH_FATAL, "No space left"); return SSH_ERROR; } i = 0; /* in */ wanted = session->client_kex.methods[SSH_CRYPT_S_C]; while (ssh_ciphertab[i].name && strcmp(wanted, ssh_ciphertab[i].name)) { i++; } if (ssh_ciphertab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "Crypt_set_algorithms: no crypto algorithm function found for %s", wanted); return SSH_ERROR; } ssh_log(session, SSH_LOG_PACKET, "Set input algorithm to %s", wanted); session->next_crypto->in_cipher = cipher_new(i); if (session->next_crypto->in_cipher == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return SSH_ERROR; } /* compression */ if (strstr(session->client_kex.methods[SSH_COMP_C_S], "zlib")) { session->next_crypto->do_compress_out = 1; } if (strstr(session->client_kex.methods[SSH_COMP_S_C], "zlib")) { session->next_crypto->do_compress_in = 1; } return SSH_OK; }
static int packet_wait1(SSH_SESSION *session, int type, int blocking) { enter_function(); ssh_log(session, SSH_LOG_PROTOCOL, "packet_wait1 waiting for %d", type); do { if ((packet_read1(session) != SSH_OK) || (packet_translate(session) != SSH_OK)) { leave_function(); return SSH_ERROR; } ssh_log(session, SSH_LOG_PACKET, "packet_wait1() received a type %d packet", session->in_packet.type); switch (session->in_packet.type) { case SSH_MSG_DISCONNECT: packet_parse(session); leave_function(); return SSH_ERROR; case SSH_SMSG_STDOUT_DATA: case SSH_SMSG_STDERR_DATA: case SSH_SMSG_EXITSTATUS: if (channel_handle1(session,type) < 0) { leave_function(); return SSH_ERROR; } break; case SSH_MSG_DEBUG: case SSH_MSG_IGNORE: break; /* case SSH2_MSG_CHANNEL_CLOSE: packet_parse(session); break;; */ default: if (type && (type != session->in_packet.type)) { ssh_set_error(session, SSH_FATAL, "packet_wait1(): Received a %d type packet, but expected %d\n", session->in_packet.type, type); leave_function(); return SSH_ERROR; } leave_function(); return SSH_OK; } if (blocking == 0) { leave_function(); return SSH_OK; } } while(1); leave_function(); return SSH_OK; }
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; }
void ssh_list_kex(ssh_session session, KEX *kex) { int i = 0; #ifdef DEBUG_CRYPTO ssh_print_hexa("session cookie", kex->cookie, 16); #endif if(kex->methods==NULL){ ssh_log(session, SSH_LOG_RARE,"kex->methods is NULL"); return; } for(i = 0; i < 10; i++) { ssh_log(session, SSH_LOG_FUNCTIONS, "%s: %s", ssh_kex_nums[i], kex->methods[i]); } }
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) { ssh_session session; 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; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_WINDOW_SIZE) < 0 || buffer_add_u32(session->out_buffer, ntohl(rows)) < 0 || buffer_add_u32(session->out_buffer, ntohl(cols)) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 || buffer_add_u32(session->out_buffer, 0) < 0) { return SSH_ERROR; } channel->request_state=SSH_CHANNEL_REQ_STATE_PENDING; if (packet_send(session) == SSH_ERROR) { return SSH_ERROR; } ssh_log(session, SSH_LOG_PROTOCOL, "Change pty size send"); 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_PROTOCOL, "pty size changed"); return SSH_OK; case SSH_CHANNEL_REQ_STATE_DENIED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_log(session, SSH_LOG_RARE, "pty size change denied"); ssh_set_error(session, SSH_REQUEST_DENIED, "pty size change denied"); return SSH_ERROR; } // Not reached return SSH_ERROR; }
int packet_decrypt(SSH_SESSION *session, void *data,u32 len) { struct crypto_struct *crypto = session->current_crypto->in_cipher; char *out = NULL; out = malloc(len); if (out == NULL) { return -1; } ssh_log(session,SSH_LOG_PACKET, "Decrypting %d bytes", len); #ifdef HAVE_LIBGCRYPT if (crypto->set_decrypt_key(crypto, session->current_crypto->decryptkey, session->current_crypto->decryptIV) < 0) { SAFE_FREE(out); return -1; } crypto->cbc_decrypt(crypto,data,out,len); #elif defined HAVE_LIBCRYPTO if (crypto->set_decrypt_key(crypto, session->current_crypto->decryptkey) < 0) { SAFE_FREE(out); return -1; } crypto->cbc_decrypt(crypto,data,out,len,session->current_crypto->decryptIV); #endif memcpy(data,out,len); memset(out,0,len); SAFE_FREE(out); 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; }
static STRING *encrypt_session_key(SSH_SESSION *session, PUBLIC_KEY *srvkey, PUBLIC_KEY *hostkey, int slen, int hlen) { unsigned char buffer[32] = {0}; int i; STRING *data1 = NULL; STRING *data2 = NULL; /* first, generate a session key */ ssh_get_random(session->next_crypto->encryptkey, 32, 1); memcpy(buffer, session->next_crypto->encryptkey, 32); memcpy(session->next_crypto->decryptkey, session->next_crypto->encryptkey, 32); #ifdef DEBUG_CRYPTO ssh_print_hexa("session key",buffer,32); #endif /* xor session key with session_id */ for (i = 0; i < 16; i++) { buffer[i] ^= session->next_crypto->session_id[i]; } data1 = string_new(32); if (data1 == NULL) { return NULL; } string_fill(data1, buffer, 32); if (ABS(hlen - slen) < 128){ ssh_log(session, SSH_LOG_FUNCTIONS, "Difference between server modulus and host modulus is only %d. " "It's illegal and may not work", ABS(hlen - slen)); } if (modulus_smaller(srvkey, hostkey)) { data2 = ssh_encrypt_rsa1(session, data1, srvkey); string_free(data1); data1 = NULL; if (data2 == NULL) { return NULL; } data1 = ssh_encrypt_rsa1(session, data2, hostkey); string_free(data2); if (data1 == NULL) { return NULL; } } else { data2 = ssh_encrypt_rsa1(session, data1, hostkey); string_free(data1); data1 = NULL; if (data2 == NULL) { return NULL; } data1 = ssh_encrypt_rsa1(session, data2, srvkey); string_free(data2); if (data1 == NULL) { return NULL; } } return data1; }
/** @brief waits for a response of the scp server * @internal * @param response pointer where the response message must be * copied if any. This pointer must then be free'd. * @returns the return code. * @returns SSH_ERROR a error occured */ int ssh_scp_response(ssh_scp scp, char **response){ unsigned char code; int r; char msg[128]; r=channel_read(scp->channel,&code,1,0); if(r == SSH_ERROR) return SSH_ERROR; if(code == 0) return 0; if(code > 2){ ssh_set_error(scp->session,SSH_FATAL, "SCP: invalid status code %ud received", code); scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r=ssh_scp_read_string(scp,msg,sizeof(msg)); if(r==SSH_ERROR) return r; /* Warning */ if(code == 1){ ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Warning: status code 1 received: %s", msg); ssh_log(scp->session,SSH_LOG_RARE,"SCP: Warning: status code 1 received: %s", msg); if(response) *response=strdup(msg); return 1; } if(code == 2){ ssh_set_error(scp->session,SSH_FATAL, "SCP: Error: status code 2 received: %s", msg); if(response) *response=strdup(msg); return 2; } /* Not reached */ return SSH_ERROR; }
/** \internal * \brief writes len bytes from buffer to socket */ static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer, uint32_t len) { int w = -1; if (s->data_except) { return -1; } if (s->fd_is_socket) w = send(s->fd_out,buffer, len, 0); else w = write(s->fd_out, buffer, len); #ifdef _WIN32 s->last_errno = WSAGetLastError(); #else s->last_errno = errno; #endif s->write_wontblock = 0; /* Reactive the POLLOUT detector in the poll multiplexer system */ if(s->poll_out){ ssh_log(s->session, SSH_LOG_PACKET, "Enabling POLLOUT for socket"); ssh_poll_set_events(s->poll_out,ssh_poll_get_events(s->poll_out) | POLLOUT); } if (w < 0) { s->data_except = 1; } return w; }
/** * @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; }
void signature_free(SIGNATURE *sign) { if (sign == NULL) { return; } switch(sign->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sign->dsa_sign); #elif defined HAVE_LIBCRYPTO DSA_SIG_free(sign->dsa_sign); #endif break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sign->rsa_sign); #elif defined HAVE_LIBCRYPTO SAFE_FREE(sign->rsa_sign); #endif break; default: /* FIXME Passing NULL segfaults */ #if 0 ssh_log(NULL, SSH_LOG_RARE, "Freeing a signature with no type!\n"); */ #endif break; } SAFE_FREE(sign); }
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 pem_get_password(char *buf, int size, int rwflag, void *userdata) { ssh_session session = userdata; (void) rwflag; /* unused */ if (buf == NULL) { return 0; } ssh_log(session, SSH_LOG_RARE, "Trying to call external authentication function"); memset(buf, '\0', size); if (session && session->common.callbacks && session->common.callbacks->auth_function) { int rc; rc = session->common.callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0, session->common.callbacks->userdata); if (rc == 0) { return strlen(buf); } } return 0; }
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; }
/** @brief initializes the sending of a file to a scp in sink mode * @param scp the scp handle. * @param filename Name of the file being sent. It should not contain any path indicator * @param size Exact size in bytes of the file being sent. * @param mode Unix permissions for the new file, e.g. 0644 * @returns SSH_OK if the file is ready to be sent. * @returns SSH_ERROR if an error happened. */ int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode){ char buffer[1024]; int r; uint8_t code; char *file; char *perms; if(scp->state != SSH_SCP_WRITE_INITED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_file called under invalid state"); return SSH_ERROR; } file=ssh_basename(filename); perms=ssh_scp_string_mode(mode); ssh_log(scp->session,SSH_LOG_PROTOCOL,"SCP pushing file %s, size %" PRIdS " with permissions '%s'",file,size,perms); snprintf(buffer, sizeof(buffer), "C%s %" PRIdS " %s\n", perms, size, file); SAFE_FREE(file); SAFE_FREE(perms); r=channel_write(scp->channel,buffer,strlen(buffer)); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r=channel_read(scp->channel,&code,1,0); if(code != 0){ ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code); scp->state=SSH_SCP_ERROR; return SSH_ERROR; } scp->filelen = size; scp->processed = 0; scp->state=SSH_SCP_WRITE_WRITING; return SSH_OK; }
int ssh_message_reply_default(ssh_message msg) { if (msg == NULL) { return -1; } switch(msg->type) { case SSH_REQUEST_AUTH: return ssh_message_auth_reply_default(msg, 0); case SSH_REQUEST_CHANNEL_OPEN: return ssh_message_channel_request_open_reply_default(msg); case SSH_REQUEST_CHANNEL: return ssh_message_channel_request_reply_default(msg); case SSH_REQUEST_SERVICE: return ssh_message_service_request_reply_default(msg); case SSH_REQUEST_GLOBAL: return ssh_message_global_request_reply_default(msg); default: ssh_log(msg->session, SSH_LOG_PACKET, "Don't know what to default reply to %d type", msg->type); break; } return -1; }
/** @brief import a base64 formated key from a memory c-string * * @param key The key to fill, created with ssh_key_new() * @param session The ssh session * @param b64_key The c-string holding the base64 encoded key * @param passphrase The passphrase to decrypt the key, or NULL * * @return SSH_ERROR in case of error, SSH_OK otherwise */ int ssh_pki_import_privkey_base64(ssh_session session, const char *b64_key, const char *passphrase, ssh_key *pkey) { ssh_key key; if (pkey == NULL || session == NULL) { return SSH_ERROR; } if (b64_key == NULL || !*b64_key) { return SSH_ERROR; } ssh_log(session, SSH_LOG_RARE, "Trying to decode privkey passphrase=%s", passphrase ? "true" : "false"); key = pki_private_key_from_base64(session, b64_key, passphrase); if (key == NULL) { return SSH_ERROR; } *pkey = key; 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(session, 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); }
static int ssh_message_channel_request_open_reply_default(ssh_message msg) { ssh_log(msg->session, 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 channel_open_session1(ssh_channel chan) { ssh_session session; if (chan == NULL) { return -1; } session = chan->session; /* * We guess we are requesting an *exec* channel. It can only have one exec * channel. So we abort with an error if we need more than one. */ if (session->exec_channel_opened) { ssh_set_error(session, SSH_REQUEST_DENIED, "SSH1 supports only one execution channel. " "One has already been opened"); return -1; } session->exec_channel_opened = 1; chan->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED; chan->state = SSH_CHANNEL_STATE_OPEN; chan->local_maxpacket = 32000; chan->local_window = 64000; ssh_log(session, SSH_LOG_PACKET, "Opened a SSH1 channel session"); return 0; }
int packet_decrypt(ssh_session session, void *data,uint32_t len) { struct crypto_struct *crypto = session->current_crypto->in_cipher; char *out = NULL; if(len % session->current_crypto->in_cipher->blocksize != 0){ ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len); return SSH_ERROR; } out = malloc(len); if (out == NULL) { return -1; } ssh_log(session,SSH_LOG_PACKET, "Decrypting %d bytes", len); #ifdef HAVE_LIBGCRYPT if (crypto->set_decrypt_key(crypto, session->current_crypto->decryptkey, session->current_crypto->decryptIV) < 0) { SAFE_FREE(out); return -1; } crypto->cbc_decrypt(crypto,data,out,len); #elif defined HAVE_LIBCRYPTO if (crypto->set_decrypt_key(crypto, session->current_crypto->decryptkey) < 0) { SAFE_FREE(out); return -1; } crypto->cbc_decrypt(crypto,data,out,len,session->current_crypto->decryptIV); #endif memcpy(data,out,len); memset(out,0,len); SAFE_FREE(out); return 0; }
SSH_SESSION *connect_host(const char *hostname){ SSH_SESSION *session; SSH_OPTIONS *options; int auth=0; int state; options=ssh_options_new(); ssh_options_set_host(options,hostname); session=ssh_new(); ssh_set_options(session,options); if(ssh_connect(session)){ fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session)); ssh_disconnect(session); return NULL; } state = ssh_session_is_known_server(session); switch(state){ case SSH_SERVER_KNOWN_OK: break; /* ok */ case SSH_SERVER_KNOWN_CHANGED: fprintf(stderr,"Host key for server changed : server's one is now :\n"); fprintf(stderr,"For security reason, connection will be stopped\n"); ssh_disconnect(session); ssh_finalize(); return NULL; case SSH_SERVER_FOUND_OTHER: fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n"); fprintf(stderr,"An attacker might change the default server key to confuse your client" "into thinking the key does not exist\n" "We advise you to rerun the client with -d or -r for more safety.\n"); ssh_disconnect(session); ssh_finalize(); return NULL; case SSH_SERVER_NOT_KNOWN: fprintf(stderr,"The server is unknown. Leaving now"); ssh_disconnect(session); return NULL; case SSH_SERVER_ERROR: fprintf(stderr,"%s",ssh_get_error(session)); ssh_disconnect(session); return NULL; } ssh_userauth_none(session, NULL); auth=ssh_userauth_autopubkey(session, NULL); if(auth==SSH_AUTH_ERROR){ fprintf(stderr,"Authenticating with pubkey: %s\n",ssh_get_error(session)); ssh_disconnect(session); return NULL; } if(auth!=SSH_AUTH_SUCCESS){ fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session)); ssh_disconnect(session); return NULL; } ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success"); return session; }
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; }