Beispiel #1
0
static int ssh_server_send_extensions(ssh_session session) {
    int rc;
    const char *hostkey_algorithms;

    SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO");
    /*
     * We can list here all the default hostkey methods, since
     * they already contain the SHA2 extension algorithms
     */
    hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS);
    rc = ssh_buffer_pack(session->out_buffer,
                         "bdss",
                         SSH2_MSG_EXT_INFO,
                         1, /* nr. of extensions */
                         "server-sig-algs",
                         hostkey_algorithms);
    if (rc != SSH_OK) {
        goto error;
    }

    if (ssh_packet_send(session) == SSH_ERROR) {
        goto error;
    }

    return 0;
error:
    ssh_buffer_reinit(session->out_buffer);

    return -1;
}
Beispiel #2
0
static int ssh_message_channel_request_reply_default(ssh_message msg) {
  uint32_t channel;
  int rc;

  if (msg->channel_request.want_reply) {
    channel = msg->channel_request.channel->remote_channel;

    SSH_LOG(SSH_LOG_PACKET,
        "Sending a default channel_request denied to channel %d", channel);

    rc = ssh_buffer_pack(msg->session->out_buffer,
                         "bd",
                         SSH2_MSG_CHANNEL_FAILURE,
                         channel);
    if (rc != SSH_OK){
        ssh_set_error_oom(msg->session);
        return SSH_ERROR;
    }
    return ssh_packet_send(msg->session);
  }

  SSH_LOG(SSH_LOG_PACKET,
      "The client doesn't want to know the request failed!");

  return SSH_OK;
}
Beispiel #3
0
int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port) {
    int rc;

    SSH_LOG(SSH_LOG_FUNCTIONS, "Accepting a global request");

    if (msg->global_request.want_reply) {
        if (ssh_buffer_add_u8(msg->session->out_buffer
                    , SSH2_MSG_REQUEST_SUCCESS) < 0) {
            goto error;
        }

        if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD 
                                && msg->global_request.bind_port == 0) {
            rc = ssh_buffer_pack(msg->session->out_buffer, "d", bound_port);
            if (rc != SSH_OK) {
                ssh_set_error_oom(msg->session);
                goto error;
            }
        }

        return ssh_packet_send(msg->session);
    }

    if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD 
                                && msg->global_request.bind_port == 0) {
        SSH_LOG(SSH_LOG_PACKET,
                "The client doesn't want to know the remote port!");
    }

    return SSH_OK;
error:
    return SSH_ERROR;
}
Beispiel #4
0
int ssh_auth_reply_success(ssh_session session, int partial) {
  int r;

  if (session == NULL) {
	  return SSH_ERROR;
  }

  if (partial) {
    return ssh_auth_reply_default(session, partial);
  }
  
  session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
  session->flags |= SSH_SESSION_FLAG_AUTHENTICATED;

  if (ssh_buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS) < 0) {
    return SSH_ERROR;
  }

  r = ssh_packet_send(session);
  if(session->current_crypto && session->current_crypto->delayed_compress_out){
      SSH_LOG(SSH_LOG_PROTOCOL,"Enabling delayed compression OUT");
  	session->current_crypto->do_compress_out=1;
  }
  if(session->current_crypto && session->current_crypto->delayed_compress_in){
      SSH_LOG(SSH_LOG_PROTOCOL,"Enabling delayed compression IN");
  	session->current_crypto->do_compress_in=1;
  }
  return r;
}
Beispiel #5
0
int ssh_send_keepalive(ssh_session session)
{
  int rc;

  rc = ssh_buffer_pack(session->out_buffer,
                       "bsb",
                       SSH2_MSG_GLOBAL_REQUEST,
                       "*****@*****.**",
                       1);
  if (rc != SSH_OK) {
    goto err;
  }

  if (ssh_packet_send(session) == SSH_ERROR) {
    goto err;
  }

  ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING);

  SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive");
  return SSH_OK;

