Esempio n. 1
0
/*
 * Check if any clock skew policy matches
 */
static void
get_clock_skew(val_context_t *ctx,
               u_char *name_n,
               int *skew,
               u_int32_t *ttl_x)
{
    policy_entry_t *cs_pol, *cs_cur;
    u_char       *p;
    size_t       name_len;

    if (ctx == NULL || name_n == NULL || skew == NULL || ttl_x == NULL) {
        val_log(ctx, LOG_DEBUG, "get_clock_skew(): Cannot check for clock skew policy, bad args"); 
        return; 
    }
    
    RETRIEVE_POLICY(ctx, P_CLOCK_SKEW, cs_pol);
    if (cs_pol) {

        name_len = wire_name_length(name_n);

        for (cs_cur = cs_pol;
             cs_cur && (wire_name_length(cs_cur->zone_n) > name_len);
             cs_cur = cs_cur->next);
        /*
         * for all zones which are shorter or as long, do a strstr 
         */
        /*
         * Because of the ordering, the longest match is found first 
         */
        for (; cs_cur; cs_cur = cs_cur->next) {
            int             root_zone = 0;
            if (!namecmp(cs_cur->zone_n, (const u_char *) ""))
                root_zone = 1;
            else {
                /*
                 * Find the last occurrence of cs_cur->zone_n in name_n 
                 */
                p = name_n;
                while (p && (*p != '\0')) {
                    if (!namecmp(p, cs_cur->zone_n))
                        break;
                    p = p + *p + 1;
                }
            }
            if (root_zone || (!namecmp(p, cs_cur->zone_n))) {
                val_log(ctx, LOG_DEBUG, "get_clock_skew(): Found clock skew policy"); 
                if (cs_cur->pol) {
                    *skew = ((struct clock_skew_policy *)(cs_cur->pol))->clock_skew;
                    if (cs_cur->exp_ttl > 0)
                        *ttl_x = cs_cur->exp_ttl;
                    return;
                }
            }
        }
    }
    val_log(ctx, LOG_DEBUG, "get_clock_skew(): No clock skew policy found"); 
    *skew = 0;
}
static void
endless_loop(void)
{
    val_context_t *context;

    /*
     * signal handlers to exit gracefully
     */
#ifdef SIGTERM
    signal(SIGTERM, sig_shutdown);
#endif
#ifdef SIGINT
    signal(SIGINT, sig_shutdown);
#endif

    /*
     * open a port and process incoming packets
     */
    port_setup(1153);
    if (VAL_NO_ERROR != val_create_context(NULL, &context)) {
        val_log(NULL, LOG_ERR, "Cannot create validator context. Exiting.");
        return;
    }

    while (!done) {
        wait_for_packet();
        process_packet(context);
    }

    val_free_context(context);

    val_free_validator_state();
}
Esempio n. 3
0
void
val_log_rrsig_rdata(const val_context_t * ctx, int level,
                    const char *prefix, val_rrsig_rdata_t * rdata)
{
    char            ctime_buf1[1028], ctime_buf2[1028];
    char            buf[1028];
    struct timeval  tv_sig1, tv_sig2;

    if (rdata) {
        if (!prefix)
            prefix = "";

        memset(&tv_sig1, 0, sizeof(tv_sig1));
        memset(&tv_sig2, 0, sizeof(tv_sig2));
        tv_sig1.tv_sec = rdata->sig_expr; 
        tv_sig2.tv_sec = rdata->sig_incp; 

        GET_TIME_BUF((const time_t *)(&tv_sig1.tv_sec), ctime_buf1);
        GET_TIME_BUF((const time_t *)(&tv_sig2.tv_sec), ctime_buf2);

        val_log(ctx, level, "%s Type=%d Algo=%d[%s] Labels=%d OrgTTL=%d "
                "SigExp=%s SigIncp=%s KeyTag=%d[0x %04x] Signer=%s Sig=%s",
                prefix, rdata->algorithm,
                get_algorithm_string(rdata->algorithm), rdata->labels,
                rdata->orig_ttl,
                ctime_buf1, ctime_buf2,
                rdata->key_tag, rdata->key_tag, rdata->signer_name,
                get_base64_string(rdata->signature, rdata->signature_len,
                                  buf, 1024));
    }
}
Esempio n. 4
0
/*
 * wrapper around the DS comparison function
 */
int
ds_hash_is_equal(val_context_t *ctx,
                 u_char ds_hashtype, u_char * ds_hash,
                 size_t ds_hash_len, u_char * name_n,
                 struct rrset_rr *dnskey, val_astatus_t * ds_status)
{
    if ((dnskey == NULL) || (ds_hash == NULL) || (name_n == NULL)) {
        val_log(ctx, LOG_INFO, "ds_hash_is_equal(): Cannot compare DS data - invalid content");
        return 0;
    }

    /*
     * Only SHA-1 is understood 
     */
    if (ds_hashtype == ALG_DS_HASH_SHA1) {
        return ds_sha_hash_is_equal(name_n, dnskey->rr_rdata,
                                    (size_t)dnskey->rr_rdata_length, 
                                    ds_hash, ds_hash_len);

    } 

#ifdef HAVE_SHA_2
    else if (ds_hashtype == ALG_DS_HASH_SHA256) {
        return ds_sha256_hash_is_equal(name_n, dnskey->rr_rdata,
                                       (size_t)dnskey->rr_rdata_length, 
                                       ds_hash, ds_hash_len);
    } 
    else if (ds_hashtype == ALG_DS_HASH_SHA384) {
        return ds_sha384_hash_is_equal(name_n, dnskey->rr_rdata,
                                       (size_t)dnskey->rr_rdata_length, 
                                       ds_hash, ds_hash_len);
    } 
#endif

    /* else */

    *ds_status = VAL_AC_ALGORITHM_NOT_SUPPORTED;
    val_log(ctx, LOG_INFO, "ds_hash_is_equal(): Unsupported DS hash algorithm");
    return 0;
}
Esempio n. 5
0
void
rsamd5_sigverify(val_context_t * ctx,
                 const u_char *data,
                 size_t data_len,
                 const val_dnskey_rdata_t * dnskey,
                 const val_rrsig_rdata_t * rrsig,
                 val_astatus_t * key_status, val_astatus_t * sig_status)
{
    char            buf[1028];
    size_t          buflen = 1024;
    RSA            *rsa = NULL;
    u_char   md5_hash[MD5_DIGEST_LENGTH];

    val_log(ctx, LOG_DEBUG,
            "rsamd5_sigverify(): parsing the public key...");
    if ((rsa = RSA_new()) == NULL) {
        val_log(ctx, LOG_INFO,
                "rsamd5_sigverify(): could not allocate rsa structure.");
        *key_status = VAL_AC_INVALID_KEY;
        return;
    };

    if (rsamd5_parse_public_key(dnskey->public_key, dnskey->public_key_len,
                                rsa) != VAL_NO_ERROR) {
        val_log(ctx, LOG_INFO,
                "rsamd5_sigverify(): Error in parsing public key.");
        RSA_free(rsa);
        *key_status = VAL_AC_INVALID_KEY;
        return;
    }

    memset(md5_hash, 0, MD5_DIGEST_LENGTH);
    MD5(data, data_len, (u_char *) md5_hash);
    val_log(ctx, LOG_DEBUG, "rsamd5_sigverify(): MD5 hash = %s",
            get_hex_string(md5_hash, MD5_DIGEST_LENGTH, buf, buflen));

    val_log(ctx, LOG_DEBUG,
            "rsamd5_sigverify(): verifying RSA signature...");

    if (RSA_verify(NID_md5, (u_char *) md5_hash, MD5_DIGEST_LENGTH,
                   rrsig->signature, rrsig->signature_len, rsa) == 1) {
        val_log(ctx, LOG_INFO, "rsamd5_sigverify(): returned SUCCESS");
        RSA_free(rsa);
        *sig_status = VAL_AC_RRSIG_VERIFIED;
    } else {
        val_log(ctx, LOG_INFO, "rsamd5_sigverify(): returned FAILURE");
        RSA_free(rsa);
        *sig_status = VAL_AC_RRSIG_VERIFY_FAILED;
    }
    return;
}
Esempio n. 6
0
static int 
_callback(void *callback_data, int eai_retval, struct addrinfo *res,
          val_status_t val_status)
{
    struct getaddr_s *gas = (struct getaddr_s*)callback_data;

    *gas->retval = eai_retval;
    *gas->ainfo = res;
    *gas->vstatus = val_status;
    gas->done = 1;

    val_log(NULL, LOG_DEBUG, "_callback %p %d %p %d\n", callback_data, eai_retval, res,
           val_status);

    return 0; /* OK */
}
Esempio n. 7
0
void
val_log_dnskey_rdata(val_context_t * ctx, int level, const char *prefix,
                     val_dnskey_rdata_t * rdata)
{
    char            buf[1028];
    if (rdata) {
        if (!prefix)
            prefix = "";
        val_log(ctx, level,
                "%s Flags=%d Prot=%d Algo=%d[%s] KeyTag=%d[0x %04x] PK=%s",
                prefix, rdata->flags, rdata->protocol, rdata->algorithm,
                get_algorithm_string(rdata->algorithm), rdata->key_tag,
                rdata->key_tag, get_base64_string(rdata->public_key,
                                                  rdata->public_key_len,
                                                  buf, 1024));
    }
}
Esempio n. 8
0
void
val_log_val_rrset_pfx(const val_context_t * ctx, int level,
                      const char *pfx, struct val_rrset_rec *val_rrset_rec)
{
    char            buf1[2049], buf2[2049];

    if (!val_rrset_rec)
        return;

    val_log(ctx, level, "%srrs->val_rrset_name=%s rrs->val_rrset_type=%s "
            "rrs->val_rrset_class=%s rrs->val_rrset_ttl=%d "
            "rrs->val_rrset_section=%s\nrrs->val_rrset_data=%s\n"
            "rrs->val_rrset_sig=%s", pfx ? pfx : "", 
            val_rrset_rec->val_rrset_name,
            p_type(val_rrset_rec->val_rrset_type),
            p_class(val_rrset_rec->val_rrset_class),
            val_rrset_rec->val_rrset_ttl,
            p_section(val_rrset_rec->val_rrset_section - 1, !ns_o_update),
            get_rr_string(val_rrset_rec->val_rrset_data, buf1, 2048),
            get_rr_string(val_rrset_rec->val_rrset_sig, buf2, 2048));
}
Esempio n. 9
0
static int 
_danecallback(void *callback_data, 
          int dane_rc, 
          struct val_danestatus **res)
{
    struct dane_cb *dcb = (struct dane_cb *)callback_data;

