示例#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;
}
示例#2
0
int
ds_sha384_hash_is_equal(u_char * name_n,
                        u_char * rrdata,
                        size_t rrdatalen, 
                        u_char * ds_hash,
                        size_t ds_hash_len)
{
    u_char        ds_digest[SHA384_DIGEST_LENGTH];
    size_t        namelen;
    SHA512_CTX    c;
    size_t          l_index;
    u_char        qc_name_n[NS_MAXCDNAME];

    if (rrdata == NULL || ds_hash_len != SHA384_DIGEST_LENGTH)
        return 0;

    namelen = wire_name_length(name_n);
    memcpy(qc_name_n, name_n, namelen);
    l_index = 0;
    lower_name(qc_name_n, &l_index);

    memset(ds_digest, 0, SHA384_DIGEST_LENGTH);

    SHA384_Init(&c);
    SHA384_Update(&c, qc_name_n, namelen);
    SHA384_Update(&c, rrdata, rrdatalen);
    SHA384_Final(ds_digest, &c);

    if (!memcmp(ds_digest, ds_hash, SHA384_DIGEST_LENGTH))
        return 1;

    return 0;
}
示例#3
0
u_char       *
nsec3_sha_hash_compute(u_char * name_n, u_char * salt,
                       size_t saltlen, size_t iter, u_char ** hash,
                       size_t * hashlen)
{
    /*
     * Assume that the caller has already performed all sanity checks 
     */
    SHA_CTX         c;
    size_t          i;
    size_t          l_index;
    int len = wire_name_length(name_n);
    u_char qc_name_n[NS_MAXCDNAME];

    memcpy(qc_name_n, name_n, len);
    l_index = 0;
    lower_name(qc_name_n, &l_index);

    *hash = (u_char *) MALLOC(SHA_DIGEST_LENGTH * sizeof(u_char));
    if (*hash == NULL)
        return NULL;
    *hashlen = SHA_DIGEST_LENGTH;

    memset(*hash, 0, SHA_DIGEST_LENGTH);

    /*
     * IH(salt, x, 0) = H( x || salt) 
     */
    SHA1_Init(&c);
    SHA1_Update(&c, qc_name_n, wire_name_length(qc_name_n));
    SHA1_Update(&c, salt, saltlen);
    SHA1_Final(*hash, &c);

    /*
     * IH(salt, x, k) = H(IH(salt, x, k-1) || salt) 
     */
    for (i = 0; i < iter; i++) {
        SHA1_Init(&c);
        SHA1_Update(&c, *hash, *hashlen);
        SHA1_Update(&c, salt, saltlen);
        SHA1_Final(*hash, &c);
    }
    return *hash;
}
示例#4
0
/*
 * Calculate the size of the field over which the verification
 * is done.  This is the sum of
 * the number of bytes through the signer name in the SIG RDATA
 * the length of the signer name (uncompressed)
 * the sum of the fully uncompressed lengths of the RRs in the set
 * *field_length is the field length
 * *signer_length is the length of the signer's name (used externally)
 */
static int
predict_sigbuflength(struct rrset_rec *rr_set,
                     size_t * field_length, size_t *signer_length)
{
    struct rrset_rr  *rr;
    int             owner_length;

    /** Input has already been NULL-checked **/
    owner_length = wire_name_length(rr_set->rrs_name_n);

    *signer_length =
        wire_name_length(&rr_set->rrs_sig->rr_rdata[SIGNBY]);

    if (*signer_length == 0)
        return VAL_BAD_ARGUMENT;

    *field_length = SIGNBY + (*signer_length);

    for (rr = rr_set->rrs_data; rr; rr = rr->rr_next)
        *field_length += owner_length + ENVELOPE + rr->rr_rdata_length;

    return VAL_NO_ERROR;
}
示例#5
0
/*
 * Create the buffer over which the signature is to be verified
 */
static int
make_sigfield(u_char ** field,
              size_t * field_length,
              struct rrset_rec *rr_set,
              struct rrset_rr *rr_sig, int is_a_wildcard)
{
    struct rrset_rr  *curr_rr;
    size_t          index;
    size_t          signer_length;
    size_t          owner_length;
    u_int16_t       type_n;
    u_int16_t       class_n;
    u_int32_t       ttl_n;
    u_int16_t       rdata_length_n;
    u_char          lowered_owner_n[NS_MAXCDNAME];
    size_t          l_index;
    int             retval;

