/* * 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 = string_from_char(msg->auth_request.username); ssh_string servicename = string_from_char(service); ssh_string method = string_from_char("publickey"); uint8_t has_sign = 1; ssh_string algo = string_from_char(msg->auth_request.public_key->type_c); ssh_string publickey = publickey_to_string(msg->auth_request.public_key); buffer = buffer_new(); if (buffer == NULL) { goto error; } session_id = string_new(SHA_DIGEST_LEN); if (session_id == NULL) { buffer_free(buffer); buffer = NULL; goto error; } 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) { buffer_free(buffer); buffer = NULL; goto error; } error: if(session_id) string_free(session_id); if(username) string_free(username); if(servicename) string_free(servicename); if(method) string_free(method); if(algo) string_free(algo); if(publickey) string_free(publickey); return buffer; }
/* 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; }
/* 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; }
int sftp_reply_names_add(SFTP_CLIENT_MESSAGE *msg, char *file, char *longname, SFTP_ATTRIBUTES *attr) { STRING *name=string_from_char(file); if(!msg->attrbuf) msg->attrbuf=buffer_new(); buffer_add_ssh_string(msg->attrbuf,name); free(name); name=string_from_char(longname); buffer_add_ssh_string(msg->attrbuf,name); free(name); buffer_add_attributes(msg->attrbuf,attr); msg->attr_num++; return 0; }
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; }
/** * @brief Run a shell command without an interactive shell. * * This is similar to 'sh -c command'. * * @param channel The channel to execute the command. * * @param cmd The command to execute * (e.g. "ls ~/ -al | grep -i reports"). * * @return SSH_SUCCESS on success, SSH_ERROR on error. * * @see channel_request_shell() */ int channel_request_exec(CHANNEL *channel, const char *cmd) { BUFFER *buffer = NULL; STRING *command = NULL; int rc = SSH_ERROR; #ifdef HAVE_SSH1 if (channel->version == 1) { return channel_request_exec1(channel, cmd); } #endif buffer = buffer_new(); if (buffer == NULL) { goto error; } command = string_from_char(cmd); if (command == NULL) { goto error; } if (buffer_add_ssh_string(buffer, command) < 0) { goto error; } rc = channel_request(channel, "exec", buffer, 1); error: buffer_free(buffer); string_free(command); return rc; }
/* this is a public key in openssh's format */ static STRING *make_rsa1_string(STRING *e, STRING *n){ BUFFER *buffer = NULL; STRING *rsa = NULL; STRING *ret = NULL; buffer = buffer_new(); rsa = string_from_char("ssh-rsa1"); if (buffer_add_ssh_string(buffer, rsa) < 0) { goto error; } if (buffer_add_ssh_string(buffer, e) < 0) { goto error; } if (buffer_add_ssh_string(buffer, n) < 0) { goto error; } ret = string_new(buffer_get_len(buffer)); if (ret == NULL) { goto error; } string_fill(ret, buffer_get(buffer), buffer_get_len(buffer)); error: buffer_free(buffer); string_free(rsa); return ret; }
/** * @brief Request a subsystem (for example "sftp"). * * @param channel The channel to send the request. * * @param system The subsystem to request (for example "sftp"). * * @return SSH_SUCCESS on success, SSH_ERROR on error. * * @warning You normally don't have to call it for sftp, see sftp_new(). */ int channel_request_subsystem(CHANNEL *channel, const char *sys) { BUFFER *buffer = NULL; STRING *subsystem = NULL; int rc = SSH_ERROR; buffer = buffer_new(); if (buffer == NULL) { goto error; } subsystem = string_from_char(sys); if (subsystem == NULL) { goto error; } if (buffer_add_ssh_string(buffer, subsystem) < 0) { goto error; } rc = channel_request(channel, "subsystem", buffer, 1); error: buffer_free(buffer); string_free(subsystem); return rc; }
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; }
/* sends challenge back to the server */ static int kbdauth_send(ssh_session session) { ssh_string answer = NULL; int rc = SSH_AUTH_ERROR; uint32_t i; enter_function(); if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE) < 0 || buffer_add_u32(session->out_buffer, htonl(session->kbdint->nprompts)) < 0) { goto error; } for (i = 0; i < session->kbdint->nprompts; i++) { if (session->kbdint->answers[i]) { answer = string_from_char(session->kbdint->answers[i]); } else { answer = string_from_char(""); } if (answer == NULL) { goto error; } if (buffer_add_ssh_string(session->out_buffer, answer) < 0) { goto error; } string_burn(answer); string_free(answer); } 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_burn(answer); string_free(answer); leave_function(); return rc; }
/* 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; }
/** * @brief Open a TCP/IP forwarding channel. * * @param channel An allocated channel. * * @param remotehost The remote host to connected (host name or IP). * * @param remoteport The remote port. * * @param sourcehost The source host (your local computer). It's facultative * and for logging purpose. * * @param localport The source port (your local computer). It's facultative * and for logging purpose. * * @return SSH_OK on success\n * SSH_ERROR on error */ int channel_open_forward(CHANNEL *channel, const char *remotehost, int remoteport, const char *sourcehost, int localport) { SSH_SESSION *session = channel->session; BUFFER *payload = NULL; STRING *str = NULL; int rc = SSH_ERROR; enter_function(); payload = buffer_new(); if (payload == NULL) { goto error; } str = string_from_char(remotehost); if (str == NULL) { goto error; } if (buffer_add_ssh_string(payload, str) < 0 || buffer_add_u32(payload,htonl(remoteport)) < 0) { goto error; } string_free(str); str = string_from_char(sourcehost); if (str == NULL) { goto error; } if (buffer_add_ssh_string(payload, str) < 0 || buffer_add_u32(payload,htonl(localport)) < 0) { goto error; } rc = channel_open(channel, "direct-tcpip", 64000, 32000, payload); error: buffer_free(payload); string_free(str); leave_function(); return rc; }
int ssh_userauth_none(SSH_SESSION *session, const char *username){ STRING *user; STRING *service; STRING *method; int ret; enter_function(); #ifdef HAVE_SSH1 if(session->version==1){ ret = ssh_userauth1_none(session,username); leave_function(); return ret; } #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); method=string_from_char("none"); service=string_from_char("ssh-connection"); 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); free(service); free(method); free(user); packet_send(session); ret = wait_auth_status(session,0); leave_function(); return ret; }
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; }
/* this is a public key in openssh's format */ static STRING *make_rsa1_string(STRING *e, STRING *n){ BUFFER *buffer=buffer_new(); STRING *rsa=string_from_char("ssh-rsa1"); STRING *ret; buffer_add_ssh_string(buffer,rsa); free(rsa); buffer_add_ssh_string(buffer,e); buffer_add_ssh_string(buffer,n); ret=string_new(buffer_get_len(buffer)); string_fill(ret,buffer_get(buffer),buffer_get_len(buffer)); buffer_free(buffer); return ret; }
int sftp_reply_name(SFTP_CLIENT_MESSAGE *msg, char *name, SFTP_ATTRIBUTES *attr) { BUFFER *out=buffer_new(); STRING *file=string_from_char(name); int r; buffer_add_u32(out,msg->id); buffer_add_u32(out,htonl(1)); buffer_add_ssh_string(out,file); buffer_add_ssh_string(out,file); /* the protocol is broken here between 3 & 4 */ free(file); buffer_add_attributes(out,attr); r=sftp_packet_write(msg->sftp,SSH_FXP_NAME,out); buffer_free(out); return r<0; }
int sftp_reply_status(SFTP_CLIENT_MESSAGE *msg, u32 status, char *message) { BUFFER *out=buffer_new(); int r; STRING *s; buffer_add_u32(out,msg->id); buffer_add_u32(out,htonl(status)); s=string_from_char(message?message:""); buffer_add_ssh_string(out,s); free(s); buffer_add_u32(out,0); // language string r=sftp_packet_write(msg->sftp,SSH_FXP_STATUS,out); buffer_free(out); return r<0; }
/** * @brief Set environement variables. * * @param channel The channel to set the environement variables. * * @param name The name of the variable. * * @param value The value to set. * * @return SSH_SUCCESS on success, SSH_ERROR on error. * * @warning Some environement variables may be refused by security reasons. * */ int channel_request_env(CHANNEL *channel, const char *name, const char *value) { BUFFER *buffer = NULL; STRING *str = NULL; int rc = SSH_ERROR; buffer = buffer_new(); if (buffer == NULL) { goto error; } str = string_from_char(name); if (str == NULL) { goto error; } if (buffer_add_ssh_string(buffer, str) < 0) { goto error; } string_free(str); str = string_from_char(value); if (str == NULL) { goto error; } if (buffer_add_ssh_string(buffer, str) < 0) { goto error; } rc = channel_request(channel, "env", buffer,1); error: buffer_free(buffer); string_free(str); return rc; }
/* sends challenge back to the server */ static int kbdauth_send(SSH_SESSION *session) { STRING *answer; u32 i; int err; enter_function(); buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_INFO_RESPONSE); buffer_add_u32(session->out_buffer,htonl(session->kbdint->nprompts)); for(i=0;i<session->kbdint->nprompts;++i){ if(session->kbdint->answers[i]) answer=string_from_char(session->kbdint->answers[i]); else answer=string_from_char(""); buffer_add_ssh_string(session->out_buffer,answer); string_burn(answer); free(answer); } if(packet_send(session)){ leave_function(); return SSH_AUTH_ERROR; } err = wait_auth_status(session,1); leave_function(); return err; }
/** \brief disconnect from a session (client or server) * \param session ssh session */ void ssh_disconnect(SSH_SESSION *session){ STRING *str; if(session->fd!= -1) { packet_clear_out(session); buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT); buffer_add_u32(session->out_buffer,htonl(SSH2_DISCONNECT_BY_APPLICATION)); str=string_from_char("Bye Bye"); buffer_add_ssh_string(session->out_buffer,str); free(str); packet_send(session); close(session->fd); session->fd=-1; } session->alive=0; ssh_cleanup(session); }
int ssh_service_request(SSH_SESSION *session,char *service){ STRING *service_s; packet_clear_out(session); buffer_add_u8(session->out_buffer,SSH2_MSG_SERVICE_REQUEST); service_s=string_from_char(service); buffer_add_ssh_string(session->out_buffer,service_s); free(service_s); packet_send(session); ssh_say(3,"Sent SSH_MSG_SERVICE_REQUEST (service %s)\n",service); if(packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1)){ ssh_set_error(session,SSH_FATAL,"did not receive SERVICE_ACCEPT"); return -1; } ssh_say(3,"Received SSH_MSG_SERVICE_ACCEPT (service %s)\n",service); return 0; }
/** \brief makes a SSH String out of a PUBLIC_KEY object * \param key the public key * \returns a SSH String containing the public key * \see string_free() */ ssh_string publickey_to_string(ssh_public_key key) { ssh_string type = NULL; ssh_string ret = NULL; ssh_buffer buf = NULL; buf = buffer_new(); if (buf == NULL) { return NULL; } type = string_from_char(key->type_c); if (type == NULL) { goto error; } if (buffer_add_ssh_string(buf, type) < 0) { goto error; } switch (key->type) { case TYPE_DSS: if (dsa_public_to_string(key->dsa_pub, buf) < 0) { goto error; } break; case TYPE_RSA: case TYPE_RSA1: if (rsa_public_to_string(key->rsa_pub, buf) < 0) { goto error; } break; } ret = string_new(buffer_get_len(buf)); if (ret == NULL) { goto error; } string_fill(ret, buffer_get(buf), buffer_get_len(buf)); error: buffer_free(buf); string_free(type); return ret; }
/** * @brief Request a pty with a specific type and size. * * @param channel The channel to sent the request. * * @param terminal The terminal type ("vt100, xterm,..."). * * @param col The number of columns. * * @param row The number of rows. * * @return SSH_SUCCESS on success, SSH_ERROR on error. */ int channel_request_pty_size(CHANNEL *channel, const char *terminal, int col, int row) { SSH_SESSION *session = channel->session; STRING *term = NULL; BUFFER *buffer = NULL; int rc = SSH_ERROR; enter_function(); #ifdef HAVE_SSH1 if (channel->version==1) { channel_request_pty_size1(channel,terminal, col, row); leave_function(); return rc; } #endif buffer = buffer_new(); if (buffer == NULL) { goto error; } term = string_from_char(terminal); if (term == NULL) { goto error; } if (buffer_add_ssh_string(buffer, term) < 0 || buffer_add_u32(buffer, htonl(col)) < 0 || buffer_add_u32(buffer, htonl(row)) < 0 || buffer_add_u32(buffer, 0) < 0 || buffer_add_u32(buffer, 0) < 0 || buffer_add_u32(buffer, htonl(1)) < 0 || /* Add a 0byte string */ buffer_add_u8(buffer, 0) < 0) { goto error; } rc = channel_request(channel, "pty-req", buffer, 1); error: buffer_free(buffer); string_free(term); leave_function(); return rc; }
/* 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); }
/** \brief makes a SSH String out of a PUBLIC_KEY object * \param key the public key * \returns a SSH String containing the public key * \see string_free() */ STRING *publickey_to_string(PUBLIC_KEY *key){ STRING *type; STRING *ret; BUFFER *buf; type=string_from_char(ssh_type_to_char(key->type)); buf=buffer_new(); buffer_add_ssh_string(buf,type); switch(key->type){ case TYPE_DSS: dsa_public_to_string(key->dsa_pub,buf); break; case TYPE_RSA: case TYPE_RSA1: rsa_public_to_string(key->rsa_pub,buf); break; } ret=string_new(buffer_get_len(buf)); string_fill(ret,buffer_get(buf),buffer_get_len(buf)); buffer_free(buf); free(type); return ret; }
int channel_request_exec1(ssh_channel channel, const char *cmd) { ssh_session session = channel->session; ssh_string command = NULL; command = 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) { string_free(command); return -1; } string_free(command); if(packet_send(session) != SSH_OK) { return -1; } ssh_log(session, SSH_LOG_RARE, "Executing %s ...", cmd); return 0; }
STRING *signature_to_string(SIGNATURE *sign){ STRING *str; STRING *rs; #ifdef HAVE_LIBGCRYPT const char *r,*s; gcry_sexp_t sexp; size_t size; #elif defined HAVE_LIBCRYPTO STRING *r,*s; #endif unsigned char buffer[40]; BUFFER *tmpbuf=buffer_new(); STRING *tmp; tmp=string_from_char(ssh_type_to_char(sign->type)); buffer_add_ssh_string(tmpbuf,tmp); free(tmp); switch(sign->type){ case TYPE_DSS: memset(buffer,0,40); #ifdef HAVE_LIBGCRYPT sexp=gcry_sexp_find_token(sign->dsa_sign,"r",0); r=gcry_sexp_nth_data(sexp,1,&size); if (*r == 0) /* libgcrypt put 0 when first bit is set */ { size--; r++; } memcpy(buffer,r + size - 20,20); gcry_sexp_release(sexp); sexp=gcry_sexp_find_token(sign->dsa_sign,"s",0); s=gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } memcpy(buffer+ 20, s + size - 20, 20); gcry_sexp_release(sexp); #elif defined HAVE_LIBCRYPTO r=make_bignum_string(sign->dsa_sign->r); s=make_bignum_string(sign->dsa_sign->s); rs=string_new(40); memcpy(buffer,r->string+string_len(r)-20,20); memcpy(buffer+ 20, s->string + string_len(s) - 20, 20); free(r); free(s); #endif rs=string_new(40); string_fill(rs,buffer,40); buffer_add_ssh_string(tmpbuf,rs); free(rs); break; case TYPE_RSA: case TYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp=gcry_sexp_find_token(sign->rsa_sign,"s",0); s=gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } rs=string_new(size); string_fill(rs,(char *)s,size); buffer_add_ssh_string(tmpbuf,rs); gcry_sexp_release(sexp); free(rs); #elif defined HAVE_LIBCRYPTO buffer_add_ssh_string(tmpbuf,sign->rsa_sign); #endif break; } str=string_new(buffer_get_len(tmpbuf)); string_fill(str,buffer_get(tmpbuf),buffer_get_len(tmpbuf)); buffer_free(tmpbuf); return str; }
static int channel_open(CHANNEL *channel, const char *type_c, int window, int maxpacket, BUFFER *payload) { SSH_SESSION *session = channel->session; STRING *type = NULL; u32 tmp = 0; enter_function(); channel->local_channel = ssh_channel_new_id(session); channel->local_maxpacket = maxpacket; channel->local_window = window; ssh_log(session, SSH_LOG_RARE, "Creating a channel %d with %d window and %d max packet", channel->local_channel, window, maxpacket); type = string_from_char(type_c); if (type == NULL) { leave_function(); return -1; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_OPEN) < 0 || buffer_add_ssh_string(session->out_buffer,type) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_channel)) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_window)) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_maxpacket)) < 0) { string_free(type); leave_function(); return -1; } string_free(type); if (payload != NULL) { if (buffer_add_buffer(session->out_buffer, payload) < 0) { leave_function(); return -1; } } if (packet_send(session) != SSH_OK) { leave_function(); return -1; } ssh_log(session, SSH_LOG_RARE, "Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d", type_c, channel->local_channel); if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) { leave_function(); return -1; } switch(session->in_packet.type) { case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: buffer_get_u32(session->in_buffer, &tmp); if (channel->local_channel != ntohl(tmp)) { ssh_set_error(session, SSH_FATAL, "Server answered with sender channel number %lu instead of given %u", (long unsigned int) ntohl(tmp), channel->local_channel); leave_function(); return -1; } buffer_get_u32(session->in_buffer, &tmp); channel->remote_channel = ntohl(tmp); buffer_get_u32(session->in_buffer, &tmp); channel->remote_window = ntohl(tmp); buffer_get_u32(session->in_buffer,&tmp); channel->remote_maxpacket=ntohl(tmp); ssh_log(session, SSH_LOG_PROTOCOL, "Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d", channel->local_channel, channel->remote_channel); ssh_log(session, SSH_LOG_PROTOCOL, "Remote window : %lu, maxpacket : %lu", (long unsigned int) channel->remote_window, (long unsigned int) channel->remote_maxpacket); channel->open = 1; leave_function(); return 0; case SSH2_MSG_CHANNEL_OPEN_FAILURE: { STRING *error_s; char *error; u32 code; buffer_get_u32(session->in_buffer, &tmp); buffer_get_u32(session->in_buffer, &code); error_s = buffer_get_ssh_string(session->in_buffer); error = string_to_char(error_s); string_free(error_s); if (error == NULL) { leave_function(); return -1; } ssh_set_error(session, SSH_REQUEST_DENIED, "Channel opening failure: channel %u error (%lu) %s", channel->local_channel, (long unsigned int) ntohl(code), error); SAFE_FREE(error); leave_function(); return -1; } default: ssh_set_error(session, SSH_FATAL, "Received unknown packet %d\n", session->in_packet.type); leave_function(); return -1; } leave_function(); return -1; }
static int channel_request(CHANNEL *channel, const char *request, BUFFER *buffer, int reply) { SSH_SESSION *session = channel->session; STRING *req = NULL; int rc = SSH_ERROR; enter_function(); req = string_from_char(request); if (req == NULL) { goto error; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_REQUEST) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0 || buffer_add_ssh_string(session->out_buffer, req) < 0 || buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) { goto error; } string_free(req); if (buffer != NULL) { if (buffer_add_data(session->out_buffer, buffer_get(buffer), buffer_get_len(buffer)) < 0) { goto error; } } if (packet_send(session) != SSH_OK) { leave_function(); return rc; } ssh_log(session, SSH_LOG_RARE, "Sent a SSH_MSG_CHANNEL_REQUEST %s", request); if (reply == 0) { leave_function(); return SSH_OK; } rc = packet_wait(session, SSH2_MSG_CHANNEL_SUCCESS, 1); if (rc) { if (session->in_packet.type == SSH2_MSG_CHANNEL_FAILURE) { ssh_log(session, SSH_LOG_PACKET, "%s channel request failed", request); ssh_set_error(session, SSH_REQUEST_DENIED, "Channel request %s failed", request); } else { ssh_log(session, SSH_LOG_RARE, "Received an unexpected %d message", session->in_packet.type); } } else { ssh_log(session, SSH_LOG_RARE, "Received a SUCCESS"); } leave_function(); return rc; error: buffer_free(session->out_buffer); string_free(req); leave_function(); return rc; }