Ejemplo n.º 1
0
Archivo: kex.c Proyecto: simonsj/libssh
/* 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;
}
Ejemplo n.º 2
0
static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid){
    int rc;
    int i;

    rc = ssh_buffer_pack(session->out_buffer,
                         "bsssd",
                         SSH2_MSG_USERAUTH_REQUEST,
                         session->opts.username,
                         "ssh-connection",
                         "gssapi-with-mic",
                         n_oid);

    if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        goto fail;
    }

    for (i=0; i<n_oid; ++i){
        rc = buffer_add_ssh_string(session->out_buffer, oid_set[i]);
        if (rc < 0) {
            goto fail;
        }
    }

    session->auth_state = SSH_AUTH_STATE_GSSAPI_REQUEST_SENT;
    return packet_send(session);
fail:
    ssh_buffer_reinit(session->out_buffer);
    return SSH_ERROR;
}
Ejemplo n.º 3
0
static ssh_buffer ssh_gssapi_build_mic(ssh_session session){
    ssh_buffer mic_buffer;
    int rc;

    mic_buffer = ssh_buffer_new();
    if (mic_buffer == NULL) {
        ssh_set_error_oom(session);
        return NULL;
    }

    rc = ssh_buffer_pack(mic_buffer,
                         "dPbsss",
                         session->current_crypto->digest_len,
                         (size_t)session->current_crypto->digest_len, session->current_crypto->session_id,
                         SSH2_MSG_USERAUTH_REQUEST,
                         session->gssapi->user,
                         "ssh-connection",
                         "gssapi-with-mic");
    if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    return mic_buffer;
}
Ejemplo n.º 4
0
Archivo: dh.c Proyecto: mwgoldsmith/ssh
/** @internal
 * @brief Starts diffie-hellman-group1 key exchange
 */
int ssh_client_dh_init(ssh_session session){
  ssh_string e = NULL;
  int rc;

  if (dh_generate_x(session) < 0) {
    goto error;
  }
  if (dh_generate_e(session) < 0) {
    goto error;
  }

  e = dh_get_e(session);
  if (e == NULL) {
    goto error;
  }

  rc = ssh_buffer_pack(session->out_buffer, "bS", SSH2_MSG_KEXDH_INIT, e);
  if (rc != SSH_OK) {
    goto error;
  }

  ssh_string_burn(e);
  ssh_string_free(e);
  e=NULL;

  rc = packet_send(session);
  return rc;
  error:
  if(e != NULL){
    ssh_string_burn(e);
    ssh_string_free(e);
  }

  return SSH_ERROR;
}
Ejemplo n.º 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 (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;
}
Ejemplo n.º 6
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 packet_send(msg->session);
  }

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

  return SSH_OK;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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 (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_ERROR) {
                ssh_set_error_oom(msg->session);
                goto error;
            }
        }

        return 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;
}
Ejemplo n.º 9
0
static void *thread_ssh_buffer_add_format(void *threadid)
{
    ssh_buffer buffer = NULL;
    uint8_t b;
    uint16_t w;
    uint32_t d;
    uint64_t q;
    ssh_string s = NULL;
    int rc;
    size_t len;
    uint8_t verif[] = "\x42\x13\x37\x0b\xad\xc0\xde\x13\x24\x35\x46"
        "\xac\xbd\xce\xdf"
        "\x00\x00\x00\x06" "libssh"
        "\x00\x00\x00\x05" "rocks"
        "So much"
        "Fun!";

    /* Unused */
    (void) threadid;

    /* Setup */
    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        pthread_exit((void *)-1);
    }
    ssh_buffer_set_secure(buffer);

    b = 0x42;
    w = 0x1337;
    d = 0xbadc0de;
    q = 0x13243546acbdcedf;
    s = ssh_string_from_char("libssh");
    rc = ssh_buffer_pack(buffer,
                         "bwdqSsPt",
                         b,
                         w,
                         d,
                         q,
                         s,
                         "rocks",
                         7,
                         "So much",
                         "Fun!");
    assert_int_equal(rc, SSH_OK);

    len = ssh_buffer_get_len(buffer);
    assert_int_equal(len, sizeof(verif) - 1);
    assert_memory_equal(ssh_buffer_get(buffer), verif, sizeof(verif) -1);

    SSH_STRING_FREE(s);

    /* Teardown */
    SSH_BUFFER_FREE(buffer);
    pthread_exit(NULL);
}
Ejemplo n.º 10
0
static void *thread_buffer_pack_badformat(void *threadid)
{
    ssh_buffer buffer = NULL;
    uint8_t b = 42;
    int rc;

    /* Unused */
    (void) threadid;

    /* Setup */
    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        pthread_exit((void *)-1);
    }
    ssh_buffer_set_secure(buffer);

    /* first with missing format */
    rc = ssh_buffer_pack(buffer, "b", b, b);
    assert_int_equal(rc, SSH_ERROR);
    ssh_buffer_reinit(buffer);

    /* with additional format */
    rc = ssh_buffer_pack(buffer, "bb", b);
    /* check that we detect the missing parameter */
    assert_int_equal(rc, SSH_ERROR);

    /* unpack with missing format */
    ssh_buffer_reinit(buffer);

    rc = ssh_buffer_pack(buffer, "bb", 42, 43);
    assert_int_equal(rc, SSH_OK);

    rc = ssh_buffer_unpack(buffer, "b", &b, &b);
    assert_int_equal(rc, SSH_ERROR);

    /* not doing the test with additional format as
     * it could crash the process */

    /* Teardown */
    SSH_BUFFER_FREE(buffer);
    pthread_exit(NULL);
}
Ejemplo n.º 11
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 = packet_send(session);
  return rc;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
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 = packet_send(msg->session);
    return rc;
}
Ejemplo n.º 15
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 = packet_send(msg->session);
    return rc;
}
Ejemplo n.º 16
0
/** @internal
 * @brief exports a private key to a string blob.
 * @param[in] privkey private key to convert
 * @param[out] buffer buffer to write the blob in.
 * @returns SSH_OK on success
 * @warning only supports ed25519 key type at the moment.
 */
