Exemple #1
0
/* caller has to free commment */
struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *session,
    char **comment) {
  struct ssh_public_key_struct *pubkey = NULL;
  struct ssh_string_struct *blob = NULL;
  struct ssh_string_struct *tmp = NULL;

  if (session->agent->count == 0) {
    return NULL;
  }

  switch(session->version) {
    case 1:
      return NULL;
    case 2:
      /* get the blob */
      blob = buffer_get_ssh_string(session->agent->ident);
      if (blob == NULL) {
        return NULL;
      }

      /* get the comment */
      tmp = buffer_get_ssh_string(session->agent->ident);
      if (tmp == NULL) {
        string_free(blob);

        return NULL;
      }

      if (comment) {
        *comment = string_to_char(tmp);
      } else {
        string_free(blob);
        string_free(tmp);

        return NULL;
      }
      string_free(tmp);

      /* get key from blob */
      pubkey = publickey_from_string(session, blob);
      string_free(blob);
      break;
    default:
      return NULL;
  }

  return pubkey;
}
Exemple #2
0
int signature_verify(ssh_session session, ssh_string signature) {
  ssh_public_key pubkey = NULL;
  SIGNATURE *sign = NULL;
  int err;

  enter_function();

  pubkey = publickey_from_string(session,session->next_crypto->server_pubkey);
  if(pubkey == NULL) {
    leave_function();
    return -1;
  }

  if (session->wanted_methods[SSH_HOSTKEYS]) {
    if(!match(session->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) {
      ssh_set_error(session, SSH_FATAL,
          "Public key from server (%s) doesn't match user preference (%s)",
          pubkey->type_c, session->wanted_methods[SSH_HOSTKEYS]);
      publickey_free(pubkey);
      leave_function();
      return -1;
    }
  }

  sign = signature_from_string(session, signature, pubkey, pubkey->type);
  if (sign == NULL) {
    ssh_set_error(session, SSH_FATAL, "Invalid signature blob");
    publickey_free(pubkey);
    leave_function();
    return -1;
  }

  ssh_log(session, SSH_LOG_FUNCTIONS,
      "Going to verify a %s type signature", pubkey->type_c);

  err = sig_verify(session,pubkey,sign,
                            session->next_crypto->session_id,SHA_DIGEST_LEN);
  signature_free(sign);
  session->next_crypto->server_pubkey_type = pubkey->type_c;
  publickey_free(pubkey);

  leave_function();
  return err;
}
Exemple #3
0
int ssh_get_kex1(SSH_SESSION *session) {
  STRING *server_exp = NULL;
  STRING *server_mod = NULL;
  STRING *host_exp = NULL;
  STRING *host_mod = NULL;
  STRING *serverkey = NULL;
  STRING *hostkey = NULL;
  STRING *enc_session = NULL;
  PUBLIC_KEY *srv = NULL;
  PUBLIC_KEY *host = NULL;
  u32 server_bits;
  u32 host_bits;
  u32 protocol_flags;
  u32 supported_ciphers_mask;
  u32 supported_authentications_mask;
  u16 bits;
  int rc = -1;
  int ko;

  enter_function();
  ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
  if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) {
    leave_function();
    return -1;
  }

  ssh_log(session, SSH_LOG_PROTOCOL, "Got a SSH_SMSG_PUBLIC_KEY");
  if (buffer_get_data(session->in_buffer, session->server_kex.cookie, 8) != 8) {
    ssh_set_error(session, SSH_FATAL, "Can't get cookie in buffer");
    leave_function();
    return -1;
  }

  buffer_get_u32(session->in_buffer, &server_bits);
  server_exp = buffer_get_mpint(session->in_buffer);
  if (server_exp == NULL) {
    goto error;
  }
  server_mod = buffer_get_mpint(session->in_buffer);
  if (server_mod == NULL) {
    goto error;
  }
  buffer_get_u32(session->in_buffer, &host_bits);
  host_exp = buffer_get_mpint(session->in_buffer);
  if (host_exp == NULL) {
    goto error;
  }
  host_mod = buffer_get_mpint(session->in_buffer);
  if (host_mod == NULL) {
    goto error;
  }
  buffer_get_u32(session->in_buffer, &protocol_flags);
  buffer_get_u32(session->in_buffer, &supported_ciphers_mask);
  ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask);

  if ((ko != sizeof(u32)) || !host_mod || !host_exp
      || !server_mod || !server_exp) {
    ssh_log(session, SSH_LOG_RARE, "Invalid SSH_SMSG_PUBLIC_KEY packet");
    ssh_set_error(session, SSH_FATAL, "Invalid SSH_SMSG_PUBLIC_KEY packet");
    goto error;
  }

  server_bits = ntohl(server_bits);
  host_bits = ntohl(host_bits);
  protocol_flags = ntohl(protocol_flags);
  supported_ciphers_mask = ntohl(supported_ciphers_mask);
  supported_authentications_mask = ntohl(supported_authentications_mask);
  ssh_log(session, SSH_LOG_PROTOCOL,
      "Server bits: %d; Host bits: %d; Protocol flags: %.8lx; "
      "Cipher mask: %.8lx; Auth mask: %.8lx",
      server_bits,
      host_bits,
      (unsigned long int) protocol_flags,
      (unsigned long int) supported_ciphers_mask,
      (unsigned long int) supported_authentications_mask);

  serverkey = make_rsa1_string(server_exp, server_mod);
  if (serverkey == NULL) {
    goto error;
  }
  hostkey = make_rsa1_string(host_exp,host_mod);
  if (serverkey == NULL) {
    goto error;
  }
  if (build_session_id1(session, server_mod, host_mod) < 0) {
    goto error;
  }

  srv = publickey_from_string(session, serverkey);
  if (srv == NULL) {
    goto error;
  }
  host = publickey_from_string(session, hostkey);
  if (host == NULL) {
    goto error;
  }

  session->next_crypto->server_pubkey = string_copy(hostkey);
  if (session->next_crypto->server_pubkey == NULL) {
    goto error;
  }
  session->next_crypto->server_pubkey_type = "ssh-rsa1";

  /* now, we must choose an encryption algo */
  /* hardcode 3des */
  if (!(supported_ciphers_mask & (1 << SSH_CIPHER_3DES))) {
    ssh_set_error(session, SSH_FATAL, "Remote server doesn't accept 3DES");
    goto error;
  }

  ssh_log(session, SSH_LOG_PROTOCOL, "Sending SSH_CMSG_SESSION_KEY");

  if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) {
    goto error;
  }
  if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) {
    goto error;
  }
  if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) {
    goto error;
  }

  enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits);
  if (enc_session == NULL) {
    goto error;
  }

  bits = string_len(enc_session) * 8 - 7;
  ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session",
      bits, string_len(enc_session));
  bits = htons(bits);
  /* the encrypted mpint */
  if (buffer_add_data(session->out_buffer, &bits, sizeof(u16)) < 0) {
    goto error;
  }
  if (buffer_add_data(session->out_buffer, enc_session->string,
        string_len(enc_session)) < 0) {
    goto error;
  }
  /* the protocol flags */
  if (buffer_add_u32(session->out_buffer, 0) < 0) {
    goto error;
  }

  if (packet_send(session) != SSH_OK) {
    goto error;
  }

  /* we can set encryption */
  if (crypt_set_algorithms(session)) {
    goto error;
  }

  session->current_crypto = session->next_crypto;
  session->next_crypto = NULL;

  ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS");
  if (packet_wait(session,SSH_SMSG_SUCCESS,1) != SSH_OK) {
    char buffer[1024] = {0};
    snprintf(buffer, sizeof(buffer),
        "Key exchange failed: %s", ssh_get_error(session));
    ssh_set_error(session, SSH_FATAL, "%s",buffer);
    goto error;
  }
  ssh_log(session, SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n");

  rc = 0;
error:
  string_free(host_mod);
  string_free(host_exp);
  string_free(server_mod);
  string_free(server_exp);
  string_free(serverkey);
  string_free(hostkey);

  publickey_free(srv);
  publickey_free(host);

  leave_function();
  return rc;
}
Exemple #4
0
/**
 * @brief Write the current server as known in the known hosts file.
 *
 * This will create the known hosts file if it does not exist. You generaly use
 * it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN.
 *
 * @param[in]  session  The ssh session to use.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 */