    *dcb->retval = dane_rc;
    if (res != NULL) {
        *dcb->danestatus = *res;
        *res = NULL;
    }
    else
        *dcb->danestatus = NULL;
    dcb->done = 1;

    val_log(NULL, LOG_DEBUG, "_danecallback %p %d %p\n", 
            callback_data, dane_rc, res);

    return 0; /* OK */
}
Esempio n. 10
0
int
val_get_rrset(val_context_t *context,
              const char *name,
              int class_h,
              int type_h,
              u_int32_t flags,
              struct val_answer_chain **answers) 
{
    struct val_result_chain *results = NULL;
    int retval = VAL_NO_ERROR;
    val_context_t *ctx = NULL;
    
    if (name == NULL || answers == NULL) {
        return VAL_BAD_ARGUMENT;
    }

    ctx = val_create_or_refresh_context(context);/* does CTX_LOCK_POL_SH */
    if (ctx == NULL)
        return VAL_INTERNAL_ERROR;

    if ((retval = val_resolve_and_check(ctx, name, class_h, type_h, 
                                       flags,
                                       &results)) != VAL_NO_ERROR) {
        val_log(ctx, LOG_INFO,
                "get_addrinfo_from_dns(): val_resolve_and_check failed - %s",
                p_val_err(retval));
        goto err; 
    }

    retval = val_get_answer_from_result(ctx, name, class_h, type_h, &results,
                                        answers, 0);

err:
    CTX_UNLOCK_POL(ctx);
    return retval;
} 
Esempio n. 11
0
void
dsasha1_sigverify(val_context_t * ctx,
                  const u_char *data,
                  size_t data_len,
                  const val_dnskey_rdata_t * dnskey,
                  const val_rrsig_rdata_t * rrsig,
                  val_astatus_t * key_status, val_astatus_t * sig_status)
{
    char            buf[1028];
    size_t          buflen = 1024;
    DSA            *dsa = NULL;
    u_char   sha1_hash[SHA_DIGEST_LENGTH];
    u_char   sig_asn1[2+2*(3+SHA_DIGEST_LENGTH)];

    val_log(ctx, LOG_DEBUG,
            "dsasha1_sigverify(): parsing the public key...");
    if ((dsa = DSA_new()) == NULL) {
        val_log(ctx, LOG_INFO,
                "dsasha1_sigverify(): could not allocate dsa structure.");
        *key_status = VAL_AC_INVALID_KEY;
        return;
    };

    if (dsasha1_parse_public_key
        (dnskey->public_key, dnskey->public_key_len,
         dsa) != VAL_NO_ERROR) {
        val_log(ctx, LOG_INFO,
                "dsasha1_sigverify(): Error in parsing public key.");
        DSA_free(dsa);
        *key_status = VAL_AC_INVALID_KEY;
        return;
    }

    memset(sha1_hash, 0, SHA_DIGEST_LENGTH);
    SHA1(data, data_len, sha1_hash);
    val_log(ctx, LOG_DEBUG, "dsasha1_sigverify(): SHA-1 hash = %s",
            get_hex_string(sha1_hash, SHA_DIGEST_LENGTH, buf, buflen));

    val_log(ctx, LOG_DEBUG,
            "dsasha1_sigverify(): verifying DSA signature...");

    /*
     * Fix: courtesy tom.fowler
     * First convert the signature into its DER representation
     *  0x30, 0x2E,       -  ASN1 sequence 
     *   0x02, 0x15,      - ASN integer, length 21 bytes
     *   0x00, <R bytes>  - 1 + 20 bytes per 2536 
     *   0x02, 0x15,      - ASN integer 
     *   0x00, <S bytes>  - 1 + 20 bytes per 2536
     */
    if (rrsig->signature_len < (1 + 2*SHA_DIGEST_LENGTH)) {
        /* dont have enough data */
        val_log(ctx, LOG_INFO,
                "dsasha1_sigverify(): Error parsing DSA rrsig.");
        DSA_free(dsa);
        *sig_status = VAL_AC_INVALID_RRSIG;
        return;
    }
    memcpy(sig_asn1, "\x30\x2E\x02\x15\x00", 5);
    memcpy(sig_asn1+5, rrsig->signature+1, SHA_DIGEST_LENGTH);
    memcpy(sig_asn1+5+SHA_DIGEST_LENGTH, "\x02\x15\x00", 3);
    memcpy(sig_asn1+5+SHA_DIGEST_LENGTH+3,
           rrsig->signature+1+SHA_DIGEST_LENGTH, SHA_DIGEST_LENGTH);

    if (DSA_verify
        (NID_sha1, (u_char *) sha1_hash, SHA_DIGEST_LENGTH,
         sig_asn1, sizeof(sig_asn1), dsa)  == 1) {
        val_log(ctx, LOG_INFO, "dsasha1_sigverify(): returned SUCCESS");
        DSA_free(dsa);
        *sig_status = VAL_AC_RRSIG_VERIFIED;
    } else {
        val_log(ctx, LOG_INFO, "dsasha1_sigverify(): returned FAILURE");
        DSA_free(dsa);
        *sig_status = VAL_AC_RRSIG_VERIFY_FAILED;
    }
    return;
}
Esempio n. 12
0
void
val_log_authentication_chain(const val_context_t * ctx, int level,
                             const char * name_p, int class_h,
                             int type_h,
                             struct val_result_chain *results)
{
    struct val_result_chain *next_result;
    int real_type_h;
    int real_class_h;

    if (results == NULL) { 
        return;
    } 
    
    for (next_result = results; next_result;
         next_result = next_result->val_rc_next) {
        struct val_authentication_chain *next_as;
        int             i;

        /* Display the correct owner name, class,type for the record */
        if (next_result->val_rc_rrset) {
            real_type_h = next_result->val_rc_rrset->val_rrset_type; 
            real_class_h = next_result->val_rc_rrset->val_rrset_class; 
        } else {
            real_type_h = type_h;
            real_class_h = class_h;
        }

        if (val_isvalidated(next_result->val_rc_status)) {
            val_log(ctx, level, "Validation result for {%s, %s(%d), %s(%d)}: %s:%d (Validated)",
                    name_p, p_class(real_class_h), real_class_h,
                    p_type(real_type_h), real_type_h,
                    p_val_status(next_result->val_rc_status),
                    next_result->val_rc_status);
        } else if (val_istrusted(next_result->val_rc_status)) {
            val_log(ctx, level, "Validation result for {%s, %s(%d), %s(%d)}: %s:%d (Trusted but not Validated)",
                    name_p, p_class(real_class_h), real_class_h,
                    p_type(real_type_h), real_type_h,
                    p_val_status(next_result->val_rc_status),
                    next_result->val_rc_status);
        } else {
            val_log(ctx, level, "Validation result for {%s, %s(%d), %s(%d)}: %s:%d (Untrusted)",
                    name_p, p_class(real_class_h), real_class_h,
                    p_type(real_type_h), real_type_h,
                    p_val_status(next_result->val_rc_status),
                    next_result->val_rc_status);
        }

        for (next_as = next_result->val_rc_answer; next_as;
             next_as = next_as->val_ac_trust) {

            if (next_as->val_ac_rrset == NULL) {
                val_log(ctx, level, "    Assertion status = %s:%d",
                        p_ac_status(next_as->val_ac_status),
                        next_as->val_ac_status);
            } else {
                const char   *t_name;
                t_name = next_as->val_ac_rrset->val_rrset_name;
                if (t_name == NULL)
                    t_name = (const char *) "NULL_DATA";

                val_log_assertion_pfx(ctx, level, "    ", t_name,
                                      next_as);
                //                val_log_val_rrset_pfx(ctx, level, "     ",
                //                                  next_as->val_ac_rrset);
            }
        }

        for (i = 0; i < next_result->val_rc_proof_count; i++) {
            val_log(ctx, level, "    Proof of non-existence [%d of %d]", 
                    i+1, next_result->val_rc_proof_count);
            for (next_as = next_result->val_rc_proofs[i]; next_as;
                 next_as = next_as->val_ac_trust) {
                if (next_as->val_ac_rrset == NULL) {
                    val_log(ctx, level, "      Assertion status = %s:%d",
                            p_ac_status(next_as->val_ac_status),
                            next_as->val_ac_status);
                } else {
                    const char   *t_name;
                    t_name = next_as->val_ac_rrset->val_rrset_name;
                    if (t_name == NULL)
                        t_name = (const char *) "NULL_DATA";

                    val_log_assertion_pfx(ctx, level, "      ", t_name,
                                          next_as);
                }
            }
        }
    }
}
Esempio n. 13
0
void
val_log_assertion_pfx(const val_context_t * ctx, int level,
                      const char *prefix, const char * name_pr,
                      struct val_authentication_chain *next_as)
{
    char            name_buf[INET6_ADDRSTRLEN + 1];
    const char     *serv_pr;
    int             tag = 0;
    int             class_h;
    int             type_h;
    struct          val_rr_rec  *data;
    struct          sockaddr *serv;
    val_astatus_t   status;
    struct val_rr_rec  *curkey;
#undef VAL_LOG_SIG
#ifdef VAL_LOG_SIG
    struct          val_rr_rec  *sig;
    struct val_rr_rec  *cursig;
#endif


