Example #1
3
/**
 * @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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
/**
 * @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;
}
Example #7
0
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;
}
Example #8
0
/**
 * @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
    }
}
Example #9
0
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;
}
Example #10
0
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;
}