int ssh_write_knownhost(ssh_session session) {
  ssh_string pubkey;
  unsigned char *pubkey_64;
  char buffer[4096] = {0};
  FILE *file;
  char *dir;
  char *host;
  char *hostport;
  size_t len = 0;

  if (session->host == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Can't write host in known hosts if the hostname isn't known");
    return SSH_ERROR;
  }

  host = ssh_lowercase(session->host);
  /* If using a nonstandard port, save the host in the [host]:port format */
  if(session->port != 22){
    hostport = ssh_hostport(host,session->port);
    SAFE_FREE(host);
    host=hostport;
    hostport=NULL;
  }

  if (session->knownhosts == NULL) {
    if (ssh_options_apply(session) < 0) {
      ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file");
      return SSH_ERROR;
    }
  }

  if(session->current_crypto==NULL) {
  	ssh_set_error(session, SSH_FATAL, "No current crypto context");
  	return SSH_ERROR;
  }

  pubkey = session->current_crypto->server_pubkey;
  if(pubkey == NULL){
  	ssh_set_error(session, SSH_FATAL, "No public key present");
  	return SSH_ERROR;
  }

  /* Check if ~/.ssh exists and create it if not */
  dir = ssh_dirname(session->knownhosts);
  if (dir == NULL) {
    ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
    return -1;
  }
  if (! ssh_file_readaccess_ok(dir)) {
    if (ssh_mkdir(dir, 0700) < 0) {
      ssh_set_error(session, SSH_FATAL,
          "Cannot create %s directory.", dir);
      SAFE_FREE(dir);
      return -1;
    }
  }
  SAFE_FREE(dir);

  file = fopen(session->knownhosts, "a");
  if (file == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Couldn't open known_hosts file %s for appending: %s",
        session->knownhosts, strerror(errno));
    SAFE_FREE(host);
    return -1;
  }

  if (strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1") == 0) {
    /* openssh uses a different format for ssh-rsa1 keys.
       Be compatible --kv */
    ssh_public_key key;
    char *e_string = NULL;
    char *n_string = NULL;
    bignum e = NULL;
    bignum n = NULL;
    int rsa_size;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t sexp;
#endif

    key = publickey_from_string(session, pubkey);
    if (key == NULL) {
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

#ifdef HAVE_LIBGCRYPT
    sexp = gcry_sexp_find_token(key->rsa_pub, "e", 0);
    if (sexp == NULL) {
      publickey_free(key);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }
    e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
    gcry_sexp_release(sexp);
    if (e == NULL) {
      publickey_free(key);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    sexp = gcry_sexp_find_token(key->rsa_pub, "n", 0);
    if (sexp == NULL) {
      publickey_free(key);
      bignum_free(e);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }
    n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
    gcry_sexp_release(sexp);
    if (n == NULL) {
      publickey_free(key);
      bignum_free(e);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    rsa_size = (gcry_pk_get_nbits(key->rsa_pub) + 7) / 8;
#elif defined HAVE_LIBCRYPTO
    e = key->rsa_pub->e;
    n = key->rsa_pub->n;
    rsa_size = RSA_size(key->rsa_pub);
#endif

    e_string = bignum_bn2dec(e);
    n_string = bignum_bn2dec(n);
    if (e_string == NULL || n_string == NULL) {
#ifdef HAVE_LIBGCRYPT
      bignum_free(e);
      bignum_free(n);
      SAFE_FREE(e_string);
      SAFE_FREE(n_string);
#elif defined HAVE_LIBCRYPTO
      OPENSSL_free(e_string);
      OPENSSL_free(n_string);
#endif
      publickey_free(key);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    snprintf(buffer, sizeof(buffer),
        "%s %d %s %s\n",
        host,
        rsa_size << 3,
        e_string,
        n_string);

#ifdef HAVE_LIBGCRYPT
    bignum_free(e);
    bignum_free(n);
    SAFE_FREE(e_string);
    SAFE_FREE(n_string);
#elif defined HAVE_LIBCRYPTO
    OPENSSL_free(e_string);
    OPENSSL_free(n_string);
#endif

    publickey_free(key);
  } else {
    pubkey_64 = bin_to_base64(pubkey->string, ssh_string_len(pubkey));
    if (pubkey_64 == NULL) {
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    snprintf(buffer, sizeof(buffer),
        "%s %s %s\n",
        host,
        session->current_crypto->server_pubkey_type,
        pubkey_64);

    SAFE_FREE(pubkey_64);
  }
  SAFE_FREE(host);
  len = strlen(buffer);
  if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
    fclose(file);
    return -1;
  }

  fclose(file);
  return 0;
}
Exemple #5
0
int ssh_get_kex1(SSH_SESSION *session){
    u32 server_bits, host_bits, protocol_flags, 
        supported_ciphers_mask, supported_authentications_mask;
    STRING *server_exp=NULL;
    STRING *server_mod=NULL;
    STRING *host_exp=NULL;
    STRING *host_mod=NULL;
    STRING *serverkey;
    STRING *hostkey;
    STRING *enc_session;
    PUBLIC_KEY *svr,*host;
    int ko;
    u16 bits;
    ssh_say(3,"Waiting for a SSH_SMSG_PUBLIC_KEY\n");
    if(packet_wait(session,SSH_SMSG_PUBLIC_KEY,1)){
        return -1;
    }
    ssh_say(3,"Got a SSH_SMSG_PUBLIC_KEY\n");
    if(buffer_get_data(session->in_buffer,session->server_kex.cookie,8)!=8){
        ssh_set_error(NULL,SSH_FATAL,"Can't get cookie in buffer");
        return -1;
    }
    buffer_get_u32(session->in_buffer,&server_bits);
    server_exp=buffer_get_mpint(session->in_buffer);
    server_mod=buffer_get_mpint(session->in_buffer);
    buffer_get_u32(session->in_buffer,&host_bits);
    host_exp=buffer_get_mpint(session->in_buffer);
    host_mod=buffer_get_mpint(session->in_buffer);
    buffer_get_u32(session->in_buffer,&protocol_flags);
    buffer_get_u32(session->in_buffer,&supported_ciphers_mask);
    ko=buffer_get_u32(session->in_buffer,&supported_authentications_mask);
    if((ko!=sizeof(u32)) || !host_mod || !host_exp || !server_mod || !server_exp){
        ssh_say(2,"Invalid SSH_SMSG_PUBLIC_KEY packet\n");
        ssh_set_error(NULL,SSH_FATAL,"Invalid SSH_SMSG_PUBLIC_KEY packet");
        if(host_mod)
            free(host_mod);
        if(host_exp)
            free(host_exp);
        if(server_mod)
            free(server_mod);
        if(server_exp)
            free(server_exp);
        return -1;
    }
    server_bits=ntohl(server_bits);
    host_bits=ntohl(host_bits);
    protocol_flags=ntohl(protocol_flags);
    supported_ciphers_mask=ntohl(supported_ciphers_mask);
    supported_authentications_mask=ntohl(supported_authentications_mask);
    ssh_say(1,"server bits: %d ; host bits: %d\nProtocol flags : %.8lx ; "
            "cipher mask : %.8lx ; auth mask: %.8lx\n",server_bits,
            host_bits,protocol_flags,supported_ciphers_mask,
            supported_authentications_mask);
    serverkey=make_rsa1_string(server_exp,server_mod);
    hostkey=make_rsa1_string(host_exp,host_mod);
    build_session_id1(session,server_mod,host_mod);
    free(server_exp);
    free(server_mod);
    free(host_exp);
    free(host_mod);
    svr=publickey_from_string(serverkey);
    host=publickey_from_string(hostkey);
    session->next_crypto->server_pubkey=string_copy(hostkey);
    session->next_crypto->server_pubkey_type="ssh-rsa1";

    /* now, we must choose an encryption algo */
    /* hardcode 3des */
    if(!(supported_ciphers_mask & (1<<SSH_CIPHER_3DES))){
        ssh_set_error(NULL,SSH_FATAL,"Remote server doesn't accept 3des");
        return -1;
    }
    packet_clear_out(session);
    buffer_add_u8(session->out_buffer,SSH_CMSG_SESSION_KEY);
    buffer_add_u8(session->out_buffer,SSH_CIPHER_3DES);
    buffer_add_data(session->out_buffer,session->server_kex.cookie,8);
    
    enc_session=encrypt_session_key(session,svr,host,server_bits, host_bits);
    bits=string_len(enc_session)*8 - 7;
    ssh_say(2,"%d bits,%d bytes encrypted session\n",bits,string_len(enc_session));
    bits=htons(bits);
    /* the encrypted mpint */
    buffer_add_data(session->out_buffer,&bits,sizeof(u16));
    buffer_add_data(session->out_buffer,enc_session->string,
            string_len(enc_session));
    /* the protocol flags */
    buffer_add_u32(session->out_buffer,0);

    packet_send(session); 
    /* we can set encryption */
    if(crypt_set_algorithms(session))
        return -1;
    session->current_crypto=session->next_crypto;
    session->next_crypto=NULL;
    if(packet_wait(session,SSH_SMSG_SUCCESS,1)){
        char buffer[1024];
        snprintf(buffer,sizeof(buffer),"Key exchange failed : %s",ssh_get_error(session));
        ssh_set_error(session,SSH_FATAL,"%s",buffer);
        return -1;
    }
    ssh_say(1,"received SSH_SMSG_SUCCESS\n");
    return 0;
    
}