/** * @brief Close the scp channel. * * @param[in] scp The scp context to close. * * @return SSH_OK on success or an SSH error code. * * @see ssh_scp_init() */ int ssh_scp_close(ssh_scp scp) { char buffer[128]; int err; if(scp==NULL) return SSH_ERROR; if(scp->channel != NULL){ if(ssh_channel_send_eof(scp->channel) == SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } /* avoid situations where data are buffered and * not yet stored on disk. This can happen if the close is sent * before we got the EOF back */ while(!ssh_channel_is_eof(scp->channel)){ err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0); if(err==SSH_ERROR || err==0) break; } if(ssh_channel_close(scp->channel) == SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } ssh_channel_free(scp->channel); scp->channel=NULL; } scp->state=SSH_SCP_NEW; return SSH_OK; }
void clSSH::OnCheckRemoteOutut(wxTimerEvent& event) { if(!m_channel) return; char buffer[1024]; int nbytes = ssh_channel_read_nonblocking(m_channel, buffer, sizeof(buffer), 0); if(nbytes > 0) { wxString strOutput = wxString::FromUTF8((const char*)buffer, nbytes); clCommandEvent sshEvent(wxEVT_SSH_COMMAND_OUTPUT); sshEvent.SetString(strOutput); m_owner->AddPendingEvent(sshEvent); } else if(nbytes == SSH_ERROR) { m_timer->Stop(); DoCloseChannel(); clCommandEvent sshEvent(wxEVT_SSH_COMMAND_ERROR); sshEvent.SetString(ssh_get_error(m_session)); m_owner->AddPendingEvent(sshEvent); } else { // nbytes == 0 if(ssh_channel_is_eof(m_channel)) { m_timer->Stop(); DoCloseChannel(); // EOF was sent, nothing more to read clCommandEvent sshEvent(wxEVT_SSH_COMMAND_COMPLETED); m_owner->AddPendingEvent(sshEvent); } else { // Nothing to read, no error } } }
/** * @brief Wait for a scp request (file, directory). * * @returns SSH_SCP_REQUEST_NEWFILE: The other side is sending * a file * SSH_SCP_REQUEST_NEWDIR: The other side is sending * a directory * SSH_SCP_REQUEST_ENDDIR: The other side has * finished with the current * directory * SSH_SCP_REQUEST_WARNING: The other side sent us a warning * SSH_SCP_REQUEST_EOF: The other side finished sending us * files and data. * SSH_ERROR: Some error happened * * @see ssh_scp_read() * @see ssh_scp_deny_request() * @see ssh_scp_accept_request() * @see ssh_scp_request_get_warning() */ int ssh_scp_pull_request(ssh_scp scp){ char buffer[MAX_BUF_SIZE] = {0}; char *mode=NULL; char *p,*tmp; uint64_t size; char *name=NULL; int err; if(scp==NULL) return SSH_ERROR; if(scp->state != SSH_SCP_READ_INITED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_pull_request called under invalid state"); return SSH_ERROR; } err=ssh_scp_read_string(scp,buffer,sizeof(buffer)); if(err==SSH_ERROR){ if(ssh_channel_is_eof(scp->channel)){ scp->state=SSH_SCP_TERMINATED; return SSH_SCP_REQUEST_EOF; } return err; } p=strchr(buffer,'\n'); if(p!=NULL) *p='\0'; SSH_LOG(SSH_LOG_PROTOCOL,"Received SCP request: '%s'",buffer); switch(buffer[0]){ case 'C': /* File */ case 'D': /* Directory */ p=strchr(buffer,' '); if(p==NULL) goto error; *p='\0'; p++; //mode=strdup(&buffer[1]); scp->request_mode=ssh_scp_integer_mode(&buffer[1]); tmp=p; p=strchr(p,' '); if(p==NULL) goto error; *p=0; size = strtoull(tmp,NULL,10); p++; name=strdup(p); SAFE_FREE(scp->request_name); scp->request_name=name; if(buffer[0]=='C'){ scp->filelen=size; scp->request_type=SSH_SCP_REQUEST_NEWFILE; } else { scp->filelen='0'; scp->request_type=SSH_SCP_REQUEST_NEWDIR; } scp->state=SSH_SCP_READ_REQUESTED; scp->processed = 0; return scp->request_type; break; case 'E': scp->request_type=SSH_SCP_REQUEST_ENDDIR; ssh_channel_write(scp->channel,"",1); return scp->request_type; case 0x1: ssh_set_error(scp->session,SSH_REQUEST_DENIED,"SCP: Warning: %s",&buffer[1]); scp->request_type=SSH_SCP_REQUEST_WARNING; SAFE_FREE(scp->warning); scp->warning=strdup(&buffer[1]); return scp->request_type; case 0x2: ssh_set_error(scp->session,SSH_FATAL,"SCP: Error: %s",&buffer[1]); return SSH_ERROR; case 'T': /* Timestamp */ default: ssh_set_error(scp->session,SSH_FATAL,"Unhandled message: (%d)%s",buffer[0],buffer); return SSH_ERROR; } /* a parsing error occured */ error: SAFE_FREE(name); SAFE_FREE(mode); ssh_set_error(scp->session,SSH_FATAL,"Parsing error while parsing message: %s",buffer); return SSH_ERROR; }
/* * @overload eof? * Check if remote ha sent an EOF. * @since 0.1.0 * @return [Boolean] * @see http://api.libssh.org/stable/group__libssh__channel.html * ssh_channel_is_eof */ static VALUE m_eof_p(VALUE self) { ChannelHolder *holder; TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder); return ssh_channel_is_eof(holder->channel) ? Qtrue : Qfalse; }
int channel_is_eof(ssh_channel channel){ return ssh_channel_is_eof(channel); }
static int nc_write(struct nc_session *session, const void *buf, size_t count) { int c; size_t written = 0; #ifdef NC_ENABLED_TLS unsigned long e; #endif if ((session->status != NC_STATUS_RUNNING) && (session->status != NC_STATUS_STARTING)) { return -1; } /* prevent SIGPIPE this way */ if (!nc_session_is_connected(session)) { ERR("Session %u: communication socket unexpectedly closed.", session->id); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_DROPPED; return -1; } DBG("Session %u: sending message:\n%.*s\n", session->id, count, buf); do { switch (session->ti_type) { case NC_TI_FD: c = write(session->ti.fd.out, (char *)(buf + written), count - written); if (c < 0) { ERR("Session %u: socket error (%s).", session->id, strerror(errno)); return -1; } break; #ifdef NC_ENABLED_SSH case NC_TI_LIBSSH: if (ssh_channel_is_closed(session->ti.libssh.channel) || ssh_channel_is_eof(session->ti.libssh.channel)) { if (ssh_channel_is_closed(session->ti.libssh.channel)) { ERR("Session %u: SSH channel unexpectedly closed.", session->id); } else { ERR("Session %u: SSH channel unexpected EOF.", session->id); } session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_DROPPED; return -1; } c = ssh_channel_write(session->ti.libssh.channel, (char *)(buf + written), count - written); if ((c == SSH_ERROR) || (c == -1)) { ERR("Session %u: SSH channel write failed.", session->id); return -1; } break; #endif #ifdef NC_ENABLED_TLS case NC_TI_OPENSSL: c = SSL_write(session->ti.tls, (char *)(buf + written), count - written); if (c < 1) { switch ((e = SSL_get_error(session->ti.tls, c))) { case SSL_ERROR_ZERO_RETURN: ERR("Session %u: SSL connection was properly closed.", session->id); return -1; case SSL_ERROR_WANT_WRITE: c = 0; break; case SSL_ERROR_SYSCALL: ERR("Session %u: SSL socket error (%s).", session->id, strerror(errno)); return -1; case SSL_ERROR_SSL: ERR("Session %u: SSL error (%s).", session->id, ERR_reason_error_string(e)); return -1; default: ERR("Session %u: unknown SSL error occured.", session->id); return -1; } } break; #endif default: ERRINT; return -1; } if (c == 0) { /* we must wait */ usleep(NC_TIMEOUT_STEP); } written += c; } while (written < count); return written; }
static ssize_t nc_read(struct nc_session *session, char *buf, size_t count, uint32_t inact_timeout, struct timespec *ts_act_timeout) { size_t readd = 0; ssize_t r = -1; struct timespec ts_cur, ts_inact_timeout; assert(session); assert(buf); if ((session->status != NC_STATUS_RUNNING) && (session->status != NC_STATUS_STARTING)) { return -1; } if (!count) { return 0; } nc_gettimespec_mono(&ts_inact_timeout); nc_addtimespec(&ts_inact_timeout, inact_timeout); do { switch (session->ti_type) { case NC_TI_NONE: return 0; case NC_TI_FD: /* read via standard file descriptor */ r = read(session->ti.fd.in, buf + readd, count - readd); if (r < 0) { if ((errno == EAGAIN) || (errno == EINTR)) { r = 0; break; } else { ERR("Session %u: reading from file descriptor (%d) failed (%s).", session->id, session->ti.fd.in, strerror(errno)); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_OTHER; return -1; } } else if (r == 0) { ERR("Session %u: communication file descriptor (%d) unexpectedly closed.", session->id, session->ti.fd.in); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_DROPPED; return -1; } break; #ifdef NC_ENABLED_SSH case NC_TI_LIBSSH: /* read via libssh */ r = ssh_channel_read(session->ti.libssh.channel, buf + readd, count - readd, 0); if (r == SSH_AGAIN) { r = 0; break; } else if (r == SSH_ERROR) { ERR("Session %u: reading from the SSH channel failed (%s).", session->id, ssh_get_error(session->ti.libssh.session)); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_OTHER; return -1; } else if (r == 0) { if (ssh_channel_is_eof(session->ti.libssh.channel)) { ERR("Session %u: SSH channel unexpected EOF.", session->id); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_DROPPED; return -1; } break; } break; #endif #ifdef NC_ENABLED_TLS case NC_TI_OPENSSL: /* read via OpenSSL */ r = SSL_read(session->ti.tls, buf + readd, count - readd); if (r <= 0) { int x; switch (x = SSL_get_error(session->ti.tls, r)) { case SSL_ERROR_WANT_READ: r = 0; break; case SSL_ERROR_ZERO_RETURN: ERR("Session %u: communication socket unexpectedly closed (OpenSSL).", session->id); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_DROPPED; return -1; default: ERR("Session %u: reading from the TLS session failed (SSL code %d).", session->id, x); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_OTHER; return -1; } } break; #endif } if (r == 0) { /* nothing read */ usleep(NC_TIMEOUT_STEP); nc_gettimespec_mono(&ts_cur); if ((nc_difftimespec(&ts_cur, &ts_inact_timeout) < 1) || (nc_difftimespec(&ts_cur, ts_act_timeout) < 1)) { if (nc_difftimespec(&ts_cur, &ts_inact_timeout) < 1) { ERR("Session %u: inactive read timeout elapsed.", session->id); } else { ERR("Session %u: active read timeout elapsed.", session->id); } session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_OTHER; return -1; } } else { /* something read */ readd += r; /* reset inactive timeout */ nc_gettimespec_mono(&ts_inact_timeout); nc_addtimespec(&ts_inact_timeout, inact_timeout); } } while (readd < count); buf[count] = '\0'; return (ssize_t)readd; }