Beispiel #1
0
struct hostent *
netsnmp_gethostbyname(const char *name)
{
#if HAVE_GETHOSTBYNAME
#ifdef DNSSEC_LOCAL_VALIDATION
    val_status_t val_status;
#endif
    struct hostent *hp = NULL;

    if (NULL == name)
        return NULL;

    DEBUGMSGTL(("dns:gethostbyname", "looking up %s\n", name));

#ifdef DNSSEC_LOCAL_VALIDATION
    hp  = val_gethostbyname(netsnmp_validator_context(), name, &val_status);
    DEBUGMSGTL(("dns:sec:val", "val_status %d / %s; trusted: %d\n",
                val_status, p_val_status(val_status),
                val_istrusted(val_status)));
    if (!val_istrusted(val_status)) {
        snmp_log(LOG_WARNING,
                 "The authenticity of DNS response is not trusted (%s)\n",
                 p_val_status(val_status));
        /** continue anyways if DNSSEC_WARN_ONLY is set */
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
                                    NETSNMP_DS_LIB_DNSSEC_WARN_ONLY))
            hp = NULL;
    }
    else if (val_does_not_exist(val_status) && hp)
        hp = NULL;
#else
    hp = gethostbyname(name);
#endif
    if (hp == NULL) {
        DEBUGMSGTL(("dns:gethostbyname",
                    "couldn't resolve %s\n", name));
    } else if (hp->h_addrtype != AF_INET) {
        DEBUGMSGTL(("dns:gethostbyname",
                    "warning: response for %s not AF_INET!\n", name));
    } else {
        DEBUGMSGTL(("dns:gethostbyname",
                    "%s resolved okay\n", name));
    }
    return hp;
#else
    NETSNMP_LOGONCE((LOG_ERR, "gethostbyname not available"));
    return NULL;
#endif /* HAVE_GETHOSTBYNAME */
}
Beispiel #2
0
struct hostent *
netsnmp_gethostbyaddr(const void *addr, socklen_t len, int type)
{
#if HAVE_GETHOSTBYADDR
    struct hostent *hp = NULL;
    struct sockaddr_in *saddr_in =
        NETSNMP_REMOVE_CONST(struct sockaddr_in *,addr);

    DEBUGMSGTL(("dns:gethostbyaddr", "resolving { AF_INET, %s:%hu }\n",
                inet_ntoa(saddr_in->sin_addr), ntohs(saddr_in->sin_port)));

#ifdef DNSSEC_LOCAL_VALIDATION
    val_status_t val_status;
    hp = val_gethostbyaddr(netsnmp_validator_context(),
                           (const void*)&saddr_in->sin_addr,
                           sizeof(struct in_addr), AF_INET, &val_status);
    DEBUGMSGTL(("dns:sec:val", "val_status %d / %s; trusted: %d\n",
                val_status, p_val_status(val_status),
                val_istrusted(val_status)));
    if (!val_istrusted(val_status)) {
        snmp_log(LOG_WARNING,
                 "The authenticity of DNS response is not trusted (%s)\n",
                 p_val_status(val_status));
        /** continue anyways if DNSSEC_WARN_ONLY is set */
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
                                    NETSNMP_DS_LIB_DNSSEC_WARN_ONLY))
            hp = NULL;
    }
    else if (val_does_not_exist(val_status) && hp)
        hp = NULL;
#else
    hp = gethostbyaddr((const void*) &saddr_in->sin_addr,
                       sizeof(struct in_addr), AF_INET);
#endif
    if (hp == NULL) {
        DEBUGMSGTL(("dns:gethostbyaddr", "couldn't resolve addr\n"));
    } else if (hp->h_addrtype != AF_INET) {
        DEBUGMSGTL(("dns:gethostbyaddr",
                    "warning: response for addr not AF_INET!\n"));
    } else {
        DEBUGMSGTL(("dns:gethostbyaddr", "addr resolved okay\n"));
    }
    return hp;
#else
    NETSNMP_LOGONCE((LOG_ERR, "gethostbyaddr not available"));
    return NULL;
