コード例 #1
0
ファイル: kex.c プロジェクト: caidongyun/nullfxp
static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey,
    ssh_public_key hostkey, int slen, int hlen) {
  unsigned char buffer[32] = {0};
  int i;
  ssh_string data1 = NULL;
  ssh_string data2 = NULL;

  /* first, generate a session key */
  ssh_get_random(session->next_crypto->encryptkey, 32, 1);
  memcpy(buffer, session->next_crypto->encryptkey, 32);
  memcpy(session->next_crypto->decryptkey, session->next_crypto->encryptkey, 32);

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("session key",buffer,32);
#endif

  /* xor session key with session_id */
  for (i = 0; i < 16; i++) {
    buffer[i] ^= session->next_crypto->session_id[i];
  }
  data1 = ssh_string_new(32);
  if (data1 == NULL) {
    return NULL;
  }
  ssh_string_fill(data1, buffer, 32);
  if (ABS(hlen - slen) < 128){
    ssh_log(session, SSH_LOG_FUNCTIONS,
        "Difference between server modulus and host modulus is only %d. "
        "It's illegal and may not work",
        ABS(hlen - slen));
  }

  if (modulus_smaller(srvkey, hostkey)) {
    data2 = ssh_encrypt_rsa1(session, data1, srvkey);
    ssh_string_free(data1);
    data1 = NULL;
    if (data2 == NULL) {
      return NULL;
    }
    data1 = ssh_encrypt_rsa1(session, data2, hostkey);
    ssh_string_free(data2);
    if (data1 == NULL) {
      return NULL;
    }
  } else {
    data2 = ssh_encrypt_rsa1(session, data1, hostkey);
    ssh_string_free(data1);
    data1 = NULL;
    if (data2 == NULL) {
      return NULL;
    }
    data1 = ssh_encrypt_rsa1(session, data2, srvkey);
    ssh_string_free(data2);
    if (data1 == NULL) {
      return NULL;
    }
  }

  return data1;
}
コード例 #2
0
ファイル: keys.c プロジェクト: rofl0r/libssh
/*
 * Maybe the missing function from libcrypto
 *
 * I think now, maybe it's a bad idea to name it has it should have be
 * named in libcrypto
 */
ssh_string RSA_do_sign(const unsigned char *payload, int len, RSA *privkey) {
    ssh_string sign = NULL;
    unsigned char *buffer = NULL;
    unsigned int size;

    buffer = malloc(RSA_size(privkey));
    if (buffer == NULL) {
        return NULL;
    }

    if (RSA_sign(NID_sha1, payload, len, buffer, &size, privkey) == 0) {
        SAFE_FREE(buffer);
        return NULL;
    }

    sign = ssh_string_new(size);
    if (sign == NULL) {
        SAFE_FREE(buffer);
        return NULL;
    }

    ssh_string_fill(sign, buffer, size);
    SAFE_FREE(buffer);

    return sign;
}
コード例 #3
0
ファイル: curve25519.c プロジェクト: caidongyun/ssh-proxy
/** @internal
 * @brief Starts [email protected] key exchange
 */
int ssh_client_curve25519_init(ssh_session_t * session){
  ssh_string_t * client_pubkey;
  int rc;

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

  rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
  if (rc == 0){
	  ssh_set_error(session, SSH_FATAL, "PRNG error");
	  return SSH_ERROR;
  }

  crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
		  session->next_crypto->curve25519_privkey);
  client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE);
  if (client_pubkey == NULL) {
      return SSH_ERROR;
  }
  ssh_string_fill(client_pubkey, session->next_crypto->curve25519_client_pubkey,
		  CURVE25519_PUBKEY_SIZE);
  rc = buffer_add_ssh_string(session->out_buffer,client_pubkey);
  ssh_string_free(client_pubkey);
  if (rc < 0) {
      return SSH_ERROR;
  }

  rc = packet_send(session);

  return rc;
}
コード例 #4
0
ファイル: keys.c プロジェクト: rofl0r/libssh
/*
 * This function concats in a buffer the values needed to do a signature
 * verification. */
ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg, char *service) {
    /*
         The value of 'signature' is a signature by the corresponding private
       key over the following data, in the following order:

          string    session identifier
          byte      SSH_MSG_USERAUTH_REQUEST
          string    user name
          string    service name
          string    "publickey"
          boolean   TRUE
          string    public key algorithm name
          string    public key to be used for authentication
    */
    struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
                                           session->next_crypto;
    ssh_buffer buffer = NULL;
    ssh_string session_id = NULL;
    uint8_t type = SSH2_MSG_USERAUTH_REQUEST;
    ssh_string username = ssh_string_from_char(msg->auth_request.username);
    ssh_string servicename = ssh_string_from_char(service);
    ssh_string method = ssh_string_from_char("publickey");
    uint8_t has_sign = 1;
    ssh_string algo = ssh_string_from_char(msg->auth_request.public_key->type_c);
    ssh_string publickey = publickey_to_string(msg->auth_request.public_key);

    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        goto error;
    }
    session_id = ssh_string_new(SHA_DIGEST_LEN);
    if (session_id == NULL) {
        ssh_buffer_free(buffer);
        buffer = NULL;
        goto error;
    }
    ssh_string_fill(session_id, crypto->session_id, SHA_DIGEST_LEN);

    if(buffer_add_ssh_string(buffer, session_id) < 0 ||
            buffer_add_u8(buffer, type) < 0 ||
            buffer_add_ssh_string(buffer, username) < 0 ||
            buffer_add_ssh_string(buffer, servicename) < 0 ||
            buffer_add_ssh_string(buffer, method) < 0 ||
            buffer_add_u8(buffer, has_sign) < 0 ||
            buffer_add_ssh_string(buffer, algo) < 0 ||
            buffer_add_ssh_string(buffer, publickey) < 0) {
        ssh_buffer_free(buffer);
        buffer = NULL;
        goto error;
    }

