/** * @brief Initialize the sending of a file to a scp in sink mode. * * @param[in] scp The scp handle. * * @param[in] filename The name of the file being sent. It should not contain * any path indicator * * @param[in] size Exact size in bytes of the file being sent. * * @param[in] mode The UNIX permissions for the new file, e.g. 0644. * * @returns SSH_OK if the file is ready to be sent, SSH_ERROR if an * error occured. */ 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==NULL) return SSH_ERROR; 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=ssh_channel_write(scp->channel,buffer,strlen(buffer)); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r=ssh_channel_read(scp->channel,&code,1,0); if(r<=0){ ssh_set_error(scp->session,SSH_FATAL, "Error reading status code: %s",ssh_get_error(scp->session)); scp->state=SSH_SCP_ERROR; return SSH_ERROR; } 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; }
/** * @internal * * @brief Gets the banner from socket and saves it in session. * Updates the session state * * @param data pointer to the beginning of header * @param len size of the banner * @param user is a pointer to session * @returns Number of bytes processed, or zero if the banner is not complete. */ static int callback_receive_banner(const void *data, size_t len, void *user) { char *buffer = (char *) data; ssh_session session = (ssh_session) user; char *str = NULL; size_t i; int ret=0; enter_function(); for (i = 0; i < len; i++) { #ifdef WITH_PCAP if(session->pcap_ctx && buffer[i] == '\n') { ssh_pcap_context_write(session->pcap_ctx, SSH_PCAP_DIR_IN, buffer, i + 1, i + 1); } #endif if (buffer[i] == '\r') { buffer[i]='\0'; } if (buffer[i] == '\n') { buffer[i]='\0'; str = strdup(buffer); /* number of bytes read */ ret = i + 1; session->clientbanner = str; session->session_state = SSH_SESSION_STATE_BANNER_RECEIVED; ssh_log(session, SSH_LOG_PACKET, "Received banner: %s", str); session->ssh_connection_callback(session); leave_function(); return ret; } if(i > 127) { /* Too big banner */ session->session_state = SSH_SESSION_STATE_ERROR; ssh_set_error(session, SSH_FATAL, "Receiving banner: too large banner"); leave_function(); return 0; } } leave_function(); return ret; }
static int send_username(ssh_session session, const char *username) { ssh_string user = NULL; /* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */ if(session->auth_service_state == SSH_AUTH_SERVICE_USER_SENT) { if(session->auth_state == SSH_AUTH_STATE_FAILED) return SSH_AUTH_DENIED; if(session->auth_state == SSH_AUTH_STATE_SUCCESS) return SSH_AUTH_SUCCESS; return SSH_AUTH_ERROR; } if (!username) { if(!(username = session->username)) { if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { session->auth_service_state = SSH_AUTH_SERVICE_DENIED; return SSH_ERROR; } else { username = session->username; } } } user = ssh_string_from_char(username); if (user == NULL) { return SSH_AUTH_ERROR; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } if (buffer_add_ssh_string(session->out_buffer, user) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } ssh_string_free(user); session->auth_state=SSH_AUTH_STATE_NONE; if (packet_send(session) == SSH_ERROR) { return SSH_AUTH_ERROR; } if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){ session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; session->auth_state=SSH_AUTH_STATE_SUCCESS; return SSH_AUTH_SUCCESS; } else { session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; ssh_set_error(session,SSH_REQUEST_DENIED,"Password authentication necessary for user %s",username); return SSH_AUTH_DENIED; } }
static int packet_wait2(SSH_SESSION *session, int type, int blocking) { int rc = SSH_ERROR; enter_function(); do { rc = packet_read2(session); if (rc != SSH_OK) { leave_function(); return rc; } if (packet_translate(session) != SSH_OK) { leave_function(); return SSH_ERROR; } switch (session->in_packet.type) { case SSH2_MSG_DISCONNECT: packet_parse(session); ssh_log(session, SSH_LOG_PACKET, "received disconnect packet"); leave_function(); return SSH_ERROR; case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_DATA: case SSH2_MSG_CHANNEL_EXTENDED_DATA: case SSH2_MSG_CHANNEL_REQUEST: case SSH2_MSG_CHANNEL_EOF: case SSH2_MSG_CHANNEL_CLOSE: packet_parse(session); break; case SSH2_MSG_IGNORE: break; default: if (type && (type != session->in_packet.type)) { ssh_set_error(session, SSH_FATAL, "packet_wait2(): Received a %d type packet, but expected a %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; //shouldn't it return SSH_AGAIN here ? } } while(1); leave_function(); return SSH_OK; }
static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t maxlen) { z_stream *zin = session->current_crypto->compress_in_ctx; void *in_ptr = buffer_get_rest(source); unsigned long in_size = buffer_get_rest_len(source); unsigned char out_buf[BLOCKSIZE] = {0}; ssh_buffer dest = NULL; unsigned long len; int status; if (zin == NULL) { zin = session->current_crypto->compress_in_ctx = initdecompress(session); if (zin == NULL) { return NULL; } } dest = ssh_buffer_new(); if (dest == NULL) { return NULL; } zin->next_out = out_buf; zin->next_in = in_ptr; zin->avail_in = in_size; do { zin->avail_out = BLOCKSIZE; status = inflate(zin, Z_PARTIAL_FLUSH); if (status != Z_OK && status != Z_BUF_ERROR) { ssh_set_error(session, SSH_FATAL, "status %d inflating zlib packet", status); ssh_buffer_free(dest); return NULL; } len = BLOCKSIZE - zin->avail_out; if (buffer_add_data(dest,out_buf,len) < 0) { ssh_buffer_free(dest); return NULL; } if (buffer_get_rest_len(dest) > maxlen) { /* Size of packet exceeded, avoid a denial of service attack */ ssh_buffer_free(dest); return NULL; } zin->next_out = out_buf; } while (zin->avail_out == 0); return dest; }
/** @internal * @brief launches the DH handshake state machine * @param session session handle * @returns SSH_OK or SSH_ERROR * @warning this function returning is no proof that DH handshake is * completed */ static int dh_handshake(ssh_session session) { int rc = SSH_AGAIN; switch (session->dh_handshake_state) { case DH_STATE_INIT: switch(session->next_crypto->kex_type){ case SSH_KEX_DH_GROUP1_SHA1: case SSH_KEX_DH_GROUP14_SHA1: rc = ssh_client_dh_init(session); break; #ifdef HAVE_ECDH case SSH_KEX_ECDH_SHA2_NISTP256: case SSH_KEX_ECDH_SHA2_NISTP384: case SSH_KEX_ECDH_SHA2_NISTP521: rc = ssh_client_ecdh_init(session); break; #endif #ifdef HAVE_CURVE25519 case SSH_KEX_CURVE25519_SHA256: case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: rc = ssh_client_curve25519_init(session); break; #endif default: rc = SSH_ERROR; } if (rc == SSH_ERROR) { return SSH_ERROR; } session->dh_handshake_state = DH_STATE_INIT_SENT; case DH_STATE_INIT_SENT: /* wait until ssh_packet_dh_reply is called */ break; case DH_STATE_NEWKEYS_SENT: /* wait until ssh_packet_newkeys is called */ break; case DH_STATE_FINISHED: return SSH_OK; default: ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d", session->dh_handshake_state); return SSH_ERROR; } return rc; }
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb){ if (session == NULL || cb == NULL) { return SSH_ERROR; } if(cb->size <= 0 || cb->size > 1024 * sizeof(void *)){ ssh_set_error(session,SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; } session->server_callbacks = cb; return 0; }
/** * @internal * * @brief Wait for a response of the scp server. * * @param[in] scp The scp handle. * * @param[out] response A pointer where the response message must be copied if * any. This pointer must then be free'd. * * @returns The return code, SSH_ERROR a error occured. */ int ssh_scp_response(ssh_scp scp, char **response){ unsigned char code; int r; char msg[128]; if(scp==NULL) return SSH_ERROR; r=ssh_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(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 * @parse the "Type" header field of a packet and updates the session */ int ssh_packet_parse_type(ssh_session session) { memset(&session->in_packet, 0, sizeof(PACKET)); if(session->in_buffer == NULL) { return SSH_ERROR; } if(buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) { ssh_set_error(session, SSH_FATAL, "Packet too short to read type"); return SSH_ERROR; } session->in_packet.valid = 1; return SSH_OK; }
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb){ if (session == NULL || cb == NULL) { return SSH_ERROR; } if (is_callback_valid(session, cb)) { ssh_set_error(session, SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; }; session->server_callbacks = cb; return 0; }
int set_kex(ssh_session session){ KEX *server = &session->server_kex; KEX *client=&session->client_kex; int i; const char *wanted; enter_function(); ssh_get_random(client->cookie,16,0); client->methods=malloc(10 * sizeof(char **)); if (client->methods == NULL) { ssh_set_error(session, SSH_FATAL, "No space left"); leave_function(); return -1; } memset(client->methods,0,10*sizeof(char **)); for (i=0;i<10;i++){ if(!(wanted=session->wanted_methods[i])) wanted=default_methods[i]; client->methods[i]=ssh_find_matching(server->methods[i],wanted); if(!client->methods[i] && i < SSH_LANG_C_S){ ssh_set_error(session,SSH_FATAL,"kex error : did not find one of algos %s in list %s for %s", wanted,server->methods[i],ssh_kex_nums[i]); leave_function(); return -1; } else { if ((i >= SSH_LANG_C_S) && (client->methods[i] == NULL)) { /* we can safely do that for languages */ client->methods[i] = strdup(""); if (client->methods[i] == NULL) { return -1; } } } } leave_function(); return 0; }
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) { ssh_session session = channel->session; 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 -1; } if (packet_send(session)) { return -1; } ssh_log(session, SSH_LOG_RARE, "Change pty size send"); if (packet_wait(session, SSH_SMSG_SUCCESS, 1) != SSH_OK) { return -1; } switch (session->in_packet.type) { case SSH_SMSG_SUCCESS: ssh_log(session, SSH_LOG_RARE, "pty size changed"); return 0; case SSH_SMSG_FAILURE: ssh_log(session, SSH_LOG_RARE, "pty size change denied"); ssh_set_error(session, SSH_REQUEST_DENIED, "pty size change denied"); return -1; } ssh_set_error(session, SSH_FATAL, "Received unexpected packet type %d", session->in_packet.type); return -1; }
int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr){ socket_t fd; if(s->state != SSH_SOCKET_NONE) { ssh_set_error(s->session, SSH_FATAL, "ssh_socket_connect called on socket not unconnected"); return SSH_ERROR; } fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port); SSH_LOG(SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd); if(fd == SSH_INVALID_SOCKET) return SSH_ERROR; ssh_socket_set_fd(s,fd); return SSH_OK; }
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; }
/** @internal * @brief launches the DH handshake state machine * @param session session handle * @returns SSH_OK or SSH_ERROR * @warning this function returning is no proof that DH handshake is * completed */ static int dh_handshake(ssh_session session) { int rc = SSH_AGAIN; enter_function(); switch (session->dh_handshake_state) { case DH_STATE_INIT: switch(session->next_crypto->kex_type){ case SSH_KEX_DH_GROUP1_SHA1: case SSH_KEX_DH_GROUP14_SHA1: rc = ssh_client_dh_init(session); break; #ifdef HAVE_ECDH case SSH_KEX_ECDH_SHA2_NISTP256: rc = ssh_client_ecdh_init(session); break; #endif default: rc=SSH_ERROR; goto error; } if (rc == SSH_ERROR) { goto error; } session->dh_handshake_state = DH_STATE_INIT_SENT; case DH_STATE_INIT_SENT: /* wait until ssh_packet_dh_reply is called */ break; case DH_STATE_NEWKEYS_SENT: /* wait until ssh_packet_newkeys is called */ break; case DH_STATE_FINISHED: leave_function(); return SSH_OK; default: ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d", session->dh_handshake_state); leave_function(); return SSH_ERROR; } error: leave_function(); return rc; }
static int agent_decode_reply(struct ssh_session_struct *session, int type) { switch (type) { case SSH_AGENT_FAILURE: case SSH2_AGENT_FAILURE: case SSH_COM_AGENT2_FAILURE: ssh_log(session, SSH_LOG_RARE, "SSH_AGENT_FAILURE"); return 0; case SSH_AGENT_SUCCESS: return 1; default: ssh_set_error(session, SSH_FATAL, "Bad response from authentication agent: %d", type); break; } return -1; }
/** * @brief denies the transfer of a file or creation of a directory * coming from the remote party * @param scp the scp handle. * @param reason nul-terminated string with a human-readable explanation * of the deny * @returns SSH_OK the message was sent * @returns SSH_ERROR Error sending the message, or sending it in a bad state */ int ssh_scp_deny_request(ssh_scp scp, const char *reason){ char buffer[4096]; int err; if(scp->state != SSH_SCP_READ_REQUESTED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state"); return SSH_ERROR; } snprintf(buffer,sizeof(buffer),"%c%s\n",2,reason); err=channel_write(scp->channel,buffer,strlen(buffer)); if(err==SSH_ERROR) { return SSH_ERROR; } else { scp->state=SSH_SCP_READ_INITED; return SSH_OK; } }
/** * @brief accepts transfer of a file or creation of a directory * coming from the remote party * @param scp the scp handle. * @returns SSH_OK the message was sent * @returns SSH_ERROR Error sending the message, or sending it in a bad state */ int ssh_scp_accept_request(ssh_scp scp){ char buffer[]={0x00}; int err; if(scp->state != SSH_SCP_READ_REQUESTED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state"); return SSH_ERROR; } err=channel_write(scp->channel,buffer,1); if(err==SSH_ERROR) { return SSH_ERROR; } if(scp->request_type==SSH_SCP_REQUEST_NEWFILE) scp->state=SSH_SCP_READ_READING; else scp->state=SSH_SCP_READ_INITED; return SSH_OK; }
int ssh_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb) { ssh_session session = NULL; if (channel == NULL || cb == NULL) { return SSH_ERROR; } session = channel->session; if(cb->size <= 0 || cb->size > 1024 * sizeof(void *)){ ssh_set_error(session,SSH_FATAL, "Invalid channel callback passed in (badly initialized)"); return SSH_ERROR; } channel->callbacks = cb; return 0; }
int ssh_set_io_callbacks(ssh_session session, ssh_socket_io_callbacks io_cb) { if (session == NULL ) { return SSH_ERROR; } if (io_cb == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; } session->socket_io_callbacks = *io_cb; if (session->socket) session->socket->io_callbacks = &(session->socket_io_callbacks); return SSH_OK; }
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks, void *userdata){ if (sshbind == NULL) { return SSH_ERROR; } if (callbacks == NULL) { ssh_set_error_invalid(sshbind); return SSH_ERROR; } if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){ ssh_set_error(sshbind,SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; } sshbind->bind_callbacks = callbacks; sshbind->bind_callbacks_userdata=userdata; return 0; }
static ssh_buffer gzip_compress(ssh_session session,ssh_buffer source,int level) { z_stream *zout = session->current_crypto->compress_out_ctx; void *in_ptr = buffer_get_rest(source); unsigned long in_size = buffer_get_rest_len(source); ssh_buffer dest = NULL; unsigned char out_buf[BLOCKSIZE] = {0}; unsigned long len; int status; if(zout == NULL) { zout = session->current_crypto->compress_out_ctx = initcompress(session, level); if (zout == NULL) { return NULL; } } dest = ssh_buffer_new(); if (dest == NULL) { return NULL; } zout->next_out = out_buf; zout->next_in = in_ptr; zout->avail_in = in_size; do { zout->avail_out = BLOCKSIZE; status = deflate(zout, Z_PARTIAL_FLUSH); if (status != Z_OK) { ssh_buffer_free(dest); ssh_set_error(session, SSH_FATAL, "status %d deflating zlib packet", status); return NULL; } len = BLOCKSIZE - zout->avail_out; if (buffer_add_data(dest, out_buf, len) < 0) { ssh_buffer_free(dest); return NULL; } zout->next_out = out_buf; } while (zout->avail_out == 0); return dest; }
/** @brief Read from a remote scp file * @param[in] scp The scp handle. * * @param[in] buffer The destination buffer. * * @param[in] size The size of the buffer. * * @returns The nNumber of bytes read, SSH_ERROR if an error occured * while reading. */ int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){ int r; int code; if(scp==NULL) return SSH_ERROR; if(scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE){ r=ssh_scp_accept_request(scp); if(r==SSH_ERROR) return r; } if(scp->state != SSH_SCP_READ_READING){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_read called under invalid state"); return SSH_ERROR; } if(scp->processed + size > scp->filelen) size = (size_t) (scp->filelen - scp->processed); if(size > 65536) size=65536; /* avoid too large reads */ r=ssh_channel_read(scp->channel,buffer,size,0); if(r != SSH_ERROR) scp->processed += r; else { scp->state=SSH_SCP_ERROR; return SSH_ERROR; } /* Check if we arrived at end of file */ if(scp->processed == scp->filelen) { scp->processed=scp->filelen=0; ssh_channel_write(scp->channel,"",1); code=ssh_scp_response(scp,NULL); if(code == 0){ scp->state=SSH_SCP_READ_INITED; return r; } if(code==1){ scp->state=SSH_SCP_READ_INITED; return SSH_ERROR; } scp->state=SSH_SCP_ERROR; return SSH_ERROR; } return r; }
static z_stream *initdecompress(ssh_session session) { z_stream *stream = NULL; int status; stream = malloc(sizeof(z_stream)); if (stream == NULL) { return NULL; } memset(stream,0,sizeof(z_stream)); status = inflateInit(stream); if (status != Z_OK) { SAFE_FREE(stream); ssh_set_error(session, SSH_FATAL, "Status = %d initiating inflate context!", status); return NULL; } return stream; }
int ssh_bind_listen(SSH_BIND *ssh_bind){ char *host; int fd; if(!ssh_bind->options) return -1; // host=ssh_bind->options->bindaddr; // FIXME -- common // if(!host) host="0.0.0.0"; fd=bind_socket(ssh_bind,host,ssh_bind->options->localport); if(fd<0) return -1; ssh_bind->bindfd=fd; if(listen(fd,10)<0){ ssh_set_error(ssh_bind,SSH_FATAL,"listening to socket %d: %s", fd,strerror(errno)); close(fd); return -1; } return 0; }
static z_stream *initcompress(ssh_session session, int level) { z_stream *stream = NULL; int status; stream = malloc(sizeof(z_stream)); if (stream == NULL) { return NULL; } memset(stream, 0, sizeof(z_stream)); status = deflateInit(stream, level); if (status != Z_OK) { SAFE_FREE(stream); ssh_set_error(session, SSH_FATAL, "status %d inititalising zlib deflate", status); return NULL; } return stream; }
/** * @brief reads a string on a channel, terminated by '\n' * @param scp the scp handle. * @param buffer pointer to a buffer to place the string * @param len size of the buffer in bytes. If the string is bigger * than len-1, only len-1 bytes are read and the string * is null-terminated. * @returns SSH_OK The string was read * @returns SSH_ERROR Error happened while reading */ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){ size_t r=0; int err=SSH_OK; while(r<len-1){ err=channel_read(scp->channel,&buffer[r],1,0); if(err==SSH_ERROR){ break; } if(err==0){ ssh_set_error(scp->session,SSH_FATAL,"End of file while reading string"); err=SSH_ERROR; break; } r++; if(buffer[r-1] == '\n') break; } buffer[r]=0; return err; }
int channel_open_session1(ssh_channel chan) { /* * 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. */ ssh_session session = chan->session; 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->open = 1; chan->local_maxpacket = 32000; chan->local_window = 64000; ssh_log(session, SSH_LOG_PACKET, "Opened a SSH1 channel session"); return 0; }
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) { if (session == NULL || cb == NULL) { return SSH_ERROR; } if (is_callback_valid(session, cb)) { ssh_set_error(session, SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; }; session->common.callbacks = cb; /* LEGACY */ if (ssh_get_log_callback() == NULL && cb->log_function) { ssh_set_log_callback(ssh_legacy_log_callback); ssh_set_log_userdata(session); } return 0; }
/** * @brief Write into a remote scp file. * * @param[in] scp The scp handle. * * @param[in] buffer The buffer to write. * * @param[in] len The number of bytes to write. * * @returns SSH_OK if the write was successful, SSH_ERROR an error * occured while writing. */ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){ int w; //int r; //uint8_t code; if(scp==NULL) return SSH_ERROR; if(scp->state != SSH_SCP_WRITE_WRITING){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_write called under invalid state"); return SSH_ERROR; } if(scp->processed + len > scp->filelen) len = scp->filelen - scp->processed; /* hack to avoid waiting for window change */ ssh_channel_poll(scp->channel,0); w=ssh_channel_write(scp->channel,buffer,len); if(w != SSH_ERROR) scp->processed += w; else { scp->state=SSH_SCP_ERROR; //return=channel_get_exit_status(scp->channel); return SSH_ERROR; } /* Check if we arrived at end of file */ if(scp->processed == scp->filelen) { /* r=channel_read(scp->channel,&code,1,0); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } 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->processed=scp->filelen=0; scp->state=SSH_SCP_WRITE_INITED; } return SSH_OK; }