/** * @brief Connect to the ssh server. * * @param[in] session The ssh session to connect. * * @returns SSH_OK on success, SSH_ERROR on error. * @returns SSH_AGAIN, if the session is in nonblocking mode, * and call must be done again. * * @see ssh_new() * @see ssh_disconnect() */ int ssh_connect(ssh_session session) { int ret; if (session == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid session pointer"); return SSH_ERROR; } enter_function(); switch(session->pending_call_state){ case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_CONNECT: goto pending; default: ssh_set_error(session,SSH_FATAL,"Bad call during pending SSH call in ssh_connect"); leave_function(); return SSH_ERROR; } session->alive = 0; session->client = 1; if (ssh_init() < 0) { leave_function(); return SSH_ERROR; } if (session->fd == SSH_INVALID_SOCKET && session->host == NULL && session->ProxyCommand == NULL) { ssh_set_error(session, SSH_FATAL, "Hostname required"); leave_function(); return SSH_ERROR; } ret = ssh_options_apply(session); if (ret < 0) { ssh_set_error(session, SSH_FATAL, "Couldn't apply options"); leave_function(); return SSH_ERROR; } ssh_log(session,SSH_LOG_RARE,"libssh %s, using threading %s", ssh_copyright(), ssh_threads_get_type()); session->ssh_connection_callback = ssh_client_connection_callback; session->session_state=SSH_SESSION_STATE_CONNECTING; ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); session->socket_callbacks.connected=socket_callback_connected; session->socket_callbacks.data=callback_receive_banner; session->socket_callbacks.exception=ssh_socket_exception_callback; session->socket_callbacks.userdata=session; if (session->fd != SSH_INVALID_SOCKET) { ssh_socket_set_fd(session->socket, session->fd); ret=SSH_OK; #ifndef _WIN32 } else if (session->ProxyCommand != NULL){ ret=ssh_socket_connect_proxycommand(session->socket, session->ProxyCommand); #endif } else { ret=ssh_socket_connect(session->socket, session->host, session->port, session->bindaddr); /*, session->timeout * 1000 + session->timeout_usec); */ } if (ret == SSH_ERROR) { leave_function(); return SSH_ERROR; } set_status(session, 0.2f); session->alive = 1; ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work"); pending: session->pending_call_state=SSH_PENDING_CALL_CONNECT; if(ssh_is_blocking(session)) ssh_handle_packets_termination(session,-1,ssh_connect_termination,session); else ssh_handle_packets_termination(session,0,ssh_connect_termination, session); ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state); if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){ leave_function(); return SSH_AGAIN; } leave_function(); session->pending_call_state=SSH_PENDING_CALL_NONE; if(session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED) return SSH_ERROR; return SSH_OK; }
int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){ socket_t pair[2]; int pid; int rc; if (s->state != SSH_SOCKET_NONE) { return SSH_ERROR; } rc = socketpair(PF_LOCAL, SOCK_STREAM, 0, pair); if (rc < 0) { return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL,"Executing proxycommand '%s'",command); pid = fork(); if(pid == 0){ ssh_execute_command(command,pair[0],pair[0]); } close(pair[0]); SSH_LOG(SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]); ssh_socket_set_fd(s, pair[1]); s->state=SSH_SOCKET_CONNECTED; s->fd_is_socket=0; /* POLLOUT is the event to wait for in a nonblocking connect */ ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLIN | POLLOUT); if(s->callbacks && s->callbacks->connected) { s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata); } return SSH_OK; }
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ int i; if (session == NULL){ ssh_set_error(sshbind, SSH_FATAL,"session is null"); return SSH_ERROR; } session->server = 1; session->version = 2; /* copy options */ for (i = 0; i < 10; ++i) { if (sshbind->wanted_methods[i]) { session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]); if (session->wanted_methods[i] == NULL) { return SSH_ERROR; } } } if (sshbind->bindaddr == NULL) session->bindaddr = NULL; else { SAFE_FREE(session->bindaddr); session->bindaddr = strdup(sshbind->bindaddr); if (session->bindaddr == NULL) { return SSH_ERROR; } } session->common.log_verbosity = sshbind->common.log_verbosity; ssh_socket_free(session->socket); session->socket = ssh_socket_new(session); if (session->socket == NULL) { /* perhaps it may be better to copy the error from session to sshbind */ ssh_set_error_oom(sshbind); return SSH_ERROR; } ssh_socket_set_fd(session->socket, fd); ssh_socket_get_poll_handle_out(session->socket); if (sshbind->dsa) { session->srv.dsa_key = ssh_key_dup(sshbind->dsa); if (session->srv.dsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } if (sshbind->rsa) { session->srv.rsa_key = ssh_key_dup(sshbind->rsa); if (session->srv.rsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } return SSH_OK; }
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_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); s->state=SSH_SOCKET_CONNECTING; /* POLLOUT is the event to wait for in a nonblocking connect */ ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLOUT); #ifdef _WIN32 ssh_poll_add_events(ssh_socket_get_poll_handle_in(s),POLLWRNORM); #endif return SSH_OK; }
/** * @brief Connect to the ssh server. * * @param[in] session The ssh session to connect. * * @returns SSH_OK on success, SSH_ERROR on error. * @returns SSH_AGAIN, if the session is in nonblocking mode, * and call must be done again. * * @see ssh_new() * @see ssh_disconnect() */ int ssh_connect(ssh_session session) { int ret; if (session == NULL) { return SSH_ERROR; } switch(session->pending_call_state){ case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_CONNECT: goto pending; default: ssh_set_error(session,SSH_FATAL,"Bad call during pending SSH call in ssh_connect"); return SSH_ERROR; } session->alive = 0; session->client = 1; if (ssh_init() < 0) { return SSH_ERROR; } if (session->opts.fd == SSH_INVALID_SOCKET && session->opts.host == NULL && session->opts.ProxyCommand == NULL) { ssh_set_error(session, SSH_FATAL, "Hostname required"); return SSH_ERROR; } ret = ssh_options_apply(session); if (ret < 0) { ssh_set_error(session, SSH_FATAL, "Couldn't apply options"); return SSH_ERROR; } SSH_LOG(SSH_LOG_RARE,"libssh %s, using threading %s", ssh_copyright(), ssh_threads_get_type()); session->ssh_connection_callback = ssh_client_connection_callback; session->session_state=SSH_SESSION_STATE_CONNECTING; ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); session->socket_callbacks.connected=socket_callback_connected; session->socket_callbacks.data=callback_receive_banner; session->socket_callbacks.exception=ssh_socket_exception_callback; session->socket_callbacks.userdata=session; if (session->opts.fd != SSH_INVALID_SOCKET) { session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED; ssh_socket_set_fd(session->socket, session->opts.fd); ret=SSH_OK; #ifndef _WIN32 } else if (session->opts.ProxyCommand != NULL){ ret = ssh_socket_connect_proxycommand(session->socket, session->opts.ProxyCommand); #endif } else { ret=ssh_socket_connect(session->socket, session->opts.host, session->opts.port, session->opts.bindaddr); } if (ret == SSH_ERROR) { return SSH_ERROR; } set_status(session, 0.2f); session->alive = 1; SSH_LOG(SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work"); pending: session->pending_call_state=SSH_PENDING_CALL_CONNECT; if(ssh_is_blocking(session)) { int timeout = (session->opts.timeout * 1000) + (session->opts.timeout_usec / 1000); if (timeout == 0) { timeout = 10 * 1000; } SSH_LOG(SSH_LOG_PACKET,"Actual timeout : %d", timeout); ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session); if (session->session_state != SSH_SESSION_STATE_ERROR && (ret == SSH_ERROR || !ssh_connect_termination(session))) { ssh_set_error(session, SSH_FATAL, "Timeout connecting to %s", session->opts.host); session->session_state = SSH_SESSION_STATE_ERROR; } } else { ret = ssh_handle_packets_termination(session, SSH_TIMEOUT_NONBLOCKING, ssh_connect_termination, session); if (ret == SSH_ERROR) { session->session_state = SSH_SESSION_STATE_ERROR; } } SSH_LOG(SSH_LOG_PACKET,"current state : %d",session->session_state); if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){ return SSH_AGAIN; } session->pending_call_state=SSH_PENDING_CALL_NONE; if(session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED) return SSH_ERROR; return SSH_OK; }
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ int i, rc; if (session == NULL){ ssh_set_error(sshbind, SSH_FATAL,"session is null"); return SSH_ERROR; } session->server = 1; session->version = 2; /* copy options */ for (i = 0; i < 10; i++) { if (sshbind->wanted_methods[i]) { session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]); if (session->opts.wanted_methods[i] == NULL) { return SSH_ERROR; } } } if (sshbind->bindaddr == NULL) session->opts.bindaddr = NULL; else { SAFE_FREE(session->opts.bindaddr); session->opts.bindaddr = strdup(sshbind->bindaddr); if (session->opts.bindaddr == NULL) { return SSH_ERROR; } } session->common.log_verbosity = sshbind->common.log_verbosity; if(sshbind->banner != NULL) session->opts.custombanner = strdup(sshbind->banner); ssh_socket_free(session->socket); session->socket = ssh_socket_new(session); if (session->socket == NULL) { /* perhaps it may be better to copy the error from session to sshbind */ ssh_set_error_oom(sshbind); return SSH_ERROR; } ssh_socket_set_fd(session->socket, fd); ssh_socket_get_poll_handle_out(session->socket); /* We must try to import any keys that could be imported in case * we are not using ssh_bind_listen (which is the other place * where keys can be imported) on this ssh_bind and are instead * only using ssh_bind_accept_fd to manage sockets ourselves. */ rc = ssh_bind_import_keys(sshbind); if (rc != SSH_OK) { return SSH_ERROR; } #ifdef HAVE_ECC if (sshbind->ecdsa) { session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa); if (session->srv.ecdsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } #endif if (sshbind->dsa) { session->srv.dsa_key = ssh_key_dup(sshbind->dsa); if (session->srv.dsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } if (sshbind->rsa) { session->srv.rsa_key = ssh_key_dup(sshbind->rsa); if (session->srv.rsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } if (sshbind->ed25519 != NULL) { session->srv.ed25519_key = ssh_key_dup(sshbind->ed25519); if (session->srv.ed25519_key == NULL){ ssh_set_error_oom(sshbind); return SSH_ERROR; } } /* force PRNG to change state in case we fork after ssh_bind_accept */ ssh_reseed(); return SSH_OK; }
/** * @brief SSH poll callback. This callback will be used when an event * caught on the socket. * * @param p Poll object this callback belongs to. * @param fd The raw socket. * @param revents The current poll events on the socket. * @param userdata Userdata to be passed to the callback function, * in this case the socket object. * * @return 0 on success, < 0 when the poll object has been removed * from its poll context. */ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s) { ssh_socket s = (ssh_socket)v_s; char buffer[MAX_BUF_SIZE]; int r; int err = 0; socklen_t errlen = sizeof(err); /* Do not do anything if this socket was already closed */ if (!ssh_socket_is_open(s)) { return -1; } SSH_LOG(SSH_LOG_TRACE, "Poll callback on socket %d (%s%s%s), out buffer %d",fd, (revents & POLLIN) ? "POLLIN ":"", (revents & POLLOUT) ? "POLLOUT ":"", (revents & POLLERR) ? "POLLERR":"", ssh_buffer_get_len(s->out_buffer)); if (revents & POLLERR || revents & POLLHUP) { /* Check if we are in a connecting state */ if (s->state == SSH_SOCKET_CONNECTING) { s->state = SSH_SOCKET_ERROR; r = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); if (r < 0) { err = errno; } s->last_errno = err; ssh_socket_close(s); if (s->callbacks && s->callbacks->connected) { s->callbacks->connected(SSH_SOCKET_CONNECTED_ERROR, err, s->callbacks->userdata); } return -1; } /* Then we are in a more standard kind of error */ /* force a read to get an explanation */ revents |= POLLIN; } if ((revents & POLLIN) && s->state == SSH_SOCKET_CONNECTED) { s->read_wontblock = 1; r = ssh_socket_unbuffered_read(s, buffer, sizeof(buffer)); if (r < 0) { if (p != NULL) { ssh_poll_remove_events(p, POLLIN); } if (s->callbacks && s->callbacks->exception) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR, s->last_errno, s->callbacks->userdata); /* p may have been freed, so don't use it * anymore in this function */ p = NULL; return -2; } } if (r == 0) { if (p != NULL) { ssh_poll_remove_events(p, POLLIN); } if (p != NULL) { ssh_poll_remove_events(p, POLLIN); } if (s->callbacks && s->callbacks->exception) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF, 0, s->callbacks->userdata); /* p may have been freed, so don't use it * anymore in this function */ p = NULL; return -2; } } if (r > 0) { if (s->session->socket_counter != NULL) { s->session->socket_counter->in_bytes += r; } /* Bufferize the data and then call the callback */ r = ssh_buffer_add_data(s->in_buffer, buffer, r); if (r < 0) { return -1; } if (s->callbacks && s->callbacks->data) { do { r = s->callbacks->data(ssh_buffer_get(s->in_buffer), ssh_buffer_get_len(s->in_buffer), s->callbacks->userdata); ssh_buffer_pass_bytes(s->in_buffer, r); } while ((r > 0) && (s->state == SSH_SOCKET_CONNECTED)); /* p may have been freed, so don't use it * anymore in this function */ p = NULL; } } } #ifdef _WIN32 if (revents & POLLOUT || revents & POLLWRNORM) { #else if (revents & POLLOUT) { #endif /* First, POLLOUT is a sign we may be connected */ if (s->state == SSH_SOCKET_CONNECTING) { SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state"); s->state = SSH_SOCKET_CONNECTED; if (p != NULL) { ssh_poll_set_events(p, POLLOUT | POLLIN); } r = ssh_socket_set_blocking(ssh_socket_get_fd_in(s)); if (r < 0) { return -1; } if (s->callbacks && s->callbacks->connected) { s->callbacks->connected(SSH_SOCKET_CONNECTED_OK, 0, s->callbacks->userdata); } return 0; } /* So, we can write data */ s->write_wontblock=1; if (p != NULL) { ssh_poll_remove_events(p, POLLOUT); } /* If buffered data is pending, write it */ if (ssh_buffer_get_len(s->out_buffer) > 0) { ssh_socket_nonblocking_flush(s); } else if (s->callbacks && s->callbacks->controlflow) { /* Otherwise advertise the upper level that write can be done */ SSH_LOG(SSH_LOG_TRACE,"sending control flow event"); s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK, s->callbacks->userdata); } /* TODO: Find a way to put back POLLOUT when buffering occurs */ } /* Return -1 if one of the poll handlers disappeared */ return (s->poll_in == NULL || s->poll_out == NULL) ? -1 : 0; } /** @internal * @brief returns the input poll handle corresponding to the socket, * creates it if it does not exist. * @returns allocated and initialized ssh_poll_handle object */ ssh_poll_handle ssh_socket_get_poll_handle_in(ssh_socket s){ if(s->poll_in) return s->poll_in; s->poll_in=ssh_poll_new(s->fd_in,0,ssh_socket_pollcallback,s); if(s->fd_in == s->fd_out && s->poll_out == NULL) s->poll_out=s->poll_in; return s->poll_in; } /** @internal * @brief returns the output poll handle corresponding to the socket, * creates it if it does not exist. * @returns allocated and initialized ssh_poll_handle object */ ssh_poll_handle ssh_socket_get_poll_handle_out(ssh_socket s){ if(s->poll_out) return s->poll_out; s->poll_out=ssh_poll_new(s->fd_out,0,ssh_socket_pollcallback,s); if(s->fd_in == s->fd_out && s->poll_in == NULL) s->poll_in=s->poll_out; return s->poll_out; } /** \internal * \brief Deletes a socket object */ void ssh_socket_free(ssh_socket s){ if (s == NULL) { return; } ssh_socket_close(s); ssh_buffer_free(s->in_buffer); ssh_buffer_free(s->out_buffer); SAFE_FREE(s); } #ifndef _WIN32 int ssh_socket_unix(ssh_socket s, const char *path) { struct sockaddr_un sunaddr; socket_t fd; sunaddr.sun_family = AF_UNIX; snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == SSH_INVALID_SOCKET) { ssh_set_error(s->session, SSH_FATAL, "Error from socket(AF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); return -1; } if (fcntl(fd, F_SETFD, 1) == -1) { ssh_set_error(s->session, SSH_FATAL, "Error from fcntl(fd, F_SETFD, 1): %s", strerror(errno)); close(fd); return -1; } if (connect(fd, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s", strerror(errno)); close(fd); return -1; } ssh_socket_set_fd(s,fd); return 0; } #endif /** \internal * \brief closes a socket */ void ssh_socket_close(ssh_socket s){ if (ssh_socket_is_open(s)) { #ifdef _WIN32 CLOSE_SOCKET(s->fd_in); /* fd_in = fd_out under win32 */ s->last_errno = WSAGetLastError(); #else if (s->fd_out != s->fd_in && s->fd_out != -1) { CLOSE_SOCKET(s->fd_out); } CLOSE_SOCKET(s->fd_in); s->last_errno = errno; #endif } if(s->poll_in != NULL){ if(s->poll_out == s->poll_in) s->poll_out = NULL; ssh_poll_free(s->poll_in); s->poll_in=NULL; } if(s->poll_out != NULL){ ssh_poll_free(s->poll_out); s->poll_out=NULL; } s->state = SSH_SOCKET_CLOSED; } /** * @internal * @brief sets the file descriptor of the socket. * @param[out] s ssh_socket to update * @param[in] fd file descriptor to set * @warning this function updates boths the input and output * file descriptors */ void ssh_socket_set_fd(ssh_socket s, socket_t fd) { s->fd_in = s->fd_out = fd; if (s->poll_in) { ssh_poll_set_fd(s->poll_in,fd); } else { s->state = SSH_SOCKET_CONNECTING; /* POLLOUT is the event to wait for in a nonblocking connect */ ssh_poll_set_events(ssh_socket_get_poll_handle_in(s), POLLOUT); #ifdef _WIN32 ssh_poll_add_events(ssh_socket_get_poll_handle_in(s), POLLWRNORM); #endif } }
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind) { SSH_SESSION *session; PRIVATE_KEY *dsa = NULL; PRIVATE_KEY *rsa = NULL; int fd = -1; if (ssh_bind->bindfd < 0) { ssh_set_error(ssh_bind, SSH_FATAL, "Can't accept new clients on a not bound socket."); return NULL; } if (ssh_bind->options->dsakey == NULL || ssh_bind->options->rsakey == NULL) { ssh_set_error(ssh_bind, SSH_FATAL, "DSA or RSA host key file must be set before accept()"); return NULL; } if (ssh_bind->options->dsakey) { dsa = _privatekey_from_file(ssh_bind, ssh_bind->options->dsakey, TYPE_DSS); if (dsa == NULL) { return NULL; } } if (ssh_bind->options->rsakey) { rsa = _privatekey_from_file(ssh_bind, ssh_bind->options->rsakey, TYPE_RSA); if (rsa == NULL) { privatekey_free(dsa); return NULL; } } fd = accept(ssh_bind->bindfd, NULL, NULL); if (fd < 0) { ssh_set_error(ssh_bind, SSH_FATAL, "Accepting a new connection: %s", strerror(errno)); privatekey_free(dsa); privatekey_free(rsa); return NULL; } session = ssh_new(); if (session == NULL) { ssh_set_error(ssh_bind, SSH_FATAL, "Not enough space"); privatekey_free(dsa); privatekey_free(rsa); return NULL; } session->server = 1; session->version = 2; session->options = ssh_options_copy(ssh_bind->options); if (session->options == NULL) { ssh_set_error(ssh_bind, SSH_FATAL, "No space left"); privatekey_free(dsa); privatekey_free(rsa); ssh_cleanup(session); return NULL; } ssh_socket_free(session->socket); session->socket = ssh_socket_new(session); if (session->socket == NULL) { privatekey_free(dsa); privatekey_free(rsa); ssh_cleanup(session); return NULL; } ssh_socket_set_fd(session->socket,fd); session->dsa_key = dsa; session->rsa_key = rsa; return session; }
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) { socket_t fd = SSH_INVALID_SOCKET; int i; if (sshbind->bindfd == SSH_INVALID_SOCKET) { ssh_set_error(sshbind, SSH_FATAL, "Can't accept new clients on a not bound socket."); return SSH_ERROR; } if(session == NULL){ ssh_set_error(sshbind, SSH_FATAL,"session is null"); return SSH_ERROR; } fd = accept(sshbind->bindfd, NULL, NULL); if (fd == SSH_INVALID_SOCKET) { ssh_set_error(sshbind, SSH_FATAL, "Accepting a new connection: %s", strerror(errno)); return SSH_ERROR; } session->server = 1; session->version = 2; /* copy options */ for (i = 0; i < 10; ++i) { if (sshbind->wanted_methods[i]) { session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]); if (session->wanted_methods[i] == NULL) { return SSH_ERROR; } } } if (sshbind->bindaddr == NULL) session->bindaddr = NULL; else { SAFE_FREE(session->bindaddr); session->bindaddr = strdup(sshbind->bindaddr); if (session->bindaddr == NULL) { return SSH_ERROR; } } session->log_verbosity = sshbind->log_verbosity; ssh_socket_free(session->socket); session->socket = ssh_socket_new(session); if (session->socket == NULL) { /* perhaps it may be better to copy the error from session to sshbind */ ssh_set_error_oom(sshbind); return SSH_ERROR; } ssh_socket_set_fd(session->socket, fd); ssh_socket_get_poll_handle_out(session->socket); session->dsa_key = sshbind->dsa; session->rsa_key = sshbind->rsa; return SSH_OK; }