error:
    if(session_id) ssh_string_free(session_id);
    if(username) ssh_string_free(username);
    if(servicename) ssh_string_free(servicename);
    if(method) ssh_string_free(method);
    if(algo) ssh_string_free(algo);
    if(publickey) ssh_string_free(publickey);
    return buffer;
}
コード例 #5
0
ファイル: kex1.c プロジェクト: caidongyun/libssh
/* this is a public key in openssh's format */
static ssh_string make_rsa1_string(ssh_string e, ssh_string n){
  ssh_buffer buffer = NULL;
  ssh_string rsa = NULL;
  ssh_string ret = NULL;

  buffer = ssh_buffer_new();
  rsa = ssh_string_from_char("ssh-rsa1");
  if (rsa == NULL) {
      goto error;
  }

  if (ssh_buffer_add_ssh_string(buffer, rsa) < 0) {
    goto error;
  }
  if (ssh_buffer_add_ssh_string(buffer, e) < 0) {
    goto error;
  }
  if (ssh_buffer_add_ssh_string(buffer, n) < 0) {
    goto error;
  }

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

  ssh_string_fill(ret, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer));
error:
  ssh_buffer_free(buffer);
  ssh_string_free(rsa);

  return ret;
}
コード例 #6
0
ファイル: pki.c プロジェクト: codinn/libssh
int ssh_pki_export_signature_blob(const ssh_signature sig,
                                  ssh_string *sig_blob)
{
    ssh_buffer buf = NULL;
    ssh_string str;
    int rc;

    if (sig == NULL || sig_blob == NULL) {
        return SSH_ERROR;
    }

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

    str = ssh_string_from_char(sig->type_c);
    if (str == NULL) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    rc = ssh_buffer_add_ssh_string(buf, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    str = pki_signature_to_blob(sig);
    if (str == NULL) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    rc = ssh_buffer_add_ssh_string(buf, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    str = ssh_string_new(ssh_buffer_get_len(buf));
    if (str == NULL) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
    ssh_buffer_free(buf);

    *sig_blob = str;

    return SSH_OK;
}
コード例 #7
0
ファイル: pki.c プロジェクト: codinn/libssh
ssh_string ssh_pki_do_sign_agent(ssh_session session,
                                 struct ssh_buffer_struct *buf,
                                 const ssh_key pubkey) {
    struct ssh_crypto_struct *crypto;
    ssh_string session_id;
    ssh_string sig_blob;
    ssh_buffer sig_buf;
    int rc;

    if (session->current_crypto) {
        crypto = session->current_crypto;
    } else {
        crypto = session->next_crypto;
    }

    /* prepend session identifier */
    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);

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

    rc = ssh_buffer_add_ssh_string(sig_buf, session_id);
    if (rc < 0) {
        ssh_string_free(session_id);
        ssh_buffer_free(sig_buf);
        return NULL;
    }
    ssh_string_free(session_id);

    /* append out buffer */
    if (ssh_buffer_add_buffer(sig_buf, buf) < 0) {
        ssh_buffer_free(sig_buf);
        return NULL;
    }

    /* create signature */
    sig_blob = ssh_agent_sign_data(session, pubkey, sig_buf);

    ssh_buffer_free(sig_buf);

    return sig_blob;
}
コード例 #8
0
ファイル: pki.c プロジェクト: rofl0r/libssh
/*
 * This function signs the session id (known as H) as a string then
 * the content of sigbuf */
ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf,
    ssh_key privatekey) {
    struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
        session->next_crypto;
    unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
    ssh_string session_str = NULL;
    ssh_string signature = NULL;
    struct signature_struct *sign = NULL;
    SHACTX ctx = NULL;

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

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

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

    sha1_update(ctx, session_str, ssh_string_len(session_str) + 4);
    ssh_string_free(session_str);
    sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
    sha1_final(hash + 1,ctx);
    hash[0] = 0;

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("Hash being signed with dsa", hash + 1, SHA_DIGEST_LEN);
#endif

    sign = pki_do_sign(privatekey, hash);
    if (sign == NULL) {
        return NULL;
    }

    signature = signature_to_string(sign);
    signature_free(sign);

    return signature;
}
コード例 #9
0
ファイル: keys.c プロジェクト: rofl0r/libssh
/**
 * @brief Convert a public_key object into a a SSH string.
 *
 * @param[in]  key      The public key to convert.
 *
 * @returns             An allocated SSH String containing the public key, NULL
 *                      on error.
 *
 * @see string_free()
 */