static int pki_openssh_export_privkey_blob(const ssh_key privkey,
                                           ssh_buffer buffer)
{
    int rc;

    if (privkey->type != SSH_KEYTYPE_ED25519) {
        ssh_pki_log("Type %s not supported", privkey->type_c);
        return SSH_ERROR;
    }
    if (privkey->ed25519_privkey == NULL ||
            privkey->ed25519_pubkey == NULL){
        return SSH_ERROR;
    }
    rc = ssh_buffer_pack(buffer,
                         "sdPdP",
                         privkey->type_c,
                         (uint32_t)ED25519_PK_LEN,
                         (size_t)ED25519_PK_LEN, privkey->ed25519_pubkey,
                         (uint32_t)ED25519_SK_LEN,
                         (size_t)ED25519_SK_LEN, privkey->ed25519_privkey);
    return rc;
}
Ejemplo n.º 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 = packet_send(msg->session);
    return rc;
}
Ejemplo n.º 18
0
static int ssh_gssapi_send_mic(ssh_session session){
    OM_uint32 maj_stat, min_stat;
    gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER;
    ssh_buffer mic_buffer;
    int rc;

    SSH_LOG(SSH_LOG_PACKET,"Sending SSH_MSG_USERAUTH_GSSAPI_MIC");

    mic_buffer = ssh_gssapi_build_mic(session);
    if (mic_buffer == NULL) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    mic_buf.length = ssh_buffer_get_len(mic_buffer);
    mic_buf.value = ssh_buffer_get_begin(mic_buffer);

    maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf);
    if (GSS_ERROR(maj_stat)){
        ssh_buffer_free(mic_buffer);
        ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "generating MIC", maj_stat);
        return SSH_ERROR;
    }

    rc = ssh_buffer_pack(session->out_buffer,
                         "bdP",
                         SSH2_MSG_USERAUTH_GSSAPI_MIC,
                         mic_token_buf.length,
                         (size_t)mic_token_buf.length, mic_token_buf.value);
    if (rc != SSH_OK) {
        ssh_buffer_free(mic_buffer);
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    return packet_send(session);
}
Ejemplo n.º 19
0
Archivo: kex.c Proyecto: simonsj/libssh
int ssh_make_sessionid(ssh_session session)
{
    ssh_string num = NULL;
    ssh_buffer server_hash = NULL;
    ssh_buffer client_hash = NULL;
    ssh_buffer buf = NULL;
    ssh_string server_pubkey_blob = NULL;
    const_bignum client_pubkey, server_pubkey;
#ifdef WITH_GEX
    const_bignum modulus, generator;
#endif
    int rc = SSH_ERROR;

    buf = ssh_buffer_new();
    if (buf == NULL) {
        return rc;
    }

    rc = ssh_buffer_pack(buf,
                         "ss",
                         session->clientbanner,
                         session->serverbanner);
    if (rc == SSH_ERROR) {
        goto error;
    }

    if (session->client) {
        server_hash = session->in_hashbuf;
        client_hash = session->out_hashbuf;
    } else {
        server_hash = session->out_hashbuf;
        client_hash = session->in_hashbuf;
    }

    /*
     * Handle the two final fields for the KEXINIT message (RFC 4253 7.1):
     *
     *      boolean      first_kex_packet_follows
     *      uint32       0 (reserved for future extension)
     */
    rc = ssh_buffer_add_u8(server_hash, 0);
    if (rc < 0) {
        goto error;
    }
    rc = ssh_buffer_add_u32(server_hash, 0);
    if (rc < 0) {
        goto error;
    }

    /* These fields are handled for the server case in ssh_packet_kexinit. */
    if (session->client) {
        rc = ssh_buffer_add_u8(client_hash, 0);
        if (rc < 0) {
            goto error;
        }
        rc = ssh_buffer_add_u32(client_hash, 0);
        if (rc < 0) {
            goto error;
        }
    }

    rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
    if (rc != SSH_OK) {
        goto error;
    }

    rc = ssh_buffer_pack(buf,
                         "dPdPS",
                         ssh_buffer_get_len(client_hash),
                         ssh_buffer_get_len(client_hash),
                         ssh_buffer_get(client_hash),
                         ssh_buffer_get_len(server_hash),
                         ssh_buffer_get_len(server_hash),
                         ssh_buffer_get(server_hash),
                         server_pubkey_blob);
    ssh_string_free(server_pubkey_blob);
    if(rc != SSH_OK){
        goto error;
    }

    switch(session->next_crypto->kex_type) {
    case SSH_KEX_DH_GROUP1_SHA1:
    case SSH_KEX_DH_GROUP14_SHA1:
    case SSH_KEX_DH_GROUP16_SHA512:
    case SSH_KEX_DH_GROUP18_SHA512:
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
                                     DH_CLIENT_KEYPAIR, NULL, &client_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
                                     DH_SERVER_KEYPAIR, NULL, &server_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
        rc = ssh_buffer_pack(buf,
                             "BB",
                             client_pubkey,
                             server_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
        break;
#ifdef WITH_GEX
    case SSH_KEX_DH_GEX_SHA1:
    case SSH_KEX_DH_GEX_SHA256:
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
                                     DH_CLIENT_KEYPAIR, NULL, &client_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
                                     DH_SERVER_KEYPAIR, NULL, &server_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
        rc = ssh_dh_get_parameters(session->next_crypto->dh_ctx,
                                   &modulus, &generator);
        if (rc != SSH_OK) {
            goto error;
        }
        rc = ssh_buffer_pack(buf,
                    "dddBBBB",
                    session->next_crypto->dh_pmin,
                    session->next_crypto->dh_pn,
                    session->next_crypto->dh_pmax,
                    modulus,
                    generator,
                    client_pubkey,
                    server_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
        break;
#endif /* WITH_GEX */
#ifdef HAVE_ECDH
    case SSH_KEX_ECDH_SHA2_NISTP256:
    case SSH_KEX_ECDH_SHA2_NISTP384:
    case SSH_KEX_ECDH_SHA2_NISTP521:
        if (session->next_crypto->ecdh_client_pubkey == NULL ||
            session->next_crypto->ecdh_server_pubkey == NULL) {
            SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
            goto error;
        }
        rc = ssh_buffer_pack(buf,
                             "SS",
                             session->next_crypto->ecdh_client_pubkey,
                             session->next_crypto->ecdh_server_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
        break;
#endif
#ifdef HAVE_CURVE25519
    case SSH_KEX_CURVE25519_SHA256:
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
        rc = ssh_buffer_pack(buf,
                             "dPdP",
                             CURVE25519_PUBKEY_SIZE,
                             (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey,
                             CURVE25519_PUBKEY_SIZE,
                             (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_server_pubkey);

        if (rc != SSH_OK) {
            goto error;
        }
        break;
#endif
    }
    rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
    if (rc != SSH_OK) {
        goto error;
    }

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
#endif

    switch (session->next_crypto->kex_type) {
    case SSH_KEX_DH_GROUP1_SHA1:
    case SSH_KEX_DH_GROUP14_SHA1:
#ifdef WITH_GEX
    case SSH_KEX_DH_GEX_SHA1:
#endif /* WITH_GEX */
        session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
        session->next_crypto->digest_type = SSH_KDF_SHA1;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
                                   session->next_crypto->secret_hash);
        break;
    case SSH_KEX_ECDH_SHA2_NISTP256:
    case SSH_KEX_CURVE25519_SHA256:
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
#ifdef WITH_GEX
    case SSH_KEX_DH_GEX_SHA256:
#endif /* WITH_GEX */
        session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
        session->next_crypto->digest_type = SSH_KDF_SHA256;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha256(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
                                     session->next_crypto->secret_hash);
        break;
    case SSH_KEX_ECDH_SHA2_NISTP384:
        session->next_crypto->digest_len = SHA384_DIGEST_LENGTH;
        session->next_crypto->digest_type = SSH_KDF_SHA384;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha384(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
                                     session->next_crypto->secret_hash);
        break;
    case SSH_KEX_DH_GROUP16_SHA512:
    case SSH_KEX_DH_GROUP18_SHA512:
    case SSH_KEX_ECDH_SHA2_NISTP521:
        session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
        session->next_crypto->digest_type = SSH_KDF_SHA512;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha512(ssh_buffer_get(buf),
               ssh_buffer_get_len(buf),
               session->next_crypto->secret_hash);
        break;
    }
    /* During the first kex, secret hash and session ID are equal. However, after
     * a key re-exchange, a new secret hash is calculated. This hash will not replace
     * but complement existing session id.
     */
    if (!session->next_crypto->session_id) {
        session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->session_id == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
                session->next_crypto->digest_len);
    }
#ifdef DEBUG_CRYPTO
    printf("Session hash: \n");
    ssh_print_hexa("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
    ssh_print_hexa("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
#endif

    rc = SSH_OK;
error:
    ssh_buffer_free(buf);
    ssh_buffer_free(client_hash);
    ssh_buffer_free(server_hash);

    session->in_hashbuf = NULL;
    session->out_hashbuf = NULL;

    ssh_string_free(num);

    return rc;
}
Ejemplo n.º 20
0
static int dh_handshake_server(ssh_session session) {
  ssh_key privkey;
  ssh_string sig_blob;
  ssh_string f;
  int rc;

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

  f = 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 (dh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not import the public key");
    ssh_string_free(f);
    return -1;
  }

  if (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_buffer_pack(session->out_buffer,
                       "bSSS",
                       SSH2_MSG_KEXDH_REPLY,
                       session->next_crypto->server_pubkey,
                       f,
                       sig_blob);
  ssh_string_free(f);
  ssh_string_free(sig_blob);
  if(rc != SSH_OK){
    ssh_set_error_oom(session);
    ssh_buffer_reinit(session->out_buffer);
    return -1;
  }

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

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

  if (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;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
Archivo: dh.c Proyecto: mwgoldsmith/ssh
int make_sessionid(ssh_session session) {
    ssh_string num = NULL;
    ssh_buffer server_hash = NULL;
    ssh_buffer client_hash = NULL;
    ssh_buffer buf = NULL;
    int rc = SSH_ERROR;

    buf = ssh_buffer_new();
    if (buf == NULL) {
        return rc;
    }

    rc = ssh_buffer_pack(buf,
                         "ss",
                         session->clientbanner,
                         session->serverbanner);
    if (rc == SSH_ERROR) {
        goto error;
    }

    if (session->client) {
        server_hash = session->in_hashbuf;
        client_hash = session->out_hashbuf;
    } else {
        server_hash = session->out_hashbuf;
        client_hash = session->in_hashbuf;
    }

    /*
     * Handle the two final fields for the KEXINIT message (RFC 4253 7.1):
     *
     *      boolean      first_kex_packet_follows
     *      uint32       0 (reserved for future extension)
     */
    rc = buffer_add_u8(server_hash, 0);
    if (rc < 0) {
        goto error;
    }
    rc = buffer_add_u32(server_hash, 0);
    if (rc < 0) {
        goto error;
    }

    /* These fields are handled for the server case in ssh_packet_kexinit. */
    if (session->client) {
        rc = buffer_add_u8(client_hash, 0);
        if (rc < 0) {
            goto error;
        }
        rc = buffer_add_u32(client_hash, 0);
        if (rc < 0) {
            goto error;
        }
    }

    rc = ssh_buffer_pack(buf,
                         "dPdPS",
                         buffer_get_rest_len(client_hash),
                         buffer_get_rest_len(client_hash),
                         buffer_get_rest(client_hash),
                         buffer_get_rest_len(server_hash),
                         buffer_get_rest_len(server_hash),
                         buffer_get_rest(server_hash),
                         session->next_crypto->server_pubkey);

    if(rc != SSH_OK){
        goto error;
    }

    if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1 ||
            session->next_crypto->kex_type == SSH_KEX_DH_GROUP14_SHA1) {
        rc = ssh_buffer_pack(buf,
                             "BB",
                             session->next_crypto->e,
                             session->next_crypto->f);
        if (rc != SSH_OK) {
            goto error;
        }

#ifdef HAVE_ECDH
    } else if (session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256) {
        if (session->next_crypto->ecdh_client_pubkey == NULL ||
            session->next_crypto->ecdh_server_pubkey == NULL) {
            SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
            goto error;
        }
        rc = ssh_buffer_pack(buf,
                             "SS",
                             session->next_crypto->ecdh_client_pubkey,
                             session->next_crypto->ecdh_server_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
#endif
#ifdef HAVE_CURVE25519
    } else if (session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG) {
        rc = ssh_buffer_pack(buf,
                             "dPdP",
                             CURVE25519_PUBKEY_SIZE,
                             (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey,
                             CURVE25519_PUBKEY_SIZE,
                             (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_server_pubkey);

        if (rc != SSH_OK) {
            goto error;
        }
#endif
    }
    rc = ssh_buffer_pack(buf, "B", session->next_crypto->k);
    if (rc != SSH_OK) {
        goto error;
    }

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("hash buffer", ssh_buffer_get_begin(buf), ssh_buffer_get_len(buf));
#endif

    switch (session->next_crypto->kex_type) {
    case SSH_KEX_DH_GROUP1_SHA1:
    case SSH_KEX_DH_GROUP14_SHA1:
        session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
        session->next_crypto->mac_type = SSH_MAC_SHA1;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha1(buffer_get_rest(buf), buffer_get_rest_len(buf),
                                   session->next_crypto->secret_hash);
        break;
    case SSH_KEX_ECDH_SHA2_NISTP256:
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
        session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
        session->next_crypto->mac_type = SSH_MAC_SHA256;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha256(buffer_get_rest(buf), buffer_get_rest_len(buf),
                                     session->next_crypto->secret_hash);
        break;
    }
    /* During the first kex, secret hash and session ID are equal. However, after
     * a key re-exchange, a new secret hash is calculated. This hash will not replace
     * but complement existing session id.
     */
    if (!session->next_crypto->session_id) {
        session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->session_id == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
                session->next_crypto->digest_len);
    }
#ifdef DEBUG_CRYPTO
    printf("Session hash: \n");
    ssh_print_hexa("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
    ssh_print_hexa("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
#endif

    rc = SSH_OK;
error:
    ssh_buffer_free(buf);
    ssh_buffer_free(client_hash);
    ssh_buffer_free(server_hash);

    session->in_hashbuf = NULL;
    session->out_hashbuf = NULL;

    ssh_string_free(num);

    return rc;
}
Ejemplo n.º 23
0
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
                                          const char *passphrase,
                                          ssh_auth_callback auth_fn,
                                          void *auth_data)
{
    ssh_buffer buffer;
    ssh_string str = NULL;
    ssh_string pubkey_s=NULL;
    ssh_buffer privkey_buffer = NULL;
    uint32_t rnd;
    uint32_t rounds = 16;
    ssh_string salt=NULL;
    ssh_string kdf_options=NULL;
    int to_encrypt=0;
    unsigned char *b64;
    uint32_t str_len, len;
    int rc;

    if (privkey == NULL) {
        return NULL;
    }
    if (privkey->type != SSH_KEYTYPE_ED25519){
        ssh_pki_log("Unsupported key type %s", privkey->type_c);
        return NULL;
    }
    if (passphrase != NULL || auth_fn != NULL){
        ssh_pki_log("Enabling encryption for private key export");
        to_encrypt = 1;
    }
    buffer = ssh_buffer_new();
    pubkey_s = pki_publickey_to_blob(privkey);
    if(buffer == NULL || pubkey_s == NULL){
        goto error;
    }
    ssh_get_random(&rnd, sizeof(rnd), 0);

    privkey_buffer = ssh_buffer_new();
    if (privkey_buffer == NULL) {
        goto error;
    }

    /* checkint1 & 2 */
    rc = ssh_buffer_pack(privkey_buffer,
                         "dd",
                         rnd,
                         rnd);
    if (rc == SSH_ERROR){
        goto error;
    }

    rc = pki_openssh_export_privkey_blob(privkey, privkey_buffer);
    if (rc == SSH_ERROR){
        goto error;
    }

    /* comment */
    rc = ssh_buffer_pack(privkey_buffer, "s", "" /* comment */);
    if (rc == SSH_ERROR){
        goto error;
    }

    if (to_encrypt){
        ssh_buffer kdf_buf;

        kdf_buf = ssh_buffer_new();
        if (kdf_buf == NULL) {
            goto error;
        }

        salt = ssh_string_new(16);
        if (salt == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        ssh_get_random(ssh_string_data(salt),16, 0);
        ssh_buffer_pack(kdf_buf, "Sd", salt, rounds);
        kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf));
        if (kdf_options == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        memcpy(ssh_string_data(kdf_options),
               ssh_buffer_get_begin(kdf_buf),
               ssh_buffer_get_len(kdf_buf));
        ssh_buffer_free(kdf_buf);
        rc = pki_private_key_encrypt(privkey_buffer,
                                     passphrase,
                                     "aes128-cbc",
                                     "bcrypt",
                                     auth_fn,
                                     auth_data,
                                     rounds,
                                     salt);
        if (rc != SSH_OK){
            goto error;
        }
    } else {
        kdf_options = ssh_string_new(0);
    }

    rc = ssh_buffer_pack(buffer,
                         "PssSdSdP",
                         (size_t)strlen(OPENSSH_AUTH_MAGIC) + 1, OPENSSH_AUTH_MAGIC,
                         to_encrypt ? "aes128-cbc" : "none", /* ciphername */
                         to_encrypt ? "bcrypt" : "none", /* kdfname */
                         kdf_options, /* kdfoptions */
                         (uint32_t) 1, /* nkeys */
                         pubkey_s,
                         (uint32_t)ssh_buffer_get_len(privkey_buffer),
                         /* rest of buffer is a string */
                         (size_t)ssh_buffer_get_len(privkey_buffer), ssh_buffer_get_begin(privkey_buffer));
    if (rc != SSH_OK) {
        goto error;
    }

    b64 = bin_to_base64(ssh_buffer_get_begin(buffer),
                        ssh_buffer_get_len(buffer));
    if (b64 == NULL){
        goto error;
    }

    /* we can reuse the buffer */
    ssh_buffer_reinit(buffer);
    rc = ssh_buffer_pack(buffer,
                         "tttttt",
                         OPENSSH_HEADER_BEGIN,
                         "\n",
                         b64,
                         "\n",
                         OPENSSH_HEADER_END,
                         "\n");
    BURN_BUFFER(b64, strlen((char *)b64));
    SAFE_FREE(b64);

    if (rc != SSH_OK){
        goto error;
    }

    str = ssh_string_new(ssh_buffer_get_len(buffer));
    if (str == NULL){
        goto error;
    }

    str_len = ssh_buffer_get_len(buffer);
    len = buffer_get_data(buffer, ssh_string_data(str), str_len);
    if (str_len != len) {
        ssh_string_free(str);
        str = NULL;
    }

error:
    if (privkey_buffer != NULL) {
        void *bufptr = ssh_buffer_get_begin(privkey_buffer);
        BURN_BUFFER(bufptr, ssh_buffer_get_len(privkey_buffer));
        ssh_buffer_free(privkey_buffer);
    }
    SAFE_FREE(pubkey_s);
    SAFE_FREE(kdf_options);
    SAFE_FREE(salt);
    if (buffer != NULL) {
        ssh_buffer_free(buffer);
    }

    return str;
}
Ejemplo n.º 24
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[1] ? 1 : 0);
    if (rc != SSH_OK){
        ssh_set_error_oom(msg->session);
        return SSH_ERROR;
    }
  }

  rc = 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 = malloc(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 = malloc(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;
}
Ejemplo n.º 25
0
static int packet_send2(ssh_session session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  unsigned int lenfield_blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->lenfield_blocksize : 0);
  enum ssh_hmac_e hmac_type = (session->current_crypto ?
      session->current_crypto->out_hmac : session->next_crypto->out_hmac);
  uint32_t currentlen = ssh_buffer_get_len(session->out_buffer);
  unsigned char *hmac = NULL;
  char padstring[32] = { 0 };
  int rc = SSH_ERROR;
  uint32_t finallen,payloadsize,compsize;
  uint8_t padding;
  ssh_buffer header_buffer = ssh_buffer_new();

  payloadsize = currentlen;
#ifdef WITH_ZLIB
  if (session->current_crypto
      && session->current_crypto->do_compress_out
      && ssh_buffer_get_len(session->out_buffer)) {
    if (compress_buffer(session,session->out_buffer) < 0) {
      goto error;
    }
    currentlen = ssh_buffer_get_len(session->out_buffer);
  }
#endif /* WITH_ZLIB */
  compsize = currentlen;
  /* compressed payload + packet len (4) + padding len (1) */
  /* totallen - lenfield_blocksize must be equal to 0 (mod blocksize) */
  padding = (blocksize - ((blocksize - lenfield_blocksize + currentlen + 5) % blocksize));
  if(padding < 4) {
    padding += blocksize;
  }

  if (session->current_crypto != NULL) {
      int ok;

      ok = ssh_get_random(padstring, padding, 0);
      if (!ok) {
          ssh_set_error(session, SSH_FATAL, "PRNG error");
          goto error;
      }
  }

  if (header_buffer == NULL){
    ssh_set_error_oom(session);
    goto error;
  }
  finallen = currentlen + padding + 1;
  rc = ssh_buffer_pack(header_buffer, "db", finallen, padding);
  if (rc == SSH_ERROR){
    goto error;
  }

  rc = ssh_buffer_prepend_data(session->out_buffer,
                               ssh_buffer_get(header_buffer),
                               ssh_buffer_get_len(header_buffer));
  if (rc < 0) {
    goto error;
  }
  rc = ssh_buffer_add_data(session->out_buffer, padstring, padding);
  if (rc < 0) {
    goto error;
  }
#ifdef WITH_PCAP
  if (session->pcap_ctx) {
      ssh_pcap_context_write(session->pcap_ctx,
                             SSH_PCAP_DIR_OUT,
                             ssh_buffer_get(session->out_buffer),
                             ssh_buffer_get_len(session->out_buffer),
                             ssh_buffer_get_len(session->out_buffer));
  }
#endif
  hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
  if (hmac) {
    rc = ssh_buffer_add_data(session->out_buffer, hmac, hmac_digest_len(hmac_type));
    if (rc < 0) {
      goto error;
    }
  }

  rc = ssh_packet_write(session);
  session->send_seq++;
  if (session->raw_counter != NULL) {
      session->raw_counter->out_bytes += payloadsize;
      session->raw_counter->out_packets++;
  }

  SSH_LOG(SSH_LOG_PACKET,
          "packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]",
          finallen, padding, compsize, payloadsize);
  if (ssh_buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:
  if (header_buffer != NULL) {
      ssh_buffer_free(header_buffer);
  }
  return rc; /* SSH_OK, AGAIN or ERROR */
}
Ejemplo n.º 26
0
Archivo: pki.c Proyecto: codinn/libssh
/*
 * This function signs the session id as a string then
 * the content of sigbuf */
ssh_string ssh_pki_do_sign(ssh_session session,
                           ssh_buffer sigbuf,
                           const ssh_key privkey) {
    struct ssh_crypto_struct *crypto =
        session->current_crypto ? session->current_crypto :
                                  session->next_crypto;
    ssh_signature sig = NULL;
    ssh_string sig_blob;
    ssh_string session_id;
    int rc;

    if (privkey == NULL || !ssh_key_is_private(privkey)) {
        return NULL;
    }

    session_id = ssh_string_new(crypto->digest_len);
    if (session_id == NULL) {
        return NULL;
    }
    ssh_string_fill(session_id, crypto->session_id, crypto->digest_len);

    if (privkey->type == SSH_KEYTYPE_ECDSA) {
#ifdef HAVE_ECC
        unsigned char ehash[EVP_DIGEST_LEN] = {0};
        uint32_t elen;
        EVPCTX ctx;

        ctx = evp_init(privkey->ecdsa_nid);
        if (ctx == NULL) {
            ssh_string_free(session_id);
            return NULL;
        }

        evp_update(ctx, session_id, ssh_string_len(session_id) + 4);
        evp_update(ctx, ssh_buffer_get(sigbuf), ssh_buffer_get_len(sigbuf));
        evp_final(ctx, ehash, &elen);

#ifdef DEBUG_CRYPTO
        ssh_print_hexa("Hash being signed", ehash, elen);
#endif

        sig = pki_do_sign(privkey, ehash, elen);
#endif
    } else if (privkey->type == SSH_KEYTYPE_ED25519){
        ssh_buffer buf;

        buf = ssh_buffer_new();
        if (buf == NULL) {
            ssh_string_free(session_id);
            return NULL;
        }

        ssh_buffer_set_secure(buf);
        rc = ssh_buffer_pack(buf,
                             "SP",
                             session_id,
                             ssh_buffer_get_len(sigbuf), ssh_buffer_get(sigbuf));
        if (rc != SSH_OK) {
            ssh_string_free(session_id);
            ssh_buffer_free(buf);
            return NULL;
        }

        sig = pki_do_sign(privkey,
                          ssh_buffer_get(buf),
                          ssh_buffer_get_len(buf));
        ssh_buffer_free(buf);
    } else {
        unsigned char hash[SHA_DIGEST_LEN] = {0};
        SHACTX ctx;

        ctx = sha1_init();
        if (ctx == NULL) {
            ssh_string_free(session_id);
            return NULL;
        }

        sha1_update(ctx, session_id, ssh_string_len(session_id) + 4);
        sha1_update(ctx, ssh_buffer_get(sigbuf), ssh_buffer_get_len(sigbuf));
        sha1_final(hash, ctx);

#ifdef DEBUG_CRYPTO
        ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
#endif

        sig = pki_do_sign(privkey, hash, SHA_DIGEST_LEN);
    }
    ssh_string_free(session_id);
    if (sig == NULL) {
        return NULL;
    }

    rc = ssh_pki_export_signature_blob(sig, &sig_blob);
    ssh_signature_free(sig);
    if (rc < 0) {
        return NULL;
    }

    return sig_blob;
}
Ejemplo n.º 27
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;
  }
}