    if ((field == NULL) || (field_length == NULL) || (rr_set == NULL) ||
        (rr_sig == NULL) || (rr_set->rrs_name_n == NULL) ||
        (rr_set->rrs_sig == NULL) || 
        (rr_set->rrs_sig->rr_rdata == NULL))
        return VAL_BAD_ARGUMENT;

    if ((retval = predict_sigbuflength(rr_set, field_length, &signer_length)) !=
        VAL_NO_ERROR)
        return retval;

    *field = (u_char *) MALLOC(*field_length * sizeof(u_char));

    if (*field == NULL)
        return VAL_OUT_OF_MEMORY;

    /*
     * Make sure we are using the correct TTL 
     */

    memcpy(&ttl_n, &rr_sig->rr_rdata[TTL], sizeof(u_int32_t));
    rr_set->rrs_ttl_h = ntohl(ttl_n);

    /*
     * While we're at it, we'll gather other common info, specifically
     * network ordered numbers (type, class) and name length.
     */

    owner_length = wire_name_length(rr_set->rrs_name_n);

    if (owner_length == 0)
        goto err;

    memcpy(lowered_owner_n, rr_set->rrs_name_n, owner_length);
    l_index = 0;
    lower_name(lowered_owner_n, &l_index);

    type_n = htons(rr_set->rrs_type_h);
    class_n = htons(rr_set->rrs_class_h);

    /*
     * Copy in the SIG RDATA (up to the signature 
     */

    index = 0;
    if ((index + SIGNBY + signer_length) > *field_length)
        goto err;
    memcpy(&(*field)[index], rr_sig->rr_rdata, SIGNBY + signer_length);
    l_index = 0;
    lower_name(&(*field)[index+SIGNBY], &l_index);
    index += SIGNBY + signer_length;

    /*
     * For each record of data, copy in the envelope & the lower cased rdata 
     */

    for (curr_rr = rr_set->rrs_data; curr_rr;
         curr_rr = curr_rr->rr_next) {
        if (curr_rr->rr_rdata == NULL)
            goto err;

        /*
         * Copy in the envelope information 
         */

        if (is_a_wildcard) {
            /*
             * Construct the original name 
             */
            u_char wcard_n[NS_MAXCDNAME];
            u_char *np = lowered_owner_n;
            int    i;
            size_t outer_len;

            for (i = 0; i < is_a_wildcard; i++)
                np += np[0] + 1;
            outer_len = wire_name_length(np);

            wcard_n[0] = (u_char) 1;
            wcard_n[1] = '*';
            if ((outer_len + 2) > sizeof(wcard_n))
                goto err;
            memcpy(&wcard_n[2], np, outer_len);
            if ((index + outer_len + 2) > *field_length)
                goto err;
            memcpy(&(*field)[index], wcard_n, outer_len + 2);
            index += outer_len + 2;
        } else {
            if ((index + owner_length) > *field_length)
                goto err;
            memcpy(&(*field)[index], lowered_owner_n, owner_length);
            index += owner_length;
        }

        if ((index + sizeof(u_int16_t) + sizeof(u_int16_t) +
             sizeof(u_int32_t))
            > *field_length)
            goto err;
        memcpy(&(*field)[index], &type_n, sizeof(u_int16_t));
        index += sizeof(u_int16_t);
        memcpy(&(*field)[index], &class_n, sizeof(u_int16_t));
        index += sizeof(u_int16_t);
        memcpy(&(*field)[index], &ttl_n, sizeof(u_int32_t));
        index += sizeof(u_int32_t);

        /*
         * Now the RR-specific info, the length and the data 
         */

        rdata_length_n = htons(curr_rr->rr_rdata_length);
        if ((index + sizeof(u_int16_t) + curr_rr->rr_rdata_length)
            > *field_length)
            goto err;
        memcpy(&(*field)[index], &rdata_length_n, sizeof(u_int16_t));
        index += sizeof(u_int16_t);
        memcpy(&(*field)[index], curr_rr->rr_rdata,
               curr_rr->rr_rdata_length);
        index += curr_rr->rr_rdata_length;
    }

    *field_length = index;
    return VAL_NO_ERROR;

  err:
    FREE(*field);
    *field = NULL;
    *field_length = 0;
    return VAL_BAD_ARGUMENT;
}
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 */
}
示例#7
0
/*
 * Set the TSIG params for this name server
 * Format is:
 * name:alg:fudge:key
 */