ssh_string publickey_to_string(ssh_public_key key) {
    ssh_string type = NULL;
    ssh_string ret = NULL;
    ssh_buffer buf = NULL;

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

    type = ssh_string_from_char(key->type_c);
    if (type == NULL) {
        goto error;
    }

    if (buffer_add_ssh_string(buf, type) < 0) {
        goto error;
    }

    switch (key->type) {
    case SSH_KEYTYPE_DSS:
        if (dsa_public_to_string(key->dsa_pub, buf) < 0) {
            goto error;
        }
        break;
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
        if (rsa_public_to_string(key->rsa_pub, buf) < 0) {
            goto error;
        }
        break;
    }

    ret = ssh_string_new(buffer_get_rest_len(buf));
    if (ret == NULL) {
        goto error;
    }

    ssh_string_fill(ret, buffer_get_rest(buf), buffer_get_rest_len(buf));
error:
    ssh_buffer_free(buf);
    if(type != NULL)
        ssh_string_free(type);

    return ret;
}
コード例 #10
0
ファイル: keys.c プロジェクト: rofl0r/libssh
ssh_string ssh_do_sign_with_agent(ssh_session session,
                                  struct ssh_buffer_struct *buf, struct ssh_public_key_struct *publickey) {
    struct ssh_buffer_struct *sigbuf = NULL;
    struct ssh_string_struct *signature = NULL;
    struct ssh_string_struct *session_id = NULL;
    struct ssh_crypto_struct *crypto = NULL;

    if (session->current_crypto) {
        crypto = session->current_crypto;
    } else {
        crypto = session->next_crypto;
    }

    /* prepend session identifier */
    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);

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

    if (buffer_add_ssh_string(sigbuf, session_id) < 0) {
        ssh_buffer_free(sigbuf);
        ssh_string_free(session_id);
        return NULL;
    }
    ssh_string_free(session_id);

    /* append out buffer */
    if (buffer_add_buffer(sigbuf, buf) < 0) {
        ssh_buffer_free(sigbuf);
        return NULL;
    }

    /* create signature */
    signature = agent_sign_data(session, sigbuf, publickey);

    ssh_buffer_free(sigbuf);

    return signature;
}
コード例 #11
0
ファイル: pki.c プロジェクト: 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;
}
コード例 #12
0
ファイル: keys.c プロジェクト: rofl0r/libssh
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
#elif defined HAVE_LIBCRYPTO
static int rsa_public_to_string(RSA *key, ssh_buffer buffer) {
#endif

    ssh_string e = NULL;
    ssh_string n = NULL;

    int rc = -1;

#ifdef HAVE_LIBGCRYPT
    const char *tmp;
    size_t size;
    gcry_sexp_t sexp;

    sexp = gcry_sexp_find_token(key, "n", 0);
    if (sexp == NULL) {
        goto error;
    }
    tmp = gcry_sexp_nth_data(sexp, 1, &size);
    n = ssh_string_new(size);
    if (n == NULL) {
        goto error;
    }
    ssh_string_fill(n, (char *) tmp, size);
    gcry_sexp_release(sexp);

    sexp = gcry_sexp_find_token(key, "e", 0);
    if (sexp == NULL) {
        goto error;
    }
    tmp = gcry_sexp_nth_data(sexp, 1, &size);
    e = ssh_string_new(size);
    if (e == NULL) {
        goto error;
    }
    ssh_string_fill(e, (char *) tmp, size);

#elif defined HAVE_LIBCRYPTO
    e = make_bignum_string(key->e);
    n = make_bignum_string(key->n);
    if (e == NULL || n == NULL) {
        goto error;
    }
#endif

    if (buffer_add_ssh_string(buffer, e) < 0) {
        goto error;
    }
    if (buffer_add_ssh_string(buffer, n) < 0) {
        goto error;
    }

    rc = 0;
error:
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(sexp);
#endif

    ssh_string_burn(e);
    ssh_string_free(e);
    ssh_string_burn(n);
    ssh_string_free(n);

    return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
}
コード例 #13
0
ファイル: keys.c プロジェクト: rofl0r/libssh
static int dsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
#elif defined HAVE_LIBCRYPTO
static int dsa_public_to_string(DSA *key, ssh_buffer buffer) {
#endif
    ssh_string p = NULL;
    ssh_string q = NULL;
    ssh_string g = NULL;
    ssh_string n = NULL;

    int rc = -1;

#ifdef HAVE_LIBGCRYPT
    const char *tmp = NULL;
    size_t size;
    gcry_sexp_t sexp;

    sexp = gcry_sexp_find_token(key, "p", 0);
    if (sexp == NULL) {
        goto error;
    }
    tmp = gcry_sexp_nth_data(sexp, 1, &size);
    p = ssh_string_new(size);
    if (p == NULL) {
        goto error;
    }
    ssh_string_fill(p, (char *) tmp, size);
    gcry_sexp_release(sexp);

    sexp = gcry_sexp_find_token(key, "q", 0);
    if (sexp == NULL) {
        goto error;
    }
    tmp = gcry_sexp_nth_data(sexp, 1, &size);
    q = ssh_string_new(size);
    if (q == NULL) {
        goto error;
    }
    ssh_string_fill(q, (char *) tmp, size);
    gcry_sexp_release(sexp);

    sexp = gcry_sexp_find_token(key, "g", 0);
    if (sexp == NULL) {
        goto error;
    }
    tmp = gcry_sexp_nth_data(sexp, 1, &size);
    g = ssh_string_new(size);
    if (g == NULL) {
        goto error;
    }
    ssh_string_fill(g, (char *) tmp, size);
    gcry_sexp_release(sexp);

    sexp = gcry_sexp_find_token(key, "y", 0);
    if (sexp == NULL) {
        goto error;
    }
    tmp = gcry_sexp_nth_data(sexp, 1, &size);
    n = ssh_string_new(size);
    if (n == NULL) {
        goto error;
    }
    ssh_string_fill(n, (char *) tmp, size);

#elif defined HAVE_LIBCRYPTO
    p = make_bignum_string(key->p);
    q = make_bignum_string(key->q);
    g = make_bignum_string(key->g);
    n = make_bignum_string(key->pub_key);
    if (p == NULL || q == NULL || g == NULL || n == NULL) {
        goto error;
    }
#endif /* HAVE_LIBCRYPTO */
    if (buffer_add_ssh_string(buffer, p) < 0) {
        goto error;
    }
    if (buffer_add_ssh_string(buffer, q) < 0) {
        goto error;
    }
    if (buffer_add_ssh_string(buffer, g) < 0) {
        goto error;
    }
    if (buffer_add_ssh_string(buffer, n) < 0) {
        goto error;
    }

    rc = 0;
error:
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(sexp);
#endif

    ssh_string_burn(p);
    ssh_string_free(p);
    ssh_string_burn(q);
    ssh_string_free(q);
    ssh_string_burn(g);
    ssh_string_free(g);
    ssh_string_burn(n);
    ssh_string_free(n);

    return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
}
コード例 #14
0
ファイル: keys.c プロジェクト: rofl0r/libssh
/**
 * @brief Make a public_key object out of a private_key object.
 *
 * @param[in]  prv      The private key to generate the public key.
 *
 * @returns             The generated public key, NULL on error.
 *
 * @see publickey_to_string()
 */
ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
    ssh_public_key key = NULL;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t sexp;
    const char *tmp = NULL;
    size_t size;
    ssh_string p = NULL;
    ssh_string q = NULL;
    ssh_string g = NULL;
    ssh_string y = NULL;
    ssh_string e = NULL;
    ssh_string n = NULL;