err:
  ssh_set_error_oom(session);
  ssh_buffer_reinit(session->out_buffer);
  return SSH_ERROR;
}
Beispiel #6
0
/* this function only sends the predefined set of kex methods */
int ssh_send_kex(ssh_session session, int server_kex) {
  struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex :
      &session->next_crypto->client_kex);
  ssh_string str = NULL;
  int i;
  int rc;

  rc = ssh_buffer_pack(session->out_buffer,
                       "bP",
                       SSH2_MSG_KEXINIT,
                       16,
                       kex->cookie); /* cookie */
  if (rc != SSH_OK)
    goto error;
  if (ssh_hashbufout_add_cookie(session) < 0) {
    goto error;
  }

  ssh_list_kex(kex);

  for (i = 0; i < KEX_METHODS_SIZE; i++) {
    str = ssh_string_from_char(kex->methods[i]);
    if (str == NULL) {
      goto error;
    }

    if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) {
      goto error;
    }
    if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) {
      goto error;
    }
    ssh_string_free(str);
    str = NULL;
  }

  rc = ssh_buffer_pack(session->out_buffer,
                       "bd",
                       0,
                       0);
  if (rc != SSH_OK) {
    goto error;
  }

  if (ssh_packet_send(session) == SSH_ERROR) {
    return -1;
  }

  SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent");
  return 0;
error:
  ssh_buffer_reinit(session->out_buffer);
  ssh_buffer_reinit(session->out_hashbuf);
  ssh_string_free(str);

  return -1;
}
Beispiel #7
0
/** @internal
 * @brief Starts ecdh-sha2-nistp256 key exchange
 */
int ssh_client_ecdh_init(ssh_session session){
  EC_KEY *key;
  const EC_GROUP *group;
  const EC_POINT *pubkey;
  ssh_string client_pubkey;
  int len;
  int rc;
  bignum_CTX ctx = BN_CTX_new();

  rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT);
  if (rc < 0) {
      BN_CTX_free(ctx);
      return SSH_ERROR;
  }

  key = EC_KEY_new_by_curve_name(NISTP256);
  if (key == NULL) {
      BN_CTX_free(ctx);
      return SSH_ERROR;
  }
  group = EC_KEY_get0_group(key);

  EC_KEY_generate_key(key);

  pubkey=EC_KEY_get0_public_key(key);
  len = EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
      NULL,0,ctx);

  client_pubkey = ssh_string_new(len);
  if (client_pubkey == NULL) {
      BN_CTX_free(ctx);
      EC_KEY_free(key);
      return SSH_ERROR;
  }

  EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
      ssh_string_data(client_pubkey),len,ctx);
  BN_CTX_free(ctx);

  rc = ssh_buffer_add_ssh_string(session->out_buffer,client_pubkey);
  if (rc < 0) {
      EC_KEY_free(key);
      ssh_string_free(client_pubkey);
      return SSH_ERROR;
  }

  session->next_crypto->ecdh_privkey = key;
  session->next_crypto->ecdh_client_pubkey = client_pubkey;

  rc = ssh_packet_send(session);

  return rc;
}
Beispiel #8
0
/** @internal
 * @brief sends a SSH_MSG_USERAUTH_GSSAPI_RESPONSE packet
 * @param[in] oid the OID that was selected for authentication
 */
static int ssh_gssapi_send_response(ssh_session session, ssh_string oid){
    if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE) < 0 ||
            ssh_buffer_add_ssh_string(session->out_buffer,oid) < 0) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN;

    ssh_packet_send(session);
    SSH_LOG(SSH_LOG_PACKET,
            "Sent SSH_MSG_USERAUTH_GSSAPI_RESPONSE");
    return SSH_OK;
}
Beispiel #9
0
/** @internal
 * replies to an SSH_AUTH packet with a default (denied) response.
 */