int
res_set_ns_tsig(struct name_server *ns, char *tsigstr)
{
    struct ns_tsig *tsig = NULL;
    int rr_hlen, rr_rdatalen;

    char *name_s; 
    char *fudge_s;
    char *key_s;
    const char *alg_s; 
    int i;

    char *buf, *c, *n;
    if (ns == NULL || tsigstr == NULL)
        return SR_TS_CALL_ERROR;

    tsig = (struct ns_tsig *) MALLOC (sizeof(struct ns_tsig));
    if (tsig == NULL)
        return SR_TS_FAIL;

    buf = strdup(tsigstr);
    if (buf == NULL) {
        FREE(tsig);
        return SR_TS_FAIL;
    }
    c = buf;

    /* Parse the tsig string */
    name_s = c;
    if (!(n = strchr(c,':'))) {
        goto err;
    }
    *n = '\0';
    c = n+1;

    alg_s = c;
    if (!(n = strchr(c,':'))) {
        goto err;
    }
    *n = '\0';
    c = n+1;

    fudge_s = c;
    if (!(n = strchr(c,':'))) {
        goto err;
    }
    *n = '\0';
    c = n+1;
    key_s = c;

    for(i = 0; name_s[i]; i++){
        if (isupper(name_s[i]))
            name_s[i] = tolower(name_s[i]);
    }
    if (ns_name_pton(name_s, tsig->name_n, sizeof(tsig->name_n)) == -1) { 
        goto err;
    }

    /* check for alg sanity */
    if (!strcmp(alg_s, "")) {
        alg_s = TSIG_ALG_HMAC_MD5_STR;
        tsig->alg = TSIG_ALG_HMAC_MD5;
        tsig->mac_size = MD5_DIGEST_LENGTH;
    } else if (!strcmp(alg_s, TSIG_ALG_HMAC_MD5_STR)) {
        tsig->alg = TSIG_ALG_HMAC_MD5;
        tsig->mac_size = MD5_DIGEST_LENGTH;
    } else if (!strcmp(alg_s, TSIG_ALG_HMAC_SHA1_STR)) {
        tsig->alg = TSIG_ALG_HMAC_SHA1;
        tsig->mac_size = SHA_DIGEST_LENGTH;
    } else if (!strcmp(alg_s, TSIG_ALG_HMAC_SHA256_STR)) {
        tsig->alg = TSIG_ALG_HMAC_SHA256;
        tsig->mac_size = SHA256_DIGEST_LENGTH;
    } else {
        goto err;
    }
    for(i = 0; alg_s[i]; i++){
        if (isupper(alg_s[i]))
            name_s[i] = tolower(alg_s[i]);
    }
    if (ns_name_pton(alg_s, tsig->alg_n, sizeof(tsig->alg_n)) == -1) { 
        goto err;
    }
   
    /* check for fudge sanity */ 
    if (0 == (tsig->fudge = (u_int16_t)atoi(fudge_s))) {
       tsig->fudge = TSIG_FUDGE_DEFAULT; 
    }

    /* Decode the base64 key */
    tsig->key = (u_char *) MALLOC (strlen(key_s)+1);
    if (tsig->key == NULL) {
        goto err;
    }
    if ((tsig->keylen = decode_tsig_key(key_s, tsig->key, strlen(key_s))) <= 0) {
        FREE(tsig->key);
        goto err;
    }

    rr_hlen = wire_name_length(tsig->name_n) + /*Name*/
                     sizeof(u_int16_t) +  /*type*/
                     sizeof(u_int16_t) +  /*class*/
                     sizeof(u_int32_t);  /*ttl*/

    rr_rdatalen = wire_name_length(tsig->alg_n) + /*alg*/
                    sizeof(u_int32_t) + sizeof(u_int16_t) + /*time signed is u_int48_t*/
                    sizeof(u_int16_t) + /*fudge*/
                    sizeof(u_int16_t) + /*mac size*/
                    tsig->mac_size + /*mac*/
                    sizeof(u_int16_t) + /*original ID*/
                    sizeof(u_int16_t) + /*error*/
                    sizeof(u_int16_t) ; /*other len*/

    tsig->rdatalen = rr_rdatalen;
    tsig->buf_size = rr_hlen + sizeof(u_int16_t) + rr_rdatalen;

    ns->ns_tsig = tsig;
    ns->ns_security_options |= ZONE_USE_TSIG;

    free(buf);
    return SR_TS_OK;

err:
    free(buf);
    FREE(tsig);
    return SR_TS_FAIL;

}
示例#8
0
int
res_tsig_sign(u_char * query,
              size_t query_length,
              struct name_server *ns,
              u_char ** signed_query, 
              size_t *signed_length)
{
    int buflen;
    u_char *cp, *p;
    u_char *hp;
    HEADER *header;
    struct timeval now;
    HMAC_CTX *ctx;
    const EVP_MD *md;
    u_char hash[MAX_DIGEST_LENGTH];
    unsigned int len;
    u_int16_t arcount;

    if (!signed_query || !signed_length)
        return SR_TS_FAIL;
    *signed_query = NULL;
    *signed_length = 0;

    if (query && query_length && query_length > sizeof(HEADER)) {
        if (!(ns->ns_security_options & ZONE_USE_TSIG)) {
            *signed_query = (u_char *) MALLOC(query_length * sizeof(u_char));
            if (*signed_query == NULL) 
                return SR_TS_FAIL;
            memcpy(*signed_query, query, query_length * sizeof(u_char));
            *signed_length = query_length;
            return SR_TS_OK;
        } else if (!ns->ns_tsig) {
            return SR_TS_FAIL;
        }

        switch(ns->ns_tsig->alg) {
            case TSIG_ALG_HMAC_MD5:
               md = EVP_md5();
               break; 
            case TSIG_ALG_HMAC_SHA1:
               md = EVP_sha1();
               break; 
            case TSIG_ALG_HMAC_SHA256:
               md = EVP_sha256();
               break; 
            default:
               return SR_TS_FAIL;
        } 

        ctx = HMAC_CTX_new();
        HMAC_Init_ex(ctx, ns->ns_tsig->key, ns->ns_tsig->keylen,
                md, NULL);

        /* Create a TSIG RR and add it to the additional section */
        buflen = query_length + ns->ns_tsig->buf_size;
        *signed_query = (u_char *) MALLOC(buflen * sizeof(u_char));
        if (*signed_query == NULL) 
            return SR_TS_FAIL;
        *signed_length = buflen;
        cp = *signed_query;

        p = cp;
        memcpy(cp, query, query_length * sizeof(u_char));
        cp += query_length;
        HMAC_Update(ctx, p, cp-p); 

        /* Bump up the additional section count */
        header = (HEADER *) p;
        arcount = ntohs(header->arcount);
        arcount++;
        header->arcount = htons(arcount);;

        p = cp;
        memcpy(cp, ns->ns_tsig->name_n, wire_name_length(ns->ns_tsig->name_n));
        cp += wire_name_length(ns->ns_tsig->name_n);
        HMAC_Update(ctx, p, cp-p); 

        /* don't digest type */
        RES_PUT16(ns_t_tsig, cp);

        p = cp;
        RES_PUT16(ns_t_any, cp);
        RES_PUT32(0, cp);
        HMAC_Update(ctx, p, cp-p); 

        /* don't digest rdatalen */
        RES_PUT16(ns->ns_tsig->rdatalen, cp);

        p = cp;
        memcpy(cp, ns->ns_tsig->alg_n, wire_name_length(ns->ns_tsig->alg_n));
        cp += wire_name_length(ns->ns_tsig->alg_n);
        HMAC_Update(ctx, p, cp-p); 

        gettimeofday(&now, NULL);
        p = cp;
        RES_PUT48((u_int64_t)now.tv_sec, cp);
        RES_PUT16(ns->ns_tsig->fudge, cp);
        HMAC_Update(ctx, p, cp-p); 

        /* don't digest the mac_size */
        RES_PUT16(ns->ns_tsig->mac_size, cp);

        /* save the location for the hmac */
        hp = cp;
        cp += ns->ns_tsig->mac_size;
    
        /* don't digest the header ID */
        RES_PUT16(ntohs(header->id), cp);

        p = cp;
        RES_PUT16(0, cp);
        RES_PUT16(0, cp);
        HMAC_Update(ctx, p, cp-p); 

        HMAC_Final(ctx, hash, &len);

        if (len != ns->ns_tsig->mac_size) {
            FREE(*signed_query);
            *signed_query = NULL;
            return SR_TS_FAIL;
        }
        memcpy(hp, hash, len);

        HMAC_CTX_free(ctx);
        return SR_TS_OK;

    } else
        return SR_TS_CALL_ERROR;
}