#endif /* HAVE_LIBGCRYPT */

    key = malloc(sizeof(struct ssh_public_key_struct));
    if (key == NULL) {
        return NULL;
    }
    ZERO_STRUCTP(key);
    key->type = prv->type;
    switch(key->type) {
    case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp, 1, &size);
        p = ssh_string_new(size);
        if (p == NULL) {
            goto error;
        }
        ssh_string_fill(p,(char *) tmp, size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->dsa_priv,"q",0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp,1,&size);
        q = ssh_string_new(size);
        if (q == NULL) {
            goto error;
        }
        ssh_string_fill(q,(char *) tmp,size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->dsa_priv, "g", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp,1,&size);
        g = ssh_string_new(size);
        if (g == NULL) {
            goto error;
        }
        ssh_string_fill(g,(char *) tmp,size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->dsa_priv,"y",0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp,1,&size);
        y = ssh_string_new(size);
        if (y == NULL) {
            goto error;
        }
        ssh_string_fill(y,(char *) tmp,size);
        gcry_sexp_release(sexp);

        gcry_sexp_build(&key->dsa_pub, NULL,
                        "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
                        ssh_string_len(p), ssh_string_data(p),
                        ssh_string_len(q), ssh_string_data(q),
                        ssh_string_len(g), ssh_string_data(g),
                        ssh_string_len(y), ssh_string_data(y));

        ssh_string_burn(p);
        ssh_string_free(p);
        ssh_string_burn(q);
        ssh_string_free(q);
        ssh_string_burn(g);
        ssh_string_free(g);
        ssh_string_burn(y);
        ssh_string_free(y);
#elif defined HAVE_LIBCRYPTO
        key->dsa_pub = DSA_new();
        if (key->dsa_pub == NULL) {
            goto error;
        }
        key->dsa_pub->p = BN_dup(prv->dsa_priv->p);
        key->dsa_pub->q = BN_dup(prv->dsa_priv->q);
        key->dsa_pub->g = BN_dup(prv->dsa_priv->g);
        key->dsa_pub->pub_key = BN_dup(prv->dsa_priv->pub_key);
        if (key->dsa_pub->p == NULL ||
                key->dsa_pub->q == NULL ||
                key->dsa_pub->g == NULL ||
                key->dsa_pub->pub_key == NULL) {
            goto error;
        }