    if (next_as == NULL)
        return;

    class_h = next_as->val_ac_rrset->val_rrset_class;
    type_h = next_as->val_ac_rrset->val_rrset_type;
    data = next_as->val_ac_rrset->val_rrset_data;
#ifdef VAL_LOG_SIG
    sig = next_as->val_ac_rrset->val_rrset_sig;
#endif
    serv = next_as->val_ac_rrset->val_rrset_server;
    status = next_as->val_ac_status;

    if (NULL == prefix)
        prefix = "";

    if (serv)
        serv_pr =
            ((serv_pr =
              val_get_ns_string(serv, name_buf, sizeof(name_buf))) == NULL) ?  "VAL_CACHE" : serv_pr;
    else
        serv_pr = "NULL";

    if (type_h == ns_t_dnskey) {
        for (curkey = data; curkey; curkey = curkey->rr_next) {
            if ((curkey->rr_status == VAL_AC_VERIFIED_LINK) ||
                (curkey->rr_status == VAL_AC_TRUST_POINT) ||
                (curkey->rr_status == VAL_AC_UNKNOWN_ALGORITHM_LINK)) {
                /*
                 * Extract the key tag 
                 */
                val_dnskey_rdata_t dnskey;
                if (VAL_NO_ERROR != val_parse_dnskey_rdata(curkey->rr_rdata,
                                       curkey->rr_rdata_length, &dnskey)) {
                    val_log(ctx, LOG_INFO, "val_log_assertion_pfx(): Cannot parse DNSKEY data");
                } else {
                    tag = dnskey.key_tag;
                    if (dnskey.public_key)
                        FREE(dnskey.public_key);
                }
                break;
            }
        }
    }

    if (tag != 0) {
        val_log(ctx, level,
                "%sname=%s class=%s type=%s[tag=%d] from-server=%s "
                "status=%s:%d", prefix, name_pr, p_class(class_h),
                p_type(type_h), tag, serv_pr, p_ac_status(status), status);
    } else {
        val_log(ctx, level,
                "%sname=%s class=%s type=%s from-server=%s status=%s:%d",
                prefix, name_pr, p_class(class_h), p_type(type_h), serv_pr,
                p_ac_status(status), status);
    }
#ifdef VAL_LOG_SIG
    for (cursig = sig; cursig; cursig = cursig->rr_next) {
        char incpTime[1028];
        char exprTime[1028];
        struct timeval  tv_sig;
        val_rrsig_rdata_t rrsig;

        val_parse_rrsig_rdata(cursig->rr_rdata, cursig->rr_rdata_length, &rrsig);

        memset(&tv_sig, 0, sizeof(tv_sig));
        tv_sig.tv_sec = rrsig.sig_incp;
        GET_TIME_BUF((const time_t *)(&tv_sig.tv_sec), incpTime);

        memset(&tv_sig, 0, sizeof(tv_sig));
        tv_sig.tv_sec = rrsig.sig_expr;
        GET_TIME_BUF((const time_t *)(&tv_sig.tv_sec), exprTime);

        val_log(ctx, level,
                "%s    ->tag=%d status=%s sig-incep=%s sig-expr=%s",
                prefix, rrsig.key_tag,
                p_ac_status(cursig->rr_status),
                incpTime, exprTime);
    }
#endif

#ifdef VAL_LOG_SIG
    struct val_rr_rec  *rr;
    struct val_rr_rec  *sig = next_as->val_ac_rrset->val_rrset_sig;
    for (rr = data; rr; rr = rr->rr_next) {
        val_log(ctx, level, "    data_status=%s:%d",
                p_ac_status(rr->rr_status), rr->rr_status);
    }
    for (rr = sig; rr; rr = rr->rr_next) {
        val_log(ctx, level, "    sig_status=%s:%d",
                p_ac_status(rr->rr_status), rr->rr_status);
    }
#endif
}
Esempio n. 14
0
/*
 * Function: val_gethostbyname2_r
 *
 * Purpose: A validating DNSSEC-aware version of the reentrant gethostbyname2_r
 *          function.  This function supports both IPv4 and IPv6 addresses.
 *
 * Parameters:
 *              ctx -- The validation context.  Can be NULL for default value.
 *             name -- The domain name or IP address in string format.
 *               af -- Address family AF_INET or AF_INET6
 *              ret -- Pointer to a hostent variable to store the return value.
 *                     This parameter must not be NULL.
 *              buf -- Pointer to a buffer to store auxiliary data.  This
 *                     parameter must not be NULL.
 *           buflen -- Length of the buffer 'buf'.
 *           result -- Pointer to a variable of type (struct hostent *).  This
 *                     parameter must not be NULL.  *result will contain NULL on
 *                     failure and will point to the 'ret' parameter on success.
 *         h_errnop -- Pointer to an integer variable to return the h_errno error
 *                     code.  This parameter must not be NULL.
 *       val_status -- A pointer to a val_status_t variable to hold the
 *                     returned validation-status value.  This parameter
 *                     must not be NULL.
 *                     If successful, *val_status will contain a success
 *                     code. If there is a failure, *val_status will contain
 *                     the validator error code. To test whether the returned
 *                     error code represents a trustworthy status, the caller
 *                     can use the val_istrusted() function. 
 *
 * Return value: 0 on success, and a non-zero error-code on failure.
 *
 * See also: val_gethostbyname2(), val_gethostbyname_r(), val_istrusted()
 */
int
val_gethostbyname2_r(val_context_t * context,
                     const char *name,
                     int af,
                     struct hostent *ret,
                     char *buf,
                     size_t buflen,
                     struct hostent **result,
                     int *h_errnop, val_status_t * val_status)
{
    struct sockaddr_in  sa;
#if defined( WIN32 )
    size_t addrlen4 = sizeof(struct sockaddr_in);
#endif
#ifdef VAL_IPV6
    struct sockaddr_in6 sa6;
#if defined( WIN32 )
    size_t addrlen6 = sizeof(struct sockaddr_in6);
#endif
#endif
    int             offset = 0;
    val_status_t local_ans_status = VAL_OOB_ANSWER;
    int trusted = 0;
    int             retval;
    struct val_result_chain *results = NULL;
    u_int16_t       type;
    val_context_t *ctx = NULL;

    *val_status = VAL_DONT_KNOW;
    
    if (!name || !ret || !h_errnop || !val_status || !result || !buf) {
        goto err;
    }

    ctx = val_create_or_refresh_context(context); /* does CTX_LOCK_POL_SH */
    if (ctx == NULL)
        goto err; 

    if (VAL_NO_ERROR == val_is_local_trusted(ctx, &trusted)) {
        if (trusted) {
            local_ans_status = VAL_TRUSTED_ANSWER;
        }
    }

    /*
     * Check if the address-family is AF_INET and the address is an IPv4 address 
     */
    if ((af == AF_INET) && (INET_PTON(AF_INET, name, ((struct sockaddr *)&sa), &addrlen4) > 0)) {
        memset(ret, 0, sizeof(struct hostent));

        // Name
        ret->h_name = bufalloc(buf, buflen, &offset, strlen(name) + 1);
        if (ret->h_name == NULL) {
            goto err; 
        }
        memcpy(ret->h_name, name, strlen(name) + 1);

        // Alias
        ret->h_aliases =
            (char **) bufalloc(buf, buflen, &offset, sizeof(char *));
        if (ret->h_aliases == NULL) {
            goto err;  
        }
        ret->h_aliases[0] = 0;

        // Address
        ret->h_addrtype = AF_INET;
        ret->h_length = sizeof(struct in_addr);
        ret->h_addr_list =
            (char **) bufalloc(buf, buflen, &offset, 2 * sizeof(char *));
        if (ret->h_addr_list == NULL) {
            goto err;      
        }
        ret->h_addr_list[0] =
            (char *) bufalloc(buf, buflen, &offset,
                              sizeof(struct in_addr));
        if (ret->h_addr_list[0] == NULL) {
            goto err;      
        }
        memcpy(ret->h_addr_list[0], &sa.sin_addr, sizeof(struct in_addr));
        ret->h_addr_list[1] = 0;

        *val_status = VAL_TRUSTED_ANSWER;
        *h_errnop = NETDB_SUCCESS;
        *result = ret;
    }

#ifdef VAL_IPV6
    /*
     * Check if the address-family is AF_INET6 and the address is an IPv6 address 
     */
    else if ((af == AF_INET6)
             && (INET_PTON(AF_INET6, name, ((struct sockaddr *)&sa6), &addrlen6) > 0)) {
        memset(ret, 0, sizeof(struct hostent));

        // Name
        ret->h_name = bufalloc(buf, buflen, &offset, strlen(name) + 1);
        if (ret->h_name == NULL) {
            goto err;
        }
        memcpy(ret->h_name, name, strlen(name) + 1);

        // Alias
        ret->h_aliases =
            (char **) bufalloc(buf, buflen, &offset, sizeof(char *));
        if (ret->h_aliases == NULL) {
            goto err;     
        }
        ret->h_aliases[0] = 0;

        // Address
        ret->h_addrtype = AF_INET6;
        ret->h_length = sizeof(struct in6_addr);
        ret->h_addr_list =
            (char **) bufalloc(buf, buflen, &offset, 2 * sizeof(char *));
        if (ret->h_addr_list == NULL) {
            goto err;    
        }
        ret->h_addr_list[0] =
            (char *) bufalloc(buf, buflen, &offset,
                              sizeof(struct in6_addr));
        if (ret->h_addr_list[0] == NULL) {
            goto err;   
        }
        memcpy(ret->h_addr_list[0], &sa6.sin6_addr, sizeof(struct in6_addr));
        ret->h_addr_list[1] = 0;

        *val_status = VAL_TRUSTED_ANSWER;
        *h_errnop = NETDB_SUCCESS;
        *result = ret;

    } 
#endif
    else if (NULL != 
                (*result = get_hostent_from_etc_hosts(ctx, name, af, 
                                                      ret, buf, buflen, &offset))) {
        /*
         * First check the ETC_HOSTS file
         * XXX: TODO check the order in the ETC_HOST_CONF file
         */
        *val_status = local_ans_status;
        *h_errnop = NETDB_SUCCESS;

    } else {

#ifdef VAL_IPV6
        if (af == AF_INET6) 
            type = ns_t_aaaa;
        else 
#endif
            type = ns_t_a;

        /*
         * Query the validator 
         */
        if (VAL_NO_ERROR ==
                (retval =
                 val_resolve_and_check(ctx, name, ns_c_in, type,
                                       0,
                                       &results))) {

            /*
             * Convert the validator result into hostent 
             */
            *result =
                get_hostent_from_response(ctx, af, ret, results,
                                          h_errnop, buf, buflen, &offset, val_status);

        } else {
            val_log(ctx, LOG_ERR, 
                    "val_gethostbyname2_r(): val_resolve_and_check failed - %s", p_val_err(retval));
        }

        if (*result == NULL) {
            goto err;
        } else {
            val_free_result_chain(results);
            results = NULL;
            *h_errnop = NETDB_SUCCESS;
        }

    }
    val_log(ctx, LOG_DEBUG, "val_gethostbyname2_r returned success, herrno = %d, val_status = %s", 
                *h_errnop, val_status? p_val_status(*val_status) : NULL); 
    CTX_UNLOCK_POL(ctx);
    return 0;

err:
    if (result) {
        *result = NULL;
    }
    if (h_errnop) 
        *h_errnop = NO_RECOVERY;

    if (ctx) {
        val_log(ctx, LOG_DEBUG, "val_gethostbyname2_r returned failure, herrno = %d, val_status = %s", 
                *h_errnop, val_status? p_val_status(*val_status) : NULL); 
        CTX_UNLOCK_POL(ctx);
    }
    return (NO_RECOVERY);
}
Esempio n. 15
0
/*
 * A thread-safe, re-entrant version of val_gethostbyaddr 
 */