int ssh_auth_reply_default(ssh_session session,int partial) {
  char methods_c[128] = {0};
  int rc = SSH_ERROR;


  if (session->auth_methods == 0) {
    session->auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD;
  }
  if (session->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
    strncat(methods_c, "publickey,",
            sizeof(methods_c) - strlen(methods_c) - 1);
  }
  if (session->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC){
	  strncat(methods_c,"gssapi-with-mic,",
			  sizeof(methods_c) - strlen(methods_c) - 1);
  }
  if (session->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
    strncat(methods_c, "keyboard-interactive,",
            sizeof(methods_c) - strlen(methods_c) - 1);
  }
  if (session->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
    strncat(methods_c, "password,",
            sizeof(methods_c) - strlen(methods_c) - 1);
  }
  if (session->auth_methods & SSH_AUTH_METHOD_HOSTBASED) {
    strncat(methods_c, "hostbased,",
            sizeof(methods_c) - strlen(methods_c) - 1);
  }

  if (methods_c[0] == '\0' || methods_c[strlen(methods_c)-1] != ',') {
      return SSH_ERROR;
  }

  /* Strip the comma. */
  methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at

  SSH_LOG(SSH_LOG_PACKET,
      "Sending a auth failure. methods that can continue: %s", methods_c);

  rc = ssh_buffer_pack(session->out_buffer,
                       "bsb",
                       SSH2_MSG_USERAUTH_FAILURE,
                       methods_c,
                       partial ? 1 : 0);
  if (rc != SSH_OK){
      ssh_set_error_oom(session);
      return SSH_ERROR;
  }
  rc = ssh_packet_send(session);
  return rc;
}
Beispiel #10
0
/** @internal
 * @brief sends a SSH_MSG_UNIMPLEMENTED answer to an unhandled packet
 * @param session the SSH session
 * @param seqnum the sequence number of the unknown packet
 * @return SSH_ERROR on error, else SSH_OK
 */
int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum){
    int rc;

    rc = ssh_buffer_pack(session->out_buffer,
                         "bd",
                         SSH2_MSG_UNIMPLEMENTED,
                         seqnum);
    if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    rc = ssh_packet_send(session);

    return rc;
}
Beispiel #11
0
/**
 * @internal
 *
 * @brief Request a service from the SSH server.
 *
 * Service requests are for example: ssh-userauth, ssh-connection, etc.
 *
 * @param  session      The session to use to ask for a service request.
 * @param  service      The service request.
 *
 * @return SSH_OK on success
 * @return SSH_ERROR on error
 * @return SSH_AGAIN No response received yet
 * @bug actually only works with ssh-userauth
 */