#endif /* HAVE_LIBCRYPTO */
        break;
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(prv->rsa_priv, "n", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp, 1, &size);
        n = ssh_string_new(size);
        if (n == NULL) {
            goto error;
        }
        ssh_string_fill(n, (char *) tmp, size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->rsa_priv, "e", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp, 1, &size);
        e = ssh_string_new(size);
        if (e == NULL) {
            goto error;
        }
        ssh_string_fill(e, (char *) tmp, size);
        gcry_sexp_release(sexp);

        gcry_sexp_build(&key->rsa_pub, NULL,
                        "(public-key(rsa(n %b)(e %b)))",
                        ssh_string_len(n), ssh_string_data(n),
                        ssh_string_len(e), ssh_string_data(e));
        if (key->rsa_pub == NULL) {
            goto error;
        }

        ssh_string_burn(e);
        ssh_string_free(e);
        ssh_string_burn(n);
        ssh_string_free(n);
#elif defined HAVE_LIBCRYPTO
        key->rsa_pub = RSA_new();
        if (key->rsa_pub == NULL) {
            goto error;
        }
        key->rsa_pub->e = BN_dup(prv->rsa_priv->e);
        key->rsa_pub->n = BN_dup(prv->rsa_priv->n);
        if (key->rsa_pub->e == NULL ||
                key->rsa_pub->n == NULL) {
            goto error;
        }
#endif
        break;
    default:
        publickey_free(key);
        return NULL;
    }
    key->type_c = ssh_type_to_char(prv->type);

    return key;
error:
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(sexp);
    ssh_string_burn(p);
    ssh_string_free(p);
    ssh_string_burn(q);
    ssh_string_free(q);
    ssh_string_burn(g);
    ssh_string_free(g);
    ssh_string_burn(y);
    ssh_string_free(y);

    ssh_string_burn(e);
    ssh_string_free(e);
    ssh_string_burn(n);
    ssh_string_free(n);
#endif
    publickey_free(key);

    return NULL;
}
コード例 #15
0
ファイル: keys.c プロジェクト: rofl0r/libssh
ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key key) {
    ssh_string str = NULL;
    size_t len = ssh_string_len(data);
    size_t size = 0;
#ifdef HAVE_LIBGCRYPT
    const char *tmp = NULL;
    gcry_sexp_t ret_sexp;
    gcry_sexp_t data_sexp;

    if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(value %b))",
                        len, ssh_string_data(data))) {
        ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
        return NULL;
    }
    if (gcry_pk_encrypt(&ret_sexp, data_sexp, key->rsa_pub)) {
        gcry_sexp_release(data_sexp);
        ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
        return NULL;
    }

    gcry_sexp_release(data_sexp);

    data_sexp = gcry_sexp_find_token(ret_sexp, "a", 0);
    if (data_sexp == NULL) {
        ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
        gcry_sexp_release(ret_sexp);
        return NULL;
    }
    tmp = gcry_sexp_nth_data(data_sexp, 1, &size);
    if (*tmp == 0) {
        size--;
        tmp++;
    }

    str = ssh_string_new(size);
    if (str == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        gcry_sexp_release(data_sexp);
        gcry_sexp_release(ret_sexp);
        return NULL;
    }
    ssh_string_fill(str, tmp, size);

    gcry_sexp_release(data_sexp);
    gcry_sexp_release(ret_sexp);
#elif defined HAVE_LIBCRYPTO
    size = RSA_size(key->rsa_pub);

    str = ssh_string_new(size);
    if (str == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        return NULL;
    }

    if (RSA_public_encrypt(len, ssh_string_data(data), ssh_string_data(str), key->rsa_pub,
                           RSA_PKCS1_PADDING) < 0) {
        ssh_string_free(str);
        return NULL;
    }