#endif
}
Beispiel #3
0
struct hostent *
dnssec_gethostbyname2(const char *name, int family) {
  	val_status_t          val_status;
  	struct hostent *      res;

  	if (dnssec_init_context())
    	return NULL;

  	LOG(L_INFO, " gethostbyname2(%s) called: wrapper\n", name);

  	res = val_gethostbyname2(libval_ctx, name, family,  &val_status);

  	if (val_istrusted(val_status) && !val_does_not_exist(val_status)) {
      	return res;
  	}
  	return NULL;
}
Beispiel #4
0
int
dnssec_res_search(const char *dname, int class_h, int type_h,
	  unsigned char *answer, int anslen) {
  	val_status_t          val_status;
  	int ret;

  	if (dnssec_init_context())
    	return -1;

  	LOG(L_INFO, "res_query(%s,%d,%d) called: wrapper\n",
	  	dname, class_h, type_h);

  	ret = val_res_search(libval_ctx, dname, class_h, type_h, answer, anslen,
			&val_status);

  	if (val_istrusted(val_status) && !val_does_not_exist(val_status)) {
		return ret;
  	} else {
		LOG(L_INFO, "invalid domain %s reason %s\n", dname, p_val_status(val_status));
	}

 	return -1;
}
Beispiel #5
0
int
val_get_answer_from_result(val_context_t *context, const char *name, int class_h,
                           int type_h, struct val_result_chain **results,
                           struct val_answer_chain **answers,
                           unsigned int vgafr_flags)
{
    struct val_result_chain *res = NULL;
    struct val_answer_chain *ans = NULL;
    struct val_answer_chain *last_ans = NULL;
    int retval = VAL_NO_ERROR;
    const char *n = NULL;
    int len;
    char *name_alias = NULL;
    int trusted, validated;
    
    if (name == NULL || answers == NULL || results == NULL || answers == NULL) {
        return VAL_BAD_ARGUMENT;
    }

    *answers = NULL;
    last_ans = NULL;
   
    if (*results == NULL) {
        /* Construct a single val_answer_chain with the untrusted status */
        ans = (struct val_answer_chain *) MALLOC (sizeof(struct val_answer_chain));
        if (ans == NULL) {
            return VAL_OUT_OF_MEMORY;
        }
        ans->val_ans_name = strdup(name); 
        if (ans->val_ans_name == NULL) {
            FREE(ans);
            ans = NULL;
            return VAL_OUT_OF_MEMORY;
        } 
        ans->val_ans_status = VAL_UNTRUSTED_ANSWER;
        ans->val_ans_class = class_h;
        ans->val_ans_type = type_h;
        ans->val_ans = NULL;
        ans->val_ans_next = NULL;
        *answers = ans;
        return VAL_NO_ERROR;
    }

    trusted = 1;
    validated = 1;

    /* Construct the val_answer_chain linked list for returned results */
    for (res = *results; res; res=res->val_rc_next) {

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

        /* 
         * we don't need cnames/dnames in the answer,
         * we only need the name that is being pointed to.
         */
        if (res->val_rc_alias) {
            name_alias = res->val_rc_alias;
            continue;
        }

        ans = (struct val_answer_chain *) MALLOC (sizeof(struct val_answer_chain));
        if (ans == NULL) {
            retval = VAL_OUT_OF_MEMORY;
            goto err;
        }

        /* add to end of chain */
        ans->val_ans_next = NULL;
        if (last_ans) {
            last_ans->val_ans_next = ans;
        } else {
            *answers = ans;
        }
        last_ans = ans;
        
        if (res->val_rc_rrset) {
            /* use values from the rrset */
            n = res->val_rc_rrset->val_rrset_name;
            ans->val_ans_class = res->val_rc_rrset->val_rrset_class; 
            ans->val_ans_type = res->val_rc_rrset->val_rrset_type; 
            ans->val_ans = (struct rr_rec *) (res->val_rc_rrset->val_rrset_data);
            res->val_rc_rrset->val_rrset_data = NULL;
        } else {
            if (name_alias) {
                n = name_alias; /* the last alias target */ 
            } else {
                n = name; /* the name being queried for */
            }
            ans->val_ans_class = class_h; 
            ans->val_ans_type = type_h; 
            ans->val_ans = NULL;
        } 

        /* Convert the name to a string */
        ans->val_ans_name = NULL;    
        len = strlen(n) + 1;
        ans->val_ans_name = (char *) MALLOC (len * sizeof (char));
        if (ans->val_ans_name == NULL) {
            retval = VAL_OUT_OF_MEMORY;
            goto err;
        }
        strcpy(ans->val_ans_name, n);

        /* 
         * if the current answer was validated or 
         * if the current answer was trusted use the exact status
         */
        if (validated || 
            (trusted && !val_isvalidated(res->val_rc_status))) {
           ans->val_ans_status = res->val_rc_status;
        } else if (trusted) {
        /*
         * If the combined answer was trusted but the current answer
         * was validated (implied), use the lower bounds of trust 
         */
            if (val_does_not_exist(res->val_rc_status)) {
                if (res->val_rc_status == VAL_NONEXISTENT_NAME)
                   ans->val_ans_status = VAL_NONEXISTENT_NAME_NOCHAIN; 
                else 
                   ans->val_ans_status = VAL_NONEXISTENT_TYPE_NOCHAIN; 
            } else {
                ans->val_ans_status = VAL_TRUSTED_ANSWER;
            }
        } else {
            ans->val_ans_status = VAL_UNTRUSTED_ANSWER;        
        }

        /* 
         * reset the below values so that we are able to handle different 
         * status values for different answers
         */
        validated = 1;
        trusted = 1;
    } 

    val_free_result_chain(*results);
    *results = NULL;
    return VAL_NO_ERROR;

err:
    val_free_answer_chain(*answers);
    *answers = NULL;
    val_free_result_chain(*results);
    *results = NULL;
    return retval;
} 
Beispiel #6
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 */
Beispiel #7
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() */