int ssh_service_request(ssh_session session, const char *service) {
  int rc=SSH_ERROR;

  if(session->auth_service_state != SSH_AUTH_SERVICE_NONE)
    goto pending;

  rc = ssh_buffer_pack(session->out_buffer,
                       "bs",
                       SSH2_MSG_SERVICE_REQUEST,
                       service);
  if (rc != SSH_OK){
      ssh_set_error_oom(session);
      return SSH_ERROR;
  }
  session->auth_service_state=SSH_AUTH_SERVICE_SENT;
  if (ssh_packet_send(session) == SSH_ERROR) {
    ssh_set_error(session, SSH_FATAL,
        "Sending SSH2_MSG_SERVICE_REQUEST failed.");
      return SSH_ERROR;
  }

  SSH_LOG(SSH_LOG_PACKET,
      "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service);
pending:
  rc=ssh_handle_packets_termination(session,SSH_TIMEOUT_USER,
      ssh_service_request_termination, session);
  if (rc == SSH_ERROR) {
      return SSH_ERROR;
  }
  switch(session->auth_service_state){
  case SSH_AUTH_SERVICE_DENIED:
    ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied");
    break;
  case SSH_AUTH_SERVICE_ACCEPTED:
    rc=SSH_OK;
    break;
  case SSH_AUTH_SERVICE_SENT:
    rc=SSH_AGAIN;
    break;
  case SSH_AUTH_SERVICE_NONE:
  case SSH_AUTH_SERVICE_USER_SENT:
    /* Invalid state, SSH1 specific */
    rc=SSH_ERROR;
    break;
  }

  return rc;
}
Beispiel #12
0
static int ssh_message_global_request_reply_default(ssh_message msg) {
    SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a global request");

    if (msg->global_request.want_reply) {
        if (ssh_buffer_add_u8(msg->session->out_buffer
                    , SSH2_MSG_REQUEST_FAILURE) < 0) {
            goto error;
        }
        return ssh_packet_send(msg->session);
    }
    SSH_LOG(SSH_LOG_PACKET,
            "The client doesn't want to know the request failed!");

    return SSH_OK;
error:
    return SSH_ERROR;
}
Beispiel #13
0
/* Answer OK to a pubkey auth request */
int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey) {
    int rc;
    if (msg == NULL) {
        return SSH_ERROR;
    }

    rc = ssh_buffer_pack(msg->session->out_buffer,
                         "bSS",
                         SSH2_MSG_USERAUTH_PK_OK,
                         algo,
                         pubkey);
    if(rc != SSH_OK){
        ssh_set_error_oom(msg->session);
        return SSH_ERROR;
    }

    rc = ssh_packet_send(msg->session);
    return rc;
}
Beispiel #14
0
/** @internal
 * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
 * a SSH_MSG_NEWKEYS
 */
int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet){
  ssh_string q_s_string = NULL;
  ssh_string pubkey = NULL;
  ssh_string signature = NULL;
  int rc;
  pubkey = ssh_buffer_get_ssh_string(packet);
  if (pubkey == NULL){
    ssh_set_error(session,SSH_FATAL, "No public key in packet");
    goto error;
  }
  ecdh_import_pubkey(session, pubkey);

  q_s_string = ssh_buffer_get_ssh_string(packet);
  if (q_s_string == NULL) {
    ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
    goto error;
  }
  session->next_crypto->ecdh_server_pubkey = q_s_string;
  signature = ssh_buffer_get_ssh_string(packet);
  if (signature == NULL) {
    ssh_set_error(session, SSH_FATAL, "No signature in packet");
    goto error;
  }
  session->next_crypto->dh_server_signature = signature;
  signature=NULL; /* ownership changed */
  /* TODO: verify signature now instead of waiting for NEWKEYS */
  if (ecdh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Cannot build k number");
    goto error;
  }

  /* Send the MSG_NEWKEYS */
  if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    goto error;
  }

  rc=ssh_packet_send(session);
  SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
  return rc;