#endif

    return str;
}
コード例 #16
0
ファイル: keys.c プロジェクト: rofl0r/libssh
/*
 * This function signs the session id (known as H) as a string then
 * the content of sigbuf */
ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
                       ssh_private_key privatekey) {
    struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
                                           session->next_crypto;
    unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
    ssh_string session_str = NULL;
    ssh_string signature = NULL;
    SIGNATURE *sign = NULL;
    SHACTX ctx = NULL;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t gcryhash;
#endif

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

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

    sha1_update(ctx, session_str, ssh_string_len(session_str) + 4);
    ssh_string_free(session_str);
    sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
    sha1_final(hash + 1,ctx);
    hash[0] = 0;

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("Hash being signed with dsa", hash + 1, SHA_DIGEST_LEN);
#endif

    sign = malloc(sizeof(SIGNATURE));
    if (sign == NULL) {
        return NULL;
    }
    ZERO_STRUCTP(sign);

    switch(privatekey->type) {
    case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN + 1, hash) ||
                gcry_pk_sign(&sign->dsa_sign, gcryhash, privatekey->dsa_priv)) {
            ssh_set_error(session, SSH_FATAL, "Signing: libcrypt error");
            gcry_sexp_release(gcryhash);
            signature_free(sign);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        sign->dsa_sign = DSA_do_sign(hash + 1, SHA_DIGEST_LEN,
                                     privatekey->dsa_priv);
        if (sign->dsa_sign == NULL) {
            ssh_set_error(session, SSH_FATAL, "Signing: openssl error");
            signature_free(sign);
            return NULL;
        }
#ifdef DEBUG_CRYPTO
        ssh_print_bignum("r", sign->dsa_sign->r);
        ssh_print_bignum("s", sign->dsa_sign->s);
#endif
#endif /* HAVE_LIBCRYPTO */
        sign->rsa_sign = NULL;
        break;
    case SSH_KEYTYPE_RSA:
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&gcryhash, NULL, "(data(flags pkcs1)(hash sha1 %b))",
                            SHA_DIGEST_LEN, hash + 1) ||
                gcry_pk_sign(&sign->rsa_sign, gcryhash, privatekey->rsa_priv)) {
            ssh_set_error(session, SSH_FATAL, "Signing: libcrypt error");
            gcry_sexp_release(gcryhash);
            signature_free(sign);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        sign->rsa_sign = RSA_do_sign(hash + 1, SHA_DIGEST_LEN,
                                     privatekey->rsa_priv);
        if (sign->rsa_sign == NULL) {
            ssh_set_error(session, SSH_FATAL, "Signing: openssl error");
            signature_free(sign);
            return NULL;
        }
#endif
        sign->dsa_sign = NULL;
        break;
    default:
        signature_free(sign);
        return NULL;
    }
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(gcryhash);
#endif

    sign->type = privatekey->type;

    signature = signature_to_string(sign);
    signature_free(sign);

    return signature;
}
コード例 #17
0
ファイル: curve25519.c プロジェクト: caidongyun/ssh-proxy
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
 * SSH_MSG_KEXDH_REPLY
 */
int ssh_server_curve25519_init(ssh_session_t * session, ssh_buffer_t * packet){
    /* ECDH keys */
    ssh_string_t * q_c_string;
    ssh_string_t * q_s_string;

    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key_t * privkey;
    ssh_string_t * sig_blob = NULL;
    int rc;

    /* Extract the client pubkey from the init packet */
    q_c_string = 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;
    }
    if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
    	ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
    			(int)ssh_string_len(q_c_string));
    	ssh_string_free(q_c_string);
    	return SSH_ERROR;
    }

    memcpy(session->next_crypto->curve25519_client_pubkey,
    		ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
    ssh_string_free(q_c_string);
    /* Build server's keypair */

    rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
    if (rc == 0){
        ssh_set_error(session, SSH_FATAL, "PRNG error");
        return SSH_ERROR;
    }

    crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
  		  session->next_crypto->curve25519_privkey);

    rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    /* build k and session_id */
    rc = ssh_curve25519_build_k(session);
    if (rc < 0) {
        ssh_set_error(session, SSH_FATAL, "Cannot build k number");
        goto error;
    }

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

    rc = make_sessionid(session);
    if (rc != SSH_OK) {
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
        goto error;
    }

    /* add host's public key */
    rc = buffer_add_ssh_string(session->out_buffer,
                               session->next_crypto->server_pubkey);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    /* add ecdh public key */
    q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
    if (q_s_string == NULL) {
        goto error;
    }

    ssh_string_fill(q_s_string,
                    session->next_crypto->curve25519_server_pubkey,
                    CURVE25519_PUBKEY_SIZE);

    rc = buffer_add_ssh_string(session->out_buffer, q_s_string);
    ssh_string_free(q_s_string);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }
    /* add signature blob */
    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");
        goto error;
    }

    rc = buffer_add_ssh_string(session->out_buffer, sig_blob);
    ssh_string_free(sig_blob);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent");
    rc = packet_send(session);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

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

    session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
    rc = packet_send(session);
    SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");

    return rc;