int
val_gethostbyaddr_r(val_context_t * context,
                    const char *addr,
                    int len,
                    int type,
                    struct hostent *ret,
                    char *buf,
                    int buflen,
                    struct hostent **result,
                    int *h_errnop, val_status_t * val_status)
{

    char            domain_string[NS_MAXDNAME];
    int             ret_status = 0, bufused = 0;
    struct val_answer_chain *val_res = NULL;
    struct val_answer_chain *res;
    int retval;
    val_context_t *ctx = NULL;
    
    /*
     * check misc parameters exist 
     */
    if (!addr || !ret || !buf || (buflen <= 0) ||
        !result || !h_errnop || !val_status) {
        if (h_errnop)
            *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    /*
     * default the input parameters 
     */
    *result = NULL;
    ret->h_name = NULL;
    ret->h_aliases = NULL;
    ret->h_addr_list = NULL;
    *h_errnop = 0;
    *val_status = VAL_UNTRUSTED_ANSWER;

    /*
     * get the address values, only support IPv4 and IPv6 
     */
    if (AF_INET == type && len >= sizeof(struct in_addr)) {
        ret->h_addrtype = type;
        ret->h_length = sizeof(struct in_addr);
    } 
#ifdef VAL_IPV6
    else if (AF_INET6 == type && len >= sizeof(struct in6_addr)) {
        ret->h_addrtype = type;
        ret->h_length = sizeof(struct in6_addr);
    } 
#endif
    else {
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    memset(domain_string, 0, sizeof(domain_string));

    if (0 !=
        (ret_status = address_to_reverse_domain(addr, type,
                                                domain_string, sizeof(domain_string)))
        ) {
        *h_errnop = ret_status;
        return ret_status;
    }

    /*
     * if there is memory, add the address to hostent's address list 
     */
    if ((buflen > bufused) && 
        ((buflen - bufused) >= (ret->h_length + (sizeof(char *) * 2)))) {
        ret->h_addr_list = (char **) (buf + bufused);
        bufused = bufused + (sizeof(char *) * 2);
        ret->h_addr_list[0] = buf + bufused;
        ret->h_addr_list[1] = NULL;
        bufused = bufused + ret->h_length;
        memcpy(ret->h_addr_list[0], addr, ret->h_length);
    } else {                    /* no memory, fail */
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    ctx = val_create_or_refresh_context(context); /* does CTX_LOCK_POL_SH */
    if (ctx == NULL) {
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    if (VAL_NO_ERROR != (retval = val_get_rrset(ctx,   /* val_context_t *  */
                                                domain_string, /* domain name */ 
                                                ns_c_in,   /* const u_int16_t q_class */
                                                ns_t_ptr,  /* const u_int16_t type */
                                                0,
                                                &val_res))) { /* struct val_answer_chain **results */
        val_log(ctx, LOG_ERR, 
                "val_gethostbyaddr_r(): val_get_rrset failed - %s", p_val_err(retval));
        CTX_UNLOCK_POL(ctx);
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    CTX_UNLOCK_POL(ctx);

    if (!val_res) {
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    for (res = val_res; res; res=res->val_ans_next) {

        struct rr_rec  *rr = res->val_ans;
        if (rr) {
            struct rr_rec  *rr_it = NULL;
            int             count = 0;
            int aliases_sz = 0;
            /*
             * if the buffer has enough room add the first host address 
             */
            if (rr->rr_length < (buflen - bufused - 1)) {
                /*
                 * setup hostent 
                 */
                ret->h_name = buf + bufused;
                ns_name_ntop(rr->rr_data, ret->h_name,
                             (buflen - bufused));
                bufused = bufused + strlen(ret->h_name) + 1;

                rr_it = rr->rr_next;
                /*
                 * are there other hostnames? 
                 */
                if (rr_it) {
                    /*
                     * calculate the amount of memory we need for aliases. 
                     */
                    do {
                        count++;
                        aliases_sz = aliases_sz + rr_it->rr_length + 1;
                    } while (NULL != (rr_it = rr_it->rr_next));

                    /*
                     * check that we have the space in the buffer 
                     */
                    if (buflen >=
                        (bufused + (sizeof(char *) * (count + 1)) +
                        aliases_sz)) {
                        /*
                         * assign the string pointer array 
                         */
                        ret->h_aliases = (char **) (buf + bufused);
                        bufused = bufused + (sizeof(char *) * (count + 1));

                        /*
                         * assign the strings 
                         */
                        rr_it = rr->rr_next;
                        count = 0;
                        do {
                            ret->h_aliases[count] = buf + bufused;
                            ns_name_ntop(rr_it->rr_data,
                                         ret->h_aliases[count],
                                        (buflen - bufused));
                            bufused =
                                bufused + strlen(ret->h_aliases[count]) + 1;
                            count++;
                        } while (NULL != (rr_it = rr_it->rr_next));
                        /*
                         * mark end of array 
                         */
                        ret->h_aliases[count] = NULL;
                    }
                    /*
                     * else we didn't have enough memory for the aliases.  They
                     * will be ignored with only one hostname returned 
                     */
                }                   /* else there are no other hostnames/aliases */

            } else {                /* else there is not enough room for even one host name, fail */
                ret->h_name = NULL;
                *h_errnop = NO_RECOVERY;
                return NO_RECOVERY;
            }
            break;

        } else if  (val_does_not_exist(res->val_ans_status)) {
                    
            if ((res->val_ans_status == VAL_NONEXISTENT_TYPE) ||
                (res->val_ans_status == VAL_NONEXISTENT_TYPE_NOCHAIN)) {
                    *h_errnop = NO_DATA;
            } else if ((res->val_ans_status == VAL_NONEXISTENT_NAME) ||
                       (res->val_ans_status == VAL_NONEXISTENT_NAME_NOCHAIN)) {
                    *h_errnop = HOST_NOT_FOUND;
            }

            *result = ret;
            return *h_errnop;
        }
    }

    if (!res) { /* no rrset, but a succesful return from the query?, fail */
        ret->h_name = NULL;
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    /* set the value of merged trusted and validated status values */
    if (val_isvalidated(res->val_ans_status))
        *val_status = VAL_VALIDATED_ANSWER; 
    else if (val_istrusted(res->val_ans_status))
        *val_status = VAL_TRUSTED_ANSWER; 

    /*
     * no error, set result 
     */
    *result = ret;
    return *h_errnop;

}                               /* val_getthostbyaddr_r */
Esempio n. 16
0
/*
 * Verify a signature, given the data and the dnskey 
 */
static int 
val_sigverify(val_context_t * ctx,
              int is_a_wildcard,
              const u_char *data,
              size_t data_len,
              const val_dnskey_rdata_t * dnskey,
              const val_rrsig_rdata_t * rrsig,
              val_astatus_t * dnskey_status, val_astatus_t * sig_status,
              int clock_skew)
{
    struct timeval  tv;
    struct timeval  tv_sig;

    /** Inputs to this function have already been NULL-checked **/

    /*
     * Check if the dnskey is a zone key 
     */
    if ((dnskey->flags & ZONE_KEY_FLAG) == 0) {
        val_log(ctx, LOG_INFO, "val_sigverify(): DNSKEY with tag=%d is not a zone key", dnskey->key_tag);
        *dnskey_status = VAL_AC_INVALID_KEY;
        return 0;
    }

    /*
     * Check dnskey protocol value 
     */
    if (dnskey->protocol != 3) {
        val_log(ctx, LOG_INFO,
                "val_sigverify(): Invalid protocol field in DNSKEY with tag=%d: %d",
                dnskey->protocol, dnskey->key_tag);
        *dnskey_status = VAL_AC_UNKNOWN_DNSKEY_PROTOCOL;
        return 0;
    }

    /*
     * Match dnskey and rrsig algorithms 
     */
    if (dnskey->algorithm != rrsig->algorithm) {
        val_log(ctx, LOG_INFO,
                "val_sigverify(): Algorithm mismatch between DNSKEY (%d) and RRSIG (%d) records.",
                dnskey->algorithm, rrsig->algorithm);
        *sig_status = VAL_AC_RRSIG_ALGORITHM_MISMATCH;
        return 0;
    }


    if (clock_skew >= 0) {
        
        /*
         * Check signature inception and expiration times 
         */
        gettimeofday(&tv, NULL);
        if (tv.tv_sec < rrsig->sig_incp) {
            if (tv.tv_sec < rrsig->sig_incp - clock_skew) {
                char            currTime[1028];
                char            incpTime[1028];

                memset(&tv_sig, 0, sizeof(tv_sig));
                tv_sig.tv_sec = rrsig->sig_incp;

                GET_TIME_BUF((const time_t *)(&tv.tv_sec), currTime);
                GET_TIME_BUF((const time_t *)(&tv_sig.tv_sec), incpTime);

                val_log(ctx, LOG_INFO,
                        "val_sigverify(): Signature not yet valid. Current time (%s) is less than signature inception time (%s).",
                        currTime, incpTime);
                *sig_status = VAL_AC_RRSIG_NOTYETACTIVE;
                return 0;
            } else {
                val_log(ctx, LOG_DEBUG,
                        "val_sigverify(): Signature not yet valid, but within acceptable skew.");
            }
    
        }
    
        if (tv.tv_sec > rrsig->sig_expr) {
            if (tv.tv_sec > rrsig->sig_expr + clock_skew) {
                char            currTime[1028];
                char            exprTime[1028];

                memset(&tv_sig, 0, sizeof(tv_sig));
                tv_sig.tv_sec = rrsig->sig_expr;

                memset(currTime, 0, sizeof(currTime));
                memset(exprTime, 0, sizeof(exprTime));
                GET_TIME_BUF((const time_t *)(&tv.tv_sec), currTime);
                GET_TIME_BUF((const time_t *)(&tv_sig.tv_sec), exprTime);

                val_log(ctx, LOG_INFO,
                        "val_sigverify(): Signature expired. Current time (%s) is greater than signature expiration time (%s).",
                        currTime, exprTime);
                *sig_status = VAL_AC_RRSIG_EXPIRED;
                return 0;
            } else {
                val_log(ctx, LOG_DEBUG,
                        "val_sigverify(): Signature expired, but within acceptable skew.");
            }
        }
    } else {
        val_log(ctx, LOG_DEBUG,
                "val_sigverify(): Not checking inception and expiration times on signatures.");
    }

    switch (rrsig->algorithm) {

    case ALG_RSAMD5:
        rsamd5_sigverify(ctx, data, data_len, dnskey, rrsig, 
                         dnskey_status, sig_status);
        break;

#ifdef LIBVAL_NSEC3
    case ALG_NSEC3_DSASHA1:
#endif
    case ALG_DSASHA1:
        dsasha1_sigverify(ctx, data, data_len, dnskey, rrsig,
                          dnskey_status, sig_status);
        break;

#ifdef LIBVAL_NSEC3
    case ALG_NSEC3_RSASHA1:
#endif
    case ALG_RSASHA1:
#ifdef HAVE_SHA_2
    case ALG_RSASHA256:
    case ALG_RSASHA512:
#endif
        rsasha_sigverify(ctx, data, data_len, dnskey, rrsig,
                          dnskey_status, sig_status);
        break;

#if defined(HAVE_SHA_2) && defined(HAVE_OPENSSL_ECDSA_H)
    case ALG_ECDSAP256SHA256:
    case ALG_ECDSAP384SHA384:
        ecdsa_sigverify(ctx, data, data_len, dnskey, rrsig,
                        dnskey_status, sig_status);
        break;
#endif

    default:
        val_log(ctx, LOG_INFO, "val_sigverify(): Unsupported algorithm %d.",
                rrsig->algorithm);
        *sig_status = VAL_AC_ALGORITHM_NOT_SUPPORTED;
        *dnskey_status = VAL_AC_ALGORITHM_NOT_SUPPORTED;
        break;
    }

    if (*sig_status == VAL_AC_RRSIG_VERIFIED) {
        if (is_a_wildcard) {
            val_log(ctx, LOG_DEBUG, "val_sigverify(): Verified RRSIG is for a wildcard");
            if (clock_skew > 0)
                *sig_status = VAL_AC_WCARD_VERIFIED_SKEW;
            else
                *sig_status = VAL_AC_WCARD_VERIFIED;
        } else {
            if (clock_skew > 0)
                *sig_status = VAL_AC_RRSIG_VERIFIED_SKEW;
        }
        return 1;
    }

    return 0;
}
Esempio n. 17
0
void
verify_next_assertion(val_context_t * ctx,
                      struct val_digested_auth_chain *as,
                      struct val_digested_auth_chain *the_trust,
                      u_int32_t flags)
{
    struct rrset_rec *the_set;
    struct rrset_rr  *the_sig;
    u_char       *signby_name_n;
    u_int16_t       signby_footprint_n;
    val_dnskey_rdata_t dnskey;
    int             is_a_wildcard;
    struct rrset_rr  *nextrr;
    struct rrset_rr  *keyrr;
    u_int16_t       tag_h;
    char            name_p[NS_MAXDNAME];

    if ((as == NULL) || (as->val_ac_rrset.ac_data == NULL) || (the_trust == NULL)) {
        val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot verify assertion - no data");
        return;
    }

    the_set = as->val_ac_rrset.ac_data;
    dnskey.public_key = NULL;


    if (-1 == ns_name_ntop(the_set->rrs_name_n, name_p, sizeof(name_p)))
        snprintf(name_p, sizeof(name_p), "unknown/error");

    if (the_set->rrs_sig == NULL) {
        val_log(ctx, LOG_INFO, "verify_next_assertion(): RRSIG is missing");
        as->val_ac_status = VAL_AC_RRSIG_MISSING;
        return;
    }

    if (the_set->rrs_type_h != ns_t_dnskey) {
        /*
         * trust path contains the key 
         */
        if (the_trust->val_ac_rrset.ac_data == NULL) {
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Key is empty");
            as->val_ac_status = VAL_AC_DNSKEY_MISSING;
            return;
        }
        keyrr = the_trust->val_ac_rrset.ac_data->rrs_data;
    } else {
        /*
         * data itself contains the key 
         */
        if (the_set->rrs_data == NULL) {
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Key is empty");
            as->val_ac_status = VAL_AC_DNSKEY_MISSING;
            return;
        }
        keyrr = the_set->rrs_data;
    }

    for (the_sig = the_set->rrs_sig;
         the_sig; the_sig = the_sig->rr_next) {

        /*
         * do wildcard processing 
         */
        if (!check_label_count(the_set, the_sig, &is_a_wildcard)) {
            SET_STATUS(as->val_ac_status, the_sig,
                       VAL_AC_WRONG_LABEL_COUNT);
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Incorrect RRSIG label count");
            continue;
        }

        /*
         * for each sig, identify key, 
         */
        if (VAL_NO_ERROR != identify_key_from_sig(the_sig, &signby_name_n,
                              &signby_footprint_n)) {
            SET_STATUS(as->val_ac_status, the_sig,
                       VAL_AC_INVALID_RRSIG);
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot extract key footprint from RRSIG");
            continue;
        }

        tag_h = ntohs(signby_footprint_n);
        for (nextrr = keyrr; nextrr; nextrr = nextrr->rr_next) {
            int             is_verified = 0;
            if (VAL_NO_ERROR != val_parse_dnskey_rdata(nextrr->rr_rdata,
                                             nextrr->rr_rdata_length,
                                             &dnskey)) {
                val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot parse DNSKEY data");
                nextrr->rr_status = VAL_AC_INVALID_KEY;
                continue;
            }

            dnskey.next = NULL;
            if (dnskey.key_tag != tag_h) {
                if (dnskey.public_key != NULL) {
                    FREE(dnskey.public_key);
                    dnskey.public_key = NULL;
                }
                continue;
            }

            val_log(ctx, LOG_DEBUG, "verify_next_assertion(): Found potential matching DNSKEY for RRSIG");

            /*
             * check the signature 
             */
            is_verified = do_verify(ctx, signby_name_n,
                      &nextrr->rr_status,
                      &the_sig->rr_status,
                      the_set, the_sig, &dnskey, is_a_wildcard, flags);

            /*
             * There might be multiple keys with the same key tag; set this as
             * the signing key only if we dont have other status for this key
             */
            SET_STATUS(as->val_ac_status, the_sig, the_sig->rr_status);
            if (nextrr->rr_status == VAL_AC_UNSET) {
                nextrr->rr_status = VAL_AC_SIGNING_KEY;
            }

            if (is_verified) {

                val_log(ctx, LOG_INFO, "verify_next_assertion(): Verified a RRSIG for %s (%s) using a DNSKEY (%d)",
                        name_p, p_type(the_set->rrs_type_h),
                        dnskey.key_tag);

                if ( as->val_ac_status == VAL_AC_TRUST ||
                    nextrr->rr_status == VAL_AC_TRUST_POINT) {
                    /* we've verified a trust anchor */
                    as->val_ac_status = VAL_AC_TRUST; 
                    val_log(ctx, LOG_INFO, "verify_next_assertion(): verification traces back to trust anchor");
                    if (dnskey.public_key != NULL) {
                        FREE(dnskey.public_key);
                        dnskey.public_key = NULL;
                    }
                    return;
                }
            
                /* Check if we're trying to verify some key in the authentication chain */
                if ( the_set->rrs_type_h == ns_t_dnskey && 
                    as != the_trust) {
                    /* Check if we have reached our trust key */
                    /*
                     * If this record contains a DNSKEY, check if the DS record contains this key 
                     * DNSKEYs cannot be wildcard expanded, so VAL_AC_WCARD_VERIFIED does not
                     * count as a good sig
                     * Create the link even if the DNSKEY algorithm is unknown since this 
                     * may be the provably insecure case
                     */
                    /*
                     * follow the trust path 
                     */
                    struct rrset_rr  *dsrec =
                        the_trust->val_ac_rrset.ac_data->rrs_data;
                    while (dsrec) {
                        val_ds_rdata_t  ds;
                        ds.d_hash = NULL;
                        int retval = val_parse_ds_rdata(dsrec->rr_rdata,
                                       dsrec->rr_rdata_length, &ds);
                        if(retval == VAL_NOT_IMPLEMENTED) {
                            val_log(ctx, LOG_INFO, "verify_next_assertion(): DS hash not supported");
                            dsrec->rr_status = VAL_AC_ALGORITHM_NOT_SUPPORTED;
                        } else if (retval != VAL_NO_ERROR) {
                            val_log(ctx, LOG_INFO, "verify_next_assertion(): DS parse error");
                            dsrec->rr_status = VAL_AC_INVALID_DS;
                        } else if (DNSKEY_MATCHES_DS(ctx, &dnskey, &ds, 
                                    the_set->rrs_name_n, nextrr, 
                                    &dsrec->rr_status)) {
                            val_log(ctx, LOG_DEBUG, 
                                    "verify_next_assertion(): DNSKEY tag (%d) matches DS tag (%d)",
                                    (&dnskey)->key_tag,                                         
                                    (&ds)->d_keytag);
                            /*
                             * the first match is enough 
                             */
                            nextrr->rr_status = VAL_AC_VERIFIED_LINK;
                            FREE(ds.d_hash);
                            ds.d_hash = NULL;
                            if (dnskey.public_key) {
                                FREE(dnskey.public_key);
                                dnskey.public_key = NULL;
                            }
                            val_log(ctx, LOG_INFO, "verify_next_assertion(): Key links upward");
                            return;
                        } else {
                            /*
                             * Didn't find a valid entry in the DS record set 
                             * Not necessarily a problem, since there is no requirement that a DS be present
                             * If none match, then we set the status accordingly. See below.
                             */
                            nextrr->rr_status = VAL_AC_DS_NOMATCH;
                        } 

                        if (ds.d_hash != NULL)
                            FREE(ds.d_hash);

                        dsrec = dsrec->rr_next;
                    }
                }
            } 

            if (dnskey.public_key != NULL) {
                FREE(dnskey.public_key);
            }
            dnskey.public_key = NULL;
        }

        val_log(ctx, LOG_INFO, "verify_next_assertion(): Could not link this RRSIG to a DNSKEY");
        SET_STATUS(as->val_ac_status, the_sig, VAL_AC_DNSKEY_NOMATCH);
    }
        
    /* 
     * If we reach here and we're a keyset, we either didn't verify the keyset or
     * didn't verify the link from the key to the DS 
     */ 
    if (the_set->rrs_type_h == ns_t_dnskey){
        as->val_ac_status = VAL_AC_NO_LINK;
    }
}
Esempio n. 18
0
/*
 * Function: get_hostent_from_etc_hosts
 *
 * Purpose: Read the ETC_HOSTS file and check if it contains the given name.
 *          Return the result in a hostent structure.
 *
 * Parameters:
 *              ctx -- The validation context.
 *             name -- The domain name or IP address in string form.
 *               af -- The address family: AF_INET or AF_INET6.
 *              ret -- Pointer to a hostent structure to return the result.
 *                     This parameter must not be NULL.
 *              buf -- A buffer to store auxiliary data.  This parameter must not be NULL.
 *           buflen -- Length of the buffer 'buf'.
 *           offset -- Pointer to an integer variable that contains the offset in the buffer
 *                     'buf', where data can be written.  When this function writes any data
 *                     in the auxiliary data, the offset is incremented accordingly.  This
 *                     parameter must not be NULL.
 *
 * Return value: Returns NULL on failure and 'ret' on success.
 *
 * See also: get_hostent_from_response()
 */
static struct hostent *
get_hostent_from_etc_hosts(val_context_t * ctx,
                           const char *name,
                           int af,
                           struct hostent *ret,
                           char *buf, int buflen, int *offset)
{
    int             orig_offset = 0;
    struct hosts   *hs = NULL;
    struct hosts   *h_prev = NULL;

    if ((ret == NULL) || (buf == NULL) || (offset == NULL)
        || (*offset < 0)) {
        return NULL;
    }

    /*
     * Parse the /etc/hosts file 
     */
    hs = parse_etc_hosts(name);

    orig_offset = *offset;
    memset(ret, 0, sizeof(struct hostent));

    /*
     * XXX: todo -- can hs have more than one element ? 
     */
    while (hs) {
        struct sockaddr_in sa;
#if defined( WIN32 )
        size_t addrlen4 = sizeof(struct sockaddr_in);
#endif
#ifdef VAL_IPV6
        struct sockaddr_in6 sa6;
#if defined( WIN32 )
        size_t addrlen6 = sizeof(struct sockaddr_in6);
#endif
#endif
        char            addr_buf[INET6_ADDRSTRLEN];
        int             i, alias_count;
        int             len = 0;
        const char *addr = NULL;
        size_t buflen = INET6_ADDRSTRLEN;

        if ((af == AF_INET)
            && (INET_PTON(AF_INET, hs->address, ((struct sockaddr *)&sa), &addrlen4) > 0)) {
            INET_NTOP(AF_INET, (&sa), sizeof(sa), addr_buf, buflen, addr);
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): type of address is IPv4");
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): Address is: %s",
                    addr
		);
        } 
#ifdef VAL_IPV6
	else if ((af == AF_INET6)
                   && (INET_PTON(AF_INET6, hs->address, ((struct sockaddr *)&sa6), &addrlen6) > 0)) {
	    
            INET_NTOP(AF_INET6, (&sa6), sizeof(sa6), addr_buf, buflen, addr);
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): type of address is IPv6");
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): Address is: %s",
                    addr
                  );
        } 
#endif
	else {
            /*
             * not a valid address ... skip this line 
             */
            val_log(ctx, LOG_WARNING,
                    "get_hostent_from_etc_hosts(): error in address format: %s",
                    hs->address);
            h_prev = hs;
            hs = hs->next;
            FREE_HOSTS(h_prev);
            continue;
        }

        // Name
        len =
            (hs->canonical_hostname ==
             NULL) ? 0 : strlen(hs->canonical_hostname);

        if (hs->canonical_hostname) {
            ret->h_name = (char *) bufalloc(buf, buflen, offset, len + 1);
            if (ret->h_name == NULL) {
                goto err;
            }

            memcpy(ret->h_name, hs->canonical_hostname, len + 1);
        } else {
            ret->h_name = NULL;
        }

        // Aliases
        alias_count = 0;
        while (hs->aliases[alias_count]) {
            alias_count++;
        }
        alias_count++;

        ret->h_aliases =
            (char **) bufalloc(buf, buflen, offset,
                               alias_count * sizeof(char *));

        if (ret->h_aliases == NULL) {
            goto err;
        }

        for (i = 0; i < alias_count; i++) {
            len = (hs->aliases[i] == NULL) ? 0 : strlen(hs->aliases[i]);
            if (hs->aliases[i]) {
                ret->h_aliases[i] =
                    (char *) bufalloc(buf, buflen, offset, len + 1);
                if (ret->h_aliases[i] == NULL) {
                    goto err;
                }
                memcpy(ret->h_aliases[i], hs->aliases[i], len + 1);
            } else {
                ret->h_aliases[i] = NULL;
            }
        }

        // Addresses
        ret->h_addr_list =
            (char **) bufalloc(buf, buflen, offset, 2 * sizeof(char *));
        if ((ret->h_addr_list == NULL)
            || ((af != AF_INET) && (af != AF_INET6))) {
            goto err;
        }
        if (af == AF_INET) {
            ret->h_addrtype = AF_INET;
            ret->h_length = sizeof(struct in_addr);
            ret->h_addr_list[0] =
                (char *) bufalloc(buf, buflen, offset,
                                  sizeof(struct in_addr));
            if (ret->h_addr_list[0] == NULL) {
                goto err;
            }
            memcpy(ret->h_addr_list[0], &sa.sin_addr, sizeof(struct in_addr));
            ret->h_addr_list[1] = 0;
        } 
#ifdef VAL_IPV6
        else if (af == AF_INET6) {
            ret->h_addrtype = AF_INET6;
            ret->h_length = sizeof(struct in6_addr);
            ret->h_addr_list[0] =
                (char *) bufalloc(buf, buflen, offset,
                                  sizeof(struct in6_addr));
            if (ret->h_addr_list[0] == NULL) {
                goto err;
            }
            memcpy(ret->h_addr_list[0], &sa6.sin6_addr,
                   sizeof(struct in6_addr));
            ret->h_addr_list[1] = 0;
        }
#endif

        /*
         * clean up host list 
         */
        while (hs) {
            h_prev = hs;
            hs = hs->next;
            FREE_HOSTS(h_prev);
        }
        return ret;
    }

    return NULL;

  err:
    /*
     * clean up host list 
     */
    while (hs) {
        h_prev = hs;
        hs = hs->next;
        FREE_HOSTS(h_prev);
    }

    *offset = orig_offset;
    return NULL;

}                               /* get_hostent_from_etc_hosts() */
Esempio n. 19
0
/*
 * helper function for a set of verify-related operations
 */
static int
do_verify(val_context_t * ctx,
          u_char *zone_n,
          val_astatus_t * dnskey_status,
          val_astatus_t * sig_status,
          struct rrset_rec *the_set,
          struct rrset_rr *the_sig,
          val_dnskey_rdata_t * the_key, int is_a_wildcard,
          u_int32_t flags)
{
    /*
     * Use the crypto routines to verify the signature
     */

    u_char       *ver_field;
    size_t          ver_length;
    int             ret_val;
    val_rrsig_rdata_t rrsig_rdata;
    int clock_skew = 0;
    u_int32_t ttl_x = 0;
    int retval = 0;

    /*
     * Wildcard expansions for DNSKEYs and DSs are not permitted
     */
    if (is_a_wildcard &&
        ((the_set->rrs_type_h == ns_t_ds) ||
         (the_set->rrs_type_h == ns_t_dnskey))) {
        val_log(ctx, LOG_INFO, "do_verify(): Invalid DNSKEY or DS record - cannot be wildcard expanded");
        *dnskey_status = VAL_AC_INVALID_KEY;
        return 0;
    }

    if ((ret_val = make_sigfield(&ver_field, &ver_length, the_set, the_sig,
                                 is_a_wildcard)) != VAL_NO_ERROR ||
        ver_field == NULL || 
        ver_length == 0) {

        val_log(ctx, LOG_INFO, 
                "do_verify(): Could not construct signature field for verification: %s", 
                p_val_err(ret_val));
        *sig_status = VAL_AC_INVALID_RRSIG;
        return 0;
    }

    /*
     * Find the signature - no memory is malloc'ed for this operation  
     */

    if (VAL_NO_ERROR != val_parse_rrsig_rdata(the_sig->rr_rdata, 
                                   the_sig->rr_rdata_length,
                                   &rrsig_rdata)) {
        if (ver_field)
            FREE(ver_field);
        val_log(ctx, LOG_INFO, 
                "do_verify(): Could not parse signature field");
        *sig_status = VAL_AC_INVALID_RRSIG;
        return 0;
    }

    rrsig_rdata.next = NULL;

    if (flags & VAL_QUERY_IGNORE_SKEW) {
        clock_skew = -1;
        val_log(ctx, LOG_DEBUG, "do_verify(): Ignoring clock skew"); 
    } else {
        get_clock_skew(ctx, zone_n, &clock_skew, &ttl_x);
        /* the state is valid for only as long as the policy validity period */
        SET_MIN_TTL(the_set->rrs_ttl_x, ttl_x);
    }

    /*
     * Perform the verification 
     */
    retval = val_sigverify(ctx, is_a_wildcard, ver_field, ver_length, the_key,
                  &rrsig_rdata, dnskey_status, sig_status, clock_skew);

    if (rrsig_rdata.signature != NULL) {
        FREE(rrsig_rdata.signature);
        rrsig_rdata.signature = NULL;
    }

    FREE(ver_field);
    return retval;
}
Esempio n. 20
0
static int
process_packet(val_context_t *context)
{
    HEADER         *query_header, *response_header;
    u_char         *pos;
    int             q_name_len, rc;
    u_int16_t       type_h, class_h;

    struct sockaddr from;
    socklen_t       from_len;

    u_char          query[4096], response[4096];
    int             query_size, response_size;

    /*
     * get a packet
     */
    from_len = sizeof(from);
    memset(&from, 0x0, sizeof(from));
    do {
        rc = recvfrom(listen_fd, query, sizeof(query), 0, &from,
                      &from_len);
        if (rc < 0 && errno != EINTR) {
            // xxx-rks: log err msg
            break;
        }
    } while (rc < 0);
    if (rc < 0)
        return rc;

    query_size = rc;
    if (query_size < (sizeof(HEADER) + 1))
        return -1;

    query_header = (HEADER *) query;

    /*
     * get query name
     */
    pos = &query[sizeof(HEADER)];
    q_name_len = wire_name_length(pos);
    pos += q_name_len;

    /*
     * get class and type
     */
    VAL_GET16(type_h, pos);
    VAL_GET16(class_h, pos);

    response_size = sizeof(response);
    
    get_results(context, "test", (char *)&query[sizeof(HEADER)], (int)class_h,
                (int)type_h, response, &response_size, 0);

    /*
     * check to see if we need a dummy response
     */
    val_log(NULL, LOG_DEBUG, "XXX-RKS: handle no response");
    if (0 == response_size) {
        // no response; generate dummy/nxdomain response?
        return 1;
    }

    response_header = (HEADER*)response;
    response_header->id = query_header->id;

    /*
     * send response
     */
    do {
        rc = sendto(listen_fd, response, response_size, 0, &from,
                    sizeof(from));
        if (rc < 0 && errno != EINTR) {
            // xxx-rks: log err msg
            break;
        }
    } while (rc < 0);
    if (rc > 0) {
        val_log(NULL, LOG_DEBUG, "sent %d bytes", rc);
    }

    return 0;                   /* no error */
}
Esempio n. 21
0
/*
 * Function: get_hostent_from_response
 *
 * Purpose: Converts the linked list of val_result_chain structures obtained
 *          as a result from the validator into a hostent structure.
 *
 * Parameters:
 *              ctx -- The validation context.
 *               af -- The address family: AF_INET or AF_INET6.
 *              ret -- Pointer to a hostent structure to return the result.
 *                     This parameter must not be NULL.
 *          results -- Pointer to a linked list of val_result_chain structures.
 *         h_errnop -- Pointer to an integer variable to store the h_errno value.
 *              buf -- A buffer to store auxiliary data.  This parameter must not be NULL.
 *           buflen -- Length of the buffer 'buf'.
 *           offset -- Pointer to an integer variable that contains the offset in the buffer
 *                     'buf', where data can be written.  When this function writes any data
 *                     in the auxiliary data, the offset is incremented accordingly.  This
 *                     parameter must not be NULL.
 *
 * Return value: Returns NULL on failure and 'ret' on success.
 *
 * See also: get_hostent_from_etc_hosts()
 */
static struct hostent *
get_hostent_from_response(val_context_t * ctx, int af, struct hostent *ret,
                          struct val_result_chain *results, int *h_errnop,
                          char *buf, int buflen, int *offset, 
                          val_status_t * val_status)
{
    int             alias_count = 0;
    int             alias_index = 0;
    int             addr_count = 0;
    int             addr_index = 0;
    int             orig_offset = 0;
    struct val_result_chain *res;
    int validated = 1;
    int trusted = 1;
    struct val_rrset_rec *rrset;
    char *alias_target = NULL;

    /*
     * Check parameter sanity 
     */
    if (!results || !h_errnop || !buf || !offset || !ret || !val_status) {
        return NULL;
    }

    *val_status = VAL_DONT_KNOW;
    *h_errnop = 0;
    
    orig_offset = *offset;
    memset(ret, 0, sizeof(struct hostent));

    /*
     * Count the number of aliases and addresses in the result 
     */
    for (res = results; res != NULL; res = res->val_rc_next) {
        rrset = res->val_rc_rrset;

        if (res->val_rc_alias && rrset) {
            val_log(ctx, LOG_DEBUG,
                    "get_hostent_from_response(): type of record = CNAME");
            alias_count++;
            continue;
        }

        // Get a count of aliases and addresses
        if (rrset) {
            struct val_rr_rec  *rr = rrset->val_rrset_data;

            while (rr) {

                if ((af == AF_INET)
                           && (rrset->val_rrset_type == ns_t_a)) {
                    val_log(ctx, LOG_DEBUG,
                            "get_hostent_from_response(): type of record = A");
                    addr_count++;
                } else if ((af == AF_INET6)
                           && (rrset->val_rrset_type == ns_t_aaaa)) {
                    val_log(ctx, LOG_DEBUG,
                            "get_hostent_from_response(): type of record = AAAA");
                    addr_count++;
                }

                rr = rr->rr_next;
            }
        }
    }

    ret->h_aliases =
        (char **) bufalloc(buf, buflen, offset,
                           (alias_count + 1) * sizeof(char *));
    if (ret->h_aliases == NULL) {
        goto err;
    }
    ret->h_aliases[alias_count] = NULL;

    ret->h_addr_list =
        (char **) bufalloc(buf, buflen, offset,
                           (addr_count + 1) * sizeof(char *));
    if (ret->h_addr_list == NULL) {
        goto err;
    }
    ret->h_addr_list[addr_count] = NULL;

    alias_index = alias_count - 1;

    if (results == NULL) {
        *val_status = VAL_UNTRUSTED_ANSWER;
        *h_errnop = HOST_NOT_FOUND; 
        goto err;
    } 
   
    /*
     * Process the result 
     */
    for (res = results; res != NULL; res = res->val_rc_next) {

        rrset = res->val_rc_rrset;

        if (!(validated && val_isvalidated(res->val_rc_status))) 
            validated = 0;
        if (!(trusted && val_istrusted(res->val_rc_status)))
            trusted = 0;

        /* save the non-existence state */
        if (val_does_not_exist(res->val_rc_status)) {
            *val_status = res->val_rc_status;
            if (res->val_rc_status == VAL_NONEXISTENT_NAME ||
                res->val_rc_status == VAL_NONEXISTENT_NAME_NOCHAIN) {

                *h_errnop = HOST_NOT_FOUND;
            } else { 
                *h_errnop = NO_DATA;
            }
            break;
        }

        if (res->val_rc_alias && rrset) {
            // Handle CNAME RRs
            if (alias_index >= 0) {
                ret->h_aliases[alias_index] =
                    (char *) bufalloc(buf, buflen, offset,
                                      (strlen(rrset->val_rrset_name) + 1) * sizeof(char));
                if (ret->h_aliases[alias_index] == NULL) {
                    goto err;
                }
                memcpy(ret->h_aliases[alias_index], rrset->val_rrset_name,
                       strlen(rrset->val_rrset_name) + 1);
                alias_index--;
            }

            /* save the alias target for later use */
            alias_target = res->val_rc_alias; 
        } else if (rrset) {

            if (((af == AF_INET)
                      && (rrset->val_rrset_type == ns_t_a))
                || ((af == AF_INET6)
                      && (rrset->val_rrset_type == ns_t_aaaa))) {

                struct val_rr_rec  *rr = rrset->val_rrset_data;

                if (!ret->h_name) {
                    ret->h_name =
                            (char *) bufalloc(buf, buflen, offset,
                                              (strlen(rrset->val_rrset_name) +
                                               1) * sizeof(char));
                    if (ret->h_name == NULL) {
                        goto err;
                    }
                    memcpy(ret->h_name, rrset->val_rrset_name, strlen(rrset->val_rrset_name) + 1);
                }

                while (rr) {
                    // Handle A and AAAA RRs
                    ret->h_length = rr->rr_rdata_length;
                    ret->h_addrtype = af;
                    ret->h_addr_list[addr_index] =
                            (char *) bufalloc(buf, buflen, offset,
                                              rr->rr_rdata_length *
                                              sizeof(char));
                    if (ret->h_addr_list[addr_index] == NULL) {
                        goto err;
                    }

                    memcpy(ret->h_addr_list[addr_index], rr->rr_rdata,
                               rr->rr_rdata_length);
                    addr_index++;

                    rr = rr->rr_next;
                }
            }
        }
    }
    /* pick up official name from the alias target */
    if (!ret->h_name && alias_target) {
        ret->h_name = (char *) bufalloc(buf, buflen, offset,
                          (strlen(alias_target) + 1) * sizeof(char));
        if (ret->h_name == NULL) {
            goto err;
        }
        memcpy(ret->h_name, alias_target, strlen(alias_target) + 1);
    }

    if (addr_count > 0) {
        *h_errnop = NETDB_SUCCESS;
        if (validated)
            *val_status = VAL_VALIDATED_ANSWER;
        else if (trusted)
            *val_status = VAL_TRUSTED_ANSWER;
        else 
            *val_status = VAL_UNTRUSTED_ANSWER; 
    } else if (alias_count == 0) {
        goto err;
    } else if (*h_errnop == 0)   {
        /* missing a proof of non-existence for alias */
        *val_status = VAL_UNTRUSTED_ANSWER;
        *h_errnop = NO_DATA;
    } 
    return ret;

err:
    *offset = orig_offset;
    return NULL;
    
}                               /* get_hostent_from_response() */
Esempio n. 22
0
void
ecdsa_sigverify(val_context_t * ctx,
                const u_char *data,
                size_t data_len,
                const val_dnskey_rdata_t * dnskey,
                const val_rrsig_rdata_t * rrsig,
                val_astatus_t * key_status, val_astatus_t * sig_status)
{
    char            buf[1028];
    size_t          buflen = 1024;
    u_char   sha_hash[MAX_DIGEST_LENGTH];
    EC_KEY   *eckey = NULL;
    BIGNUM *bn_x = NULL;
    BIGNUM *bn_y = NULL;
    ECDSA_SIG *ecdsa_sig;
    size_t   hashlen = 0;

    ecdsa_sig = ECDSA_SIG_new();
    memset(sha_hash, 0, sizeof(sha_hash));

    val_log(ctx, LOG_DEBUG,
            "ecdsa_sigverify(): parsing the public key...");

    if (rrsig->algorithm == ALG_ECDSAP256SHA256) {
        hashlen = SHA256_DIGEST_LENGTH; 
        SHA256(data, data_len, sha_hash);
        eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); /* P-256 */
    } else if (rrsig->algorithm == ALG_ECDSAP384SHA384) {
        hashlen = SHA384_DIGEST_LENGTH; 
        SHA384(data, data_len, sha_hash);
        eckey = EC_KEY_new_by_curve_name(NID_secp384r1); /* P-384 */
    } 

    if (eckey == NULL) {
        val_log(ctx, LOG_INFO,
                "ecdsa_sigverify(): could not create key for ECDSA group.");
        *key_status = VAL_AC_INVALID_KEY;
        goto err;
    };

    /* 
     * contruct an EC_POINT from the "Q" field in the 
     * dnskey->public_key, dnskey->public_key_len
     */
    if (dnskey->public_key_len != 2*hashlen) {
        val_log(ctx, LOG_INFO,
                "ecdsa_sigverify(): dnskey length does not match expected size.");
        *key_status = VAL_AC_INVALID_KEY;
        goto err;
    }
    bn_x = BN_bin2bn(dnskey->public_key, hashlen, NULL);
    bn_y = BN_bin2bn(&dnskey->public_key[hashlen], hashlen, NULL);
    if (1 != EC_KEY_set_public_key_affine_coordinates(eckey, bn_x, bn_y)) {
        val_log(ctx, LOG_INFO,
                "ecdsa_sigverify(): Error associating ECSA structure with key.");
        *key_status = VAL_AC_INVALID_KEY;
        goto err;
    }


    val_log(ctx, LOG_DEBUG, "ecdsa_sigverify(): SHA hash = %s",
            get_hex_string(sha_hash, hashlen, buf, buflen));
    val_log(ctx, LOG_DEBUG,
            "ecdsa_sigverify(): verifying ECDSA signature...");

    /* 
     * contruct ECDSA signature from the "r" and "s" fileds in 
     * rrsig->signature, rrsig->signature_len
     */
    if (rrsig->signature_len != 2*hashlen) {
        val_log(ctx, LOG_INFO,
                "ecdsa_sigverify(): Signature length does not match expected size.");
        *sig_status = VAL_AC_RRSIG_VERIFY_FAILED;
        goto err;
    }

    ECDSA_SIG_set0(ecdsa_sig, BN_bin2bn(rrsig->signature, hashlen, NULL),
                   BN_bin2bn(&rrsig->signature[hashlen], hashlen, NULL));

    if (ECDSA_do_verify(sha_hash, hashlen, ecdsa_sig, eckey) == 1) {
        val_log(ctx, LOG_INFO, "ecdsa_sigverify(): returned SUCCESS");
        *sig_status = VAL_AC_RRSIG_VERIFIED;
    } else {
        val_log(ctx, LOG_INFO, "ecdsa_sigverify(): returned FAILURE");
        *sig_status = VAL_AC_RRSIG_VERIFY_FAILED;
    }

    /* Free all structures allocated */
err:
    if (ecdsa_sig)
        ECDSA_SIG_free(ecdsa_sig);
    if (bn_x)
        BN_free(bn_x);
    if (bn_y)
        BN_free(bn_y);
    if (eckey)
        EC_KEY_free(eckey);

    return;

}
Esempio n. 23
0
void
rsasha_sigverify(val_context_t * ctx,
                  const u_char *data,
                  size_t data_len,
                  const val_dnskey_rdata_t * dnskey,
                  const val_rrsig_rdata_t * rrsig,
                  val_astatus_t * key_status, val_astatus_t * sig_status)
{
    char            buf[1028];
    size_t          buflen = 1024;
    RSA            *rsa = NULL;
    u_char   sha_hash[MAX_DIGEST_LENGTH];
    size_t   hashlen = 0;
    int nid = 0;

    val_log(ctx, LOG_DEBUG,
            "rsasha_sigverify(): parsing the public key...");
    if ((rsa = RSA_new()) == NULL) {
        val_log(ctx, LOG_INFO,
                "rsasha_sigverify(): could not allocate rsa structure.");
        *key_status = VAL_AC_INVALID_KEY;
        return;
    };

    if (rsa_parse_public_key
        (dnskey->public_key, (size_t)dnskey->public_key_len,
         rsa) != VAL_NO_ERROR) {
        val_log(ctx, LOG_INFO,
                "rsasha_sigverify(): Error in parsing public key.");
        RSA_free(rsa);
        *key_status = VAL_AC_INVALID_KEY;
        return;
    }

    memset(sha_hash, 0, sizeof(sha_hash));
    if (rrsig->algorithm == ALG_RSASHA1
#ifdef LIBVAL_NSEC3
        || rrsig->algorithm == ALG_NSEC3_RSASHA1
#endif
       ) {
        SHA1(data, data_len, sha_hash);
        hashlen = SHA_DIGEST_LENGTH; 
        nid = NID_sha1; 
    } else if (rrsig->algorithm == ALG_RSASHA256) {
        SHA256(data, data_len, sha_hash);
        hashlen = SHA256_DIGEST_LENGTH; 
        nid = NID_sha256; 
    } else if (rrsig->algorithm == ALG_RSASHA512) {
        SHA512(data, data_len, sha_hash);
        hashlen = SHA512_DIGEST_LENGTH; 
        nid = NID_sha512; 
    } else {
        val_log(ctx, LOG_INFO,
                "rsasha_sigverify(): Unkown algorithm.");
        RSA_free(rsa);
        *key_status = VAL_AC_INVALID_KEY;
        return;
    } 

    val_log(ctx, LOG_DEBUG, "rsasha_sigverify(): SHA hash = %s",
            get_hex_string(sha_hash, hashlen, buf, buflen));
    val_log(ctx, LOG_DEBUG,
            "rsasha_sigverify(): verifying RSA signature...");

    if (RSA_verify
        (nid, sha_hash, hashlen,
         rrsig->signature, rrsig->signature_len, rsa) == 1) {
        val_log(ctx, LOG_INFO, "rsasha_sigverify(): returned SUCCESS");
        RSA_free(rsa);
        *sig_status = VAL_AC_RRSIG_VERIFIED;
    } else {
        val_log(ctx, LOG_INFO, "rsasha_sigverify(): returned FAILURE");
        RSA_free(rsa);
        *sig_status = VAL_AC_RRSIG_VERIFY_FAILED;
    }
    return;
}