error:
  return SSH_ERROR;
}
Beispiel #15
0
int ssh_auth_reply_success(ssh_session session, int partial)
{
    struct ssh_crypto_struct *crypto = NULL;
    int r;

    if (session == NULL) {
        return SSH_ERROR;
    }

    if (partial) {
        return ssh_auth_reply_default(session, partial);
    }

    r = ssh_buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS);
    if (r < 0) {
        return SSH_ERROR;
    }

    r = ssh_packet_send(session);

    /*
     * Consider the session as having been authenticated only after sending
     * the USERAUTH_SUCCESS message.  Setting these flags after ssh_packet_send
     * ensures that a rekey is not triggered prematurely, causing the message
     * to be queued.
     */
    session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
    session->flags |= SSH_SESSION_FLAG_AUTHENTICATED;

    crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT);
    if (crypto != NULL && crypto->delayed_compress_out) {
        SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression OUT");
        crypto->do_compress_out = 1;
    }

    crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
    if (crypto != NULL && crypto->delayed_compress_in) {
        SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression IN");
        crypto->do_compress_in = 1;
    }
    return r;
}
Beispiel #16
0
static int ssh_message_channel_request_open_reply_default(ssh_message msg) {
    int rc;

    SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a channel");

    rc = ssh_buffer_pack(msg->session->out_buffer,
                         "bdddd",
                         SSH2_MSG_CHANNEL_OPEN_FAILURE,
                         msg->channel_request_open.sender,
                         SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
                         0,    /* reason is empty string */
                         0);   /* language string */
    if (rc != SSH_OK){
        ssh_set_error_oom(msg->session);
        return SSH_ERROR;
    }

    rc = ssh_packet_send(msg->session);
    return rc;
}
Beispiel #17
0
int ssh_message_service_reply_success(ssh_message msg) {
    ssh_session session;
    int rc;

    if (msg == NULL) {
        return SSH_ERROR;
    }
    session = msg->session;

    SSH_LOG(SSH_LOG_PACKET,
            "Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);

    rc = ssh_buffer_pack(session->out_buffer,
                         "bs",
                         SSH2_MSG_SERVICE_ACCEPT,
                         msg->service_request.service);
    if (rc != SSH_OK){
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    rc = ssh_packet_send(msg->session);
    return rc;
}
Beispiel #18
0
static int dh_handshake_server(ssh_session session) {
  ssh_key privkey;
  ssh_string sig_blob;
  ssh_string f;
  ssh_string pubkey_blob = NULL;
  int rc;

  if (ssh_dh_generate_y(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create y number");
    return -1;
  }
  if (ssh_dh_generate_f(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create f number");
    return -1;
  }

  f = ssh_dh_get_f(session);
  if (f == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not get the f number");
    return -1;
  }

  if (ssh_get_key_params(session,&privkey) != SSH_OK){
      ssh_string_free(f);
      return -1;
  }

  if (ssh_dh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not import the public key");
    ssh_string_free(f);
    return -1;
  }

  if (ssh_make_sessionid(session) != SSH_OK) {
    ssh_set_error(session, SSH_FATAL, "Could not create a session id");
    ssh_string_free(f);
    return -1;
  }

  sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
  if (sig_blob == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
    ssh_string_free(f);
    return -1;
  }

  rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob);
  if (rc != SSH_OK) {
      ssh_set_error_oom(session);
      ssh_string_free(f);
      ssh_string_free(sig_blob);
      return -1;
  }

  rc = ssh_buffer_pack(session->out_buffer,
                       "bSSS",
                       SSH2_MSG_KEXDH_REPLY,
                       pubkey_blob,
                       f,
                       sig_blob);
  ssh_string_free(f);
  ssh_string_free(sig_blob);
  ssh_string_free(pubkey_blob);
  if(rc != SSH_OK){
    ssh_set_error_oom(session);
    ssh_buffer_reinit(session->out_buffer);
    return -1;
  }

  if (ssh_packet_send(session) == SSH_ERROR) {
    return -1;
  }

  if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    ssh_buffer_reinit(session->out_buffer);
    return -1;
  }

  if (ssh_packet_send(session) == SSH_ERROR) {
    return -1;
  }
  SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
  session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;

  return 0;
}
Beispiel #19
0
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
    /* ECDH keys */
    ssh_string q_c_string;
    ssh_string q_s_string;
    EC_KEY *ecdh_key;
    const EC_GROUP *group;
    const EC_POINT *ecdh_pubkey;
    bignum_CTX ctx;
    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key privkey;
    ssh_string sig_blob = NULL;
    int len;
    int rc;

    /* Extract the client pubkey from the init packet */
    q_c_string = ssh_buffer_get_ssh_string(packet);
    if (q_c_string == NULL) {
        ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
        return SSH_ERROR;
    }
    session->next_crypto->ecdh_client_pubkey = q_c_string;

    /* Build server's keypair */

    ctx = BN_CTX_new();
    ecdh_key = EC_KEY_new_by_curve_name(NISTP256);
    if (ecdh_key == NULL) {
        ssh_set_error_oom(session);
        BN_CTX_free(ctx);
        return SSH_ERROR;
    }

    group = EC_KEY_get0_group(ecdh_key);
    EC_KEY_generate_key(ecdh_key);

    ecdh_pubkey = EC_KEY_get0_public_key(ecdh_key);
    len = EC_POINT_point2oct(group,
                             ecdh_pubkey,
                             POINT_CONVERSION_UNCOMPRESSED,
                             NULL,
                             0,
                             ctx);

    q_s_string = ssh_string_new(len);
    if (q_s_string == NULL) {
        EC_KEY_free(ecdh_key);
        BN_CTX_free(ctx);
        return SSH_ERROR;
    }

    EC_POINT_point2oct(group,
                       ecdh_pubkey,
                       POINT_CONVERSION_UNCOMPRESSED,
                       ssh_string_data(q_s_string),
                       len,
                       ctx);
    BN_CTX_free(ctx);

    session->next_crypto->ecdh_privkey = ecdh_key;
    session->next_crypto->ecdh_server_pubkey = q_s_string;

    /* build k and session_id */
    rc = ecdh_build_k(session);
    if (rc < 0) {
        ssh_set_error(session, SSH_FATAL, "Cannot build k number");
        return SSH_ERROR;
    }

    /* privkey is not allocated */
    rc = ssh_get_key_params(session, &privkey);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    rc = ssh_make_sessionid(session);
    if (rc != SSH_OK) {
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
        return SSH_ERROR;
    }

    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
    if (sig_blob == NULL) {
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
        return SSH_ERROR;
    }

    rc = ssh_buffer_pack(session->out_buffer,
                         "bSSS",
                         SSH2_MSG_KEXDH_REPLY,
                         session->next_crypto->server_pubkey, /* host's pubkey */
                         q_s_string, /* ecdh public key */
                         sig_blob); /* signature blob */

    ssh_string_free(sig_blob);

    if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent");
    rc = ssh_packet_send(session);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    /* Send the MSG_NEWKEYS */
    rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
    if (rc < 0) {
        return SSH_ERROR;;
    }

    session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
    rc = ssh_packet_send(session);
    SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");

    return rc;
}
Beispiel #20
0
int ssh_message_auth_interactive_request(ssh_message msg, const char *name,
                            const char *instruction, unsigned int num_prompts,
                            const char **prompts, char *echo) {
  int rc;
  unsigned int i = 0;

  if(name == NULL || instruction == NULL) {
    return SSH_ERROR;
  }
  if(num_prompts > 0 && (prompts == NULL || echo == NULL)) {
    return SSH_ERROR;
  }

  rc = ssh_buffer_pack(msg->session->out_buffer,
                       "bsssd",
                       SSH2_MSG_USERAUTH_INFO_REQUEST,
                       name,
                       instruction,
                       "",           /* language tag */
                       num_prompts);
  if (rc != SSH_OK){
    ssh_set_error_oom(msg->session);
    return SSH_ERROR;
  }

  for(i = 0; i < num_prompts; i++) {
    rc = ssh_buffer_pack(msg->session->out_buffer,
                         "sb",
                         prompts[i],
                         echo[i] ? 1 : 0);
    if (rc != SSH_OK){
        ssh_set_error_oom(msg->session);
        return SSH_ERROR;
    }
  }

  rc = ssh_packet_send(msg->session);

  /* fill in the kbdint structure */
  if (msg->session->kbdint == NULL) {
    SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a "
                                        "keyboard-interactive response but it "
                                        "seems we didn't send the request.");

    msg->session->kbdint = ssh_kbdint_new();
    if (msg->session->kbdint == NULL) {
      ssh_set_error_oom(msg->session);

      return SSH_ERROR;
    }
  } else {
    ssh_kbdint_clean(msg->session->kbdint);
  }

  msg->session->kbdint->name = strdup(name);
  if(msg->session->kbdint->name == NULL) {
      ssh_set_error_oom(msg->session);
      ssh_kbdint_free(msg->session->kbdint);
      msg->session->kbdint = NULL;
      return SSH_PACKET_USED;
  }
  msg->session->kbdint->instruction = strdup(instruction);
  if(msg->session->kbdint->instruction == NULL) {
      ssh_set_error_oom(msg->session);
      ssh_kbdint_free(msg->session->kbdint);
      msg->session->kbdint = NULL;
      return SSH_PACKET_USED;
  }

  msg->session->kbdint->nprompts = num_prompts;
  if(num_prompts > 0) {
    msg->session->kbdint->prompts = calloc(num_prompts, sizeof(char *));
    if (msg->session->kbdint->prompts == NULL) {
      msg->session->kbdint->nprompts = 0;
      ssh_set_error_oom(msg->session);
      ssh_kbdint_free(msg->session->kbdint);
      msg->session->kbdint = NULL;
      return SSH_ERROR;
    }
    msg->session->kbdint->echo = calloc(num_prompts, sizeof(unsigned char));
    if (msg->session->kbdint->echo == NULL) {
      ssh_set_error_oom(msg->session);
      ssh_kbdint_free(msg->session->kbdint);
      msg->session->kbdint = NULL;
      return SSH_ERROR;
    }
    for (i = 0; i < num_prompts; i++) {
      msg->session->kbdint->echo[i] = echo[i];
      msg->session->kbdint->prompts[i] = strdup(prompts[i]);
      if (msg->session->kbdint->prompts[i] == NULL) {
        ssh_set_error_oom(msg->session);
        msg->session->kbdint->nprompts = i;
        ssh_kbdint_free(msg->session->kbdint);
        msg->session->kbdint = NULL;
        return SSH_PACKET_USED;
      }
    }
  } else {
    msg->session->kbdint->prompts = NULL;
    msg->session->kbdint->echo = NULL;
  }

  return rc;
}
Beispiel #21
0
/**
 * @brief Disconnect from a session (client or server).
 * The session can then be reused to open a new session.
 *
 * @param[in]  session  The SSH session to use.
 */