error:
    buffer_reinit(session->out_buffer);
    return SSH_ERROR;
}
コード例 #18
0
ファイル: messages.c プロジェクト: magnum/tmate
/*
 * This function concats in a buffer the values needed to do a signature
 * verification.
 */
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
                                                ssh_message msg,
                                                const char *service)
{
    struct ssh_crypto_struct *crypto =
        session->current_crypto ? session->current_crypto :
                                  session->next_crypto;
    ssh_buffer buffer;
    ssh_string str;
    int rc;

    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        return NULL;
    }

    /* Add session id */
    str  = ssh_string_new(crypto->digest_len);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    ssh_string_fill(str, crypto->session_id, crypto->digest_len);

    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the type */
    rc = buffer_add_u8(buffer, SSH2_MSG_USERAUTH_REQUEST);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the username */
    str = ssh_string_from_char(msg->auth_request.username);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the service name */
    str = ssh_string_from_char(service);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the method (publickey) */
    str = ssh_string_from_char("publickey");
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Has been signed (TRUE) */
    rc = buffer_add_u8(buffer, 1);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the public key algorithm */
    str = ssh_string_from_char(msg->auth_request.pubkey->type_c);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the publickey as blob */
    rc = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    return buffer;
}
コード例 #19
0
ファイル: legacy.c プロジェクト: rofl0r/libssh
int string_fill(ssh_string str, const void *data, size_t len){
  return ssh_string_fill(str,data,len);
}
コード例 #20
0
ファイル: keys.c プロジェクト: rofl0r/libssh
/* Signature decoding functions */
ssh_string signature_to_string(SIGNATURE *sign) {
    unsigned char buffer[40] = {0};
    ssh_buffer tmpbuf = NULL;
    ssh_string str = NULL;
    ssh_string tmp = NULL;
    ssh_string rs = NULL;
    int rc = -1;
#ifdef HAVE_LIBGCRYPT
    const char *r = NULL;
    const char *s = NULL;
    gcry_sexp_t sexp;
    size_t size = 0;
#elif defined HAVE_LIBCRYPTO
    ssh_string r = NULL;
    ssh_string s = NULL;
#endif

    tmpbuf = ssh_buffer_new();
    if (tmpbuf == NULL) {
        return NULL;
    }

    tmp = ssh_string_from_char(ssh_type_to_char(sign->type));
    if (tmp == NULL) {
        ssh_buffer_free(tmpbuf);
        return NULL;
    }
    if (buffer_add_ssh_string(tmpbuf, tmp) < 0) {
        ssh_buffer_free(tmpbuf);
        ssh_string_free(tmp);
        return NULL;
    }
    ssh_string_free(tmp);

    switch(sign->type) {
    case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(sign->dsa_sign, "r", 0);
        if (sexp == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        r = gcry_sexp_nth_data(sexp, 1, &size);
        if (*r == 0) {      /* libgcrypt put 0 when first bit is set */
            size--;
            r++;
        }
        memcpy(buffer, r + size - 20, 20);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(sign->dsa_sign, "s", 0);
        if (sexp == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        s = gcry_sexp_nth_data(sexp,1,&size);
        if (*s == 0) {
            size--;
            s++;
        }
        memcpy(buffer+ 20, s + size - 20, 20);
        gcry_sexp_release(sexp);
#elif defined HAVE_LIBCRYPTO
        r = make_bignum_string(sign->dsa_sign->r);
        if (r == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        s = make_bignum_string(sign->dsa_sign->s);
        if (s == NULL) {
            ssh_buffer_free(tmpbuf);
            ssh_string_free(r);
            return NULL;
        }

        memcpy(buffer, (char *)ssh_string_data(r) + ssh_string_len(r) - 20, 20);
        memcpy(buffer + 20, (char *)ssh_string_data(s) + ssh_string_len(s) - 20, 20);

        ssh_string_free(r);
        ssh_string_free(s);
#endif /* HAVE_LIBCRYPTO */
        rs = ssh_string_new(40);
        if (rs == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }

        ssh_string_fill(rs, buffer, 40);
        rc = buffer_add_ssh_string(tmpbuf, rs);
        ssh_string_free(rs);
        if (rc < 0) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }

        break;
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(sign->rsa_sign, "s", 0);
        if (sexp == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        s = gcry_sexp_nth_data(sexp,1,&size);
        if (*s == 0) {
            size--;
            s++;
        }
        rs = ssh_string_new(size);
        if (rs == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }

        ssh_string_fill(rs, (char *) s, size);
        rc = buffer_add_ssh_string(tmpbuf, rs);
        gcry_sexp_release(sexp);
        ssh_string_free(rs);
        if (rc < 0) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        if (buffer_add_ssh_string(tmpbuf,sign->rsa_sign) < 0) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
#endif
        break;
    }

    str = ssh_string_new(buffer_get_rest_len(tmpbuf));
    if (str == NULL) {
        ssh_buffer_free(tmpbuf);
        return NULL;
    }
    ssh_string_fill(str, buffer_get_rest(tmpbuf), buffer_get_rest_len(tmpbuf));
    ssh_buffer_free(tmpbuf);

    return str;
}
コード例 #21
0
ファイル: auth1.c プロジェクト: caidongyun/libssh
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;
}
コード例 #22
0
ファイル: keys.c プロジェクト: rofl0r/libssh
/* TODO : split this function in two so it becomes smaller */
SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
                                 ssh_public_key pubkey, int needed_type) {
    SIGNATURE *sign = NULL;
    ssh_buffer tmpbuf = NULL;
    ssh_string rs = NULL;
    ssh_string type_s = NULL;
    ssh_string e = NULL;
    char *type_c = NULL;
    int type;
    int len;
    int rsalen;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t sig;
#elif defined HAVE_LIBCRYPTO
    DSA_SIG *sig = NULL;
    ssh_string r = NULL;
    ssh_string s = NULL;
#endif

    sign = malloc(sizeof(SIGNATURE));
    if (sign == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        return NULL;
    }
    ZERO_STRUCTP(sign);

    tmpbuf = ssh_buffer_new();
    if (tmpbuf == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        signature_free(sign);
        return NULL;
    }

    if (buffer_add_data(tmpbuf, ssh_string_data(signature), ssh_string_len(signature)) < 0) {
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }

    type_s = buffer_get_ssh_string(tmpbuf);
    if (type_s == NULL) {
        ssh_set_error(session, SSH_FATAL, "Invalid signature packet");
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }

    type_c = ssh_string_to_char(type_s);
    ssh_string_free(type_s);
    if (type_c == NULL) {
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }
    type = ssh_type_from_name(type_c);
    SAFE_FREE(type_c);

    if (needed_type != type) {
        ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s",
                      ssh_type_to_char(type));
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }

    switch(needed_type) {
    case SSH_KEYTYPE_DSS:
        rs = buffer_get_ssh_string(tmpbuf);
        ssh_buffer_free(tmpbuf);

        /* 40 is the dual signature blob len. */
        if (rs == NULL || ssh_string_len(rs) != 40) {
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }

        /* we make use of strings (because we have all-made functions to convert
         * them to bignums (ou pas ;) */
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
                            20 ,ssh_string_data(rs), 20,(unsigned char *)ssh_string_data(rs) + 20)) {
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        r = ssh_string_new(20);
        s = ssh_string_new(20);
        if (r == NULL || s == NULL) {
            ssh_string_free(r);
            ssh_string_free(s);
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }

        ssh_string_fill(r, ssh_string_data(rs), 20);
        ssh_string_fill(s, (char *)ssh_string_data(rs) + 20, 20);

        sig = DSA_SIG_new();
        if (sig == NULL) {
            ssh_string_free(r);
            ssh_string_free(s);
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }
        sig->r = make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */
        sig->s = make_string_bn(s);
        ssh_string_free(r);
        ssh_string_free(s);

        if (sig->r == NULL || sig->s == NULL) {
            ssh_string_free(rs);
            DSA_SIG_free(sig);
            signature_free(sign);
            return NULL;
        }
#endif

#ifdef DEBUG_CRYPTO
        ssh_print_hexa("r", ssh_string_data(rs), 20);
        ssh_print_hexa("s", (const unsigned char *)ssh_string_data(rs) + 20, 20);
#endif
        ssh_string_free(rs);

        sign->type = SSH_KEYTYPE_DSS;
        sign->dsa_sign = sig;

        return sign;
    case SSH_KEYTYPE_RSA:
        e = buffer_get_ssh_string(tmpbuf);
        ssh_buffer_free(tmpbuf);
        if (e == NULL) {
            signature_free(sign);
            return NULL;
        }
        len = ssh_string_len(e);
#ifdef HAVE_LIBGCRYPT
        rsalen = (gcry_pk_get_nbits(pubkey->rsa_pub) + 7) / 8;
#elif defined HAVE_LIBCRYPTO
        rsalen = RSA_size(pubkey->rsa_pub);
#endif
        if (len > rsalen) {
            ssh_string_free(e);
            signature_free(sign);
            ssh_set_error(session, SSH_FATAL, "Signature too big! %d instead of %d",
                          len, rsalen);
            return NULL;
        }

        if (len < rsalen) {
            ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d",
                    len, rsalen);
        }
        sign->type = SSH_KEYTYPE_RSA;
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
                            ssh_string_len(e), ssh_string_data(e))) {
            signature_free(sign);
            ssh_string_free(e);
            return NULL;
        }

        sign->rsa_sign = sig;