void ssh_disconnect(ssh_session session) {
  struct ssh_iterator *it;
  int rc;

  if (session == NULL) {
    return;
  }

  if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
    rc = ssh_buffer_pack(session->out_buffer,
                         "bds",
                         SSH2_MSG_DISCONNECT,
                         SSH2_DISCONNECT_BY_APPLICATION,
                         "Bye Bye");
    if (rc != SSH_OK){
      ssh_set_error_oom(session);
      goto error;
    }

    ssh_packet_send(session);
    ssh_socket_close(session->socket);
  }
error:
  session->alive = 0;
  if (session->socket != NULL){
    ssh_socket_reset(session->socket);
  }
  session->opts.fd = SSH_INVALID_SOCKET;
  session->session_state=SSH_SESSION_STATE_DISCONNECTED;

  while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
    ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
    ssh_list_remove(session->channels, it);
  }
  if(session->current_crypto){
    crypto_free(session->current_crypto);
    session->current_crypto=NULL;
  }
  if (session->in_buffer) {
    ssh_buffer_reinit(session->in_buffer);
  }
  if (session->out_buffer) {
    ssh_buffer_reinit(session->out_buffer);
  }
  if (session->in_hashbuf) {
    ssh_buffer_reinit(session->in_hashbuf);
  }
  if (session->out_hashbuf) {
    ssh_buffer_reinit(session->out_hashbuf);
  }
  session->auth_methods = 0;
  SAFE_FREE(session->serverbanner);
  SAFE_FREE(session->clientbanner);

  if(session->ssh_message_list){
    ssh_message msg;
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
        != NULL){
      ssh_message_free(msg);
    }
    ssh_list_free(session->ssh_message_list);
    session->ssh_message_list=NULL;
  }

  if (session->packet_callbacks){
    ssh_list_free(session->packet_callbacks);
    session->packet_callbacks=NULL;
  }
}
Beispiel #22
0
static int send_username(ssh_session session, const char *username) {
  ssh_string user = NULL;
  int rc;
  /* 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 (session->auth_service_state == SSH_AUTH_SERVICE_SENT)
      goto pending;
  if (!username) {
    if(!(username = session->opts.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->opts.username;
      }
    }
  }
  user = ssh_string_from_char(username);
  if (user == NULL) {
    return SSH_AUTH_ERROR;
  }

  if (ssh_buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) {
    ssh_string_free(user);
    return SSH_AUTH_ERROR;
  }
  if (ssh_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;
  session->auth_service_state = SSH_AUTH_SERVICE_SENT;
  if (ssh_packet_send(session) == SSH_ERROR) {
    return SSH_AUTH_ERROR;
  }
pending:
  rc = wait_auth1_status(session);
  switch (rc){
  case SSH_AUTH_SUCCESS:
    session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
    session->auth_state=SSH_AUTH_STATE_SUCCESS;
    ssh_set_error(session, SSH_NO_ERROR, "Authentication successful");
    return SSH_AUTH_SUCCESS;
  case SSH_AUTH_DENIED:
    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;
  case SSH_AUTH_AGAIN:
    return SSH_AUTH_AGAIN;
  default:
    session->auth_service_state = SSH_AUTH_SERVICE_NONE;
    session->auth_state=SSH_AUTH_STATE_ERROR;
    return SSH_AUTH_ERROR;
  }
}
Beispiel #23
0
int ssh_userauth1_password(ssh_session session, const char *username,
    const char *password) {
  ssh_string pwd = NULL;
  int rc;

  rc = send_username(session, username);
  if (rc != SSH_AUTH_DENIED) {
    return rc;
  }
  if (session->pending_call_state == SSH_PENDING_CALL_AUTH_PASSWORD)
      goto pending;
  /* we trick a bit here. A known flaw in SSH1 protocol is that it's
   * easy to guess password sizes.
   * not that sure ...
   */

  /* XXX fix me here ! */
  /* cisco IOS doesn't like when a password is followed by zeroes and random pad. */
  if(1 || strlen(password) >= 128) {
    /* not risky to disclose the size of such a big password .. */
    pwd = ssh_string_from_char(password);
    if (pwd == NULL) {
      return SSH_AUTH_ERROR;
    }
  } else {
    char buf[128] = {0};
    /* fill the password string from random things. the strcpy
     * ensure there is at least a nul byte after the password.
     * most implementation won't see the garbage at end.
     * why garbage ? because nul bytes will be compressed by
     * gzip and disclose password len.
     */
    pwd = ssh_string_new(sizeof(buf));
    if (pwd == NULL) {
      return SSH_AUTH_ERROR;
    }
    ssh_get_random(buf, sizeof(buf), 0);
    strcpy(buf, password);
    ssh_string_fill(pwd, buf, sizeof(buf));
  }

  if (ssh_buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) {
    ssh_string_burn(pwd);
    ssh_string_free(pwd);

    return SSH_AUTH_ERROR;
  }
  if (ssh_buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
    ssh_string_burn(pwd);
    ssh_string_free(pwd);

    return SSH_AUTH_ERROR;
  }

  ssh_string_burn(pwd);
  ssh_string_free(pwd);
  session->auth_state=SSH_AUTH_STATE_NONE;
  session->pending_call_state = SSH_PENDING_CALL_AUTH_PASSWORD;
  if (ssh_packet_send(session) == SSH_ERROR) {
    return SSH_AUTH_ERROR;
  }
pending:
  rc = wait_auth1_status(session);
  if (rc != SSH_AUTH_AGAIN)
      session->pending_call_state = SSH_PENDING_CALL_NONE;

  return rc;
}