#elif defined HAVE_LIBCRYPTO
        sign->rsa_sign = e;
#endif

#ifdef DEBUG_CRYPTO
        ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len);
        ssh_print_hexa("RSA signature", ssh_string_data(e), len);
#endif

#ifdef HAVE_LIBGCRYPT
        ssh_string_free(e);
#endif

        return sign;
    default:
        return NULL;
    }

    return NULL;
}
コード例 #23
0
ファイル: gssapi.c プロジェクト: alexislitool/tmate
static ssh_buffer ssh_gssapi_build_mic(ssh_session session){
    ssh_buffer mic_buffer;
    ssh_string str;
    int rc;

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

    mic_buffer = ssh_buffer_new();
    if (mic_buffer == NULL) {
        ssh_string_free(str);
        return NULL;
    }

    rc = buffer_add_ssh_string(mic_buffer, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    rc = buffer_add_u8(mic_buffer, SSH2_MSG_USERAUTH_REQUEST);
    if (rc < 0) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    str = ssh_string_from_char(session->gssapi->user);
    if (str == NULL) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    rc = buffer_add_ssh_string(mic_buffer, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    str = ssh_string_from_char("ssh-connection");
    if (str == NULL) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(mic_buffer, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    str = ssh_string_from_char("gssapi-with-mic");
    if (str == NULL) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    rc = buffer_add_ssh_string(mic_buffer, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(mic_buffer);
        return NULL;
    }

    return mic_buffer;
}