示例#1
0
KDCENTRY* krb_locate_kdc(rdpSettings* settings)
{
#ifdef WITH_RESOLV
	char *qname;
	int reslen, i;
	unsigned char response[4096];
	char kdc_host[4096];
	unsigned char* temp;
	KDCENTRY* head;
	KDCENTRY* kdcentry;
	KDCENTRY* srvans;
	ns_msg handle;
	ns_rr rr;
	head = kdcentry =  NULL;
	if (get_krb_realm(settings))
		return NULL;
	if (settings->kerberos_kdc)
	{
		srvans = xnew(KDCENTRY);
		srvans->kdchost = xstrdup(settings->kerberos_kdc);
		srvans->port = 88;
		return srvans;
	}
	qname = get_dns_queryname(settings->kerberos_realm, "_tcp.");

	if ((reslen = res_query(qname, ns_c_in, ns_t_srv, response, sizeof(response))) < 0)
		return NULL;

	ns_initparse(response, reslen, &handle);

	for (i = 0;i < ns_msg_count(handle, ns_s_an);i++)
	{
		ns_parserr(&handle, ns_s_an, i, &rr);
		srvans = xnew(KDCENTRY);
		temp = (unsigned char*)ns_rr_rdata(rr);
		GETUINT16(temp, &(srvans->priority));
		GETUINT16(temp, &(srvans->weight));
		GETUINT16(temp, &(srvans->port));
		if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), temp, (char*)kdc_host, sizeof(kdc_host)) < 0)
			srvans->kdchost = xstrdup((const char*)temp);
		else
			srvans->kdchost = xstrdup(kdc_host);
		if (head == NULL || head->priority > srvans->priority)
		{
			srvans->next = head;
			head = srvans;
		}
		else
		{
			for (kdcentry = head;kdcentry->next != NULL && kdcentry->next->priority < srvans->priority;kdcentry = kdcentry->next);
			srvans->next = kdcentry->next;
			kdcentry->next = srvans;
		}
	}

	return head;
#else
	return NULL;
#endif
}
示例#2
0
/*%
 *  Convert an RR to presentation format.
 *
 * return:
 *\li   Number of characters written to buf, or -1 (check errno).
 */
int
ns_sprintrr(const ns_msg* handle, const ns_rr* rr,
            const char* name_ctx, const char* origin,
            char* buf, size_t buflen) {
    int n;
    n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
                     ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
                     ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
                     name_ctx, origin, buf, buflen);
    return (n);
}
示例#3
0
文件: sendmail.c 项目: n0g/cherami
char* getMailserver(const char* domain) {
	int len;
	char answer[NS_PACKETSZ];
	char *mailserver = malloc(NS_PACKETSZ);
	ns_msg msg;
	ns_rr rr;

	if(res_init() == -1) {
		return NULL;
	}
	len = res_query(domain,C_ANY,T_MX,answer,NS_PACKETSZ);
	if(len == -1) {
		return NULL;
	}
	/* return first MX record */	
	ns_initparse(answer,len,&msg);
	ns_parserr(&msg,ns_s_an,0,&rr);
	dn_expand(ns_msg_base(msg),ns_msg_base(msg)+ns_msg_size(msg),ns_rr_rdata(rr)+NS_INT16SZ,mailserver,NS_PACKETSZ);
	return mailserver; 
}
示例#4
0
文件: query.c 项目: Barrell/wine
static char *dns_dname_from_msg( ns_msg msg, const unsigned char *pos )
{
    int len;
    char *str, dname[NS_MAXDNAME] = ".";

    /* returns *compressed* length, ignore it */
    dns_ns_name_uncompress( ns_msg_base(msg), ns_msg_end(msg), pos, dname, sizeof(dname) );

    len = strlen( dname );
    str = heap_alloc( len + 1 );
    if (str) strcpy( str, dname );
    return str;
}
示例#5
0
static void test_res_fake_srv_query(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    int prio;
    int weight;
    int port;
    char hostname[MAXDNAME];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "_ldap._tcp.cwrap.org", ns_c_in, ns_t_srv,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 100);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type SRV and have the priority, weight,
     * port and hostname as in the fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_srv);

    rrdata = ns_rr_rdata(rr);
    NS_GET16(prio, rrdata);
    NS_GET16(weight, rrdata);
    NS_GET16(port, rrdata);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            hostname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_int_equal(prio, 1);
    assert_int_equal(weight, 5);
    assert_int_equal(port, 389);
    assert_string_equal(hostname, "ldap.cwrap.org");
}
示例#6
0
static int
app_parse_srv(radiodns_app_t *app, ns_msg handle, ns_rr rr, char *dnbuf, radiodns_srv_t *srv)
{
	const unsigned char *rdata;
	
	(void) app;

	rdata = ns_rr_rdata(rr);
	srv->priority = ns_get16(rdata);
	rdata += NS_INT16SZ;

	srv->weight = ns_get16(rdata);
	rdata += NS_INT16SZ;
	
	srv->port = ns_get16(rdata);
	rdata += NS_INT16SZ;
	
	dn_expand(ns_msg_base(handle), ns_msg_base(handle) + ns_msg_size(handle), rdata, dnbuf, MAXDNAME);
	if(!(srv->target = strdup(dnbuf)))
	{
		return -2;
	}
	return 0;
}
示例#7
0
static JSBool parse_name(JSContext *cx, JSObject *robj, const ns_msg *hdl, const ns_rr *rr)
{
	char name[MAXDNAME];
	JSString *str;
	const unsigned char *base = ns_msg_base(*hdl), *end = ns_msg_end(*hdl);

	if (ns_name_uncompress(base, end, ns_rr_rdata(*rr), name, sizeof(name)) < 0)
		return JS_TRUE;

	str = JS_NewStringCopyZ(cx, name);
	if (!str)
		return JS_RetErrno(cx, ENOMEM);

	if (!JS_DefineProperty(cx, robj, "data", STRING_TO_JSVAL(str), NULL, NULL, JSPROP_ENUMERATE))
		return JS_RetErrno(cx, ENOMEM);

	return JS_TRUE;
}
示例#8
0
int get_krb_realm(rdpSettings* settings)
{
#ifdef WITH_RESOLV
	char* s;
	char* queryname;
	int reslen;
	unsigned char response[2048];
	char ns_realm[2048];
	ns_msg handle;
	ns_rr rr;
	s = settings->hostname;
	if (settings->kerberos_realm)
		return 0;
	do
	{
		queryname = get_dns_queryname(s, NULL);

		if ((reslen = res_query(queryname, ns_c_in, ns_t_txt, response, sizeof(response))))
		{
			ns_initparse(response, reslen, &handle);
			ns_parserr(&handle, ns_s_an, 0, &rr);
			if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr), (char*)ns_realm, sizeof(ns_realm)) < 0)
				goto end;
			else
				settings->kerberos_realm = xstrdup(ns_realm);
			xfree(queryname);
			return 0;
		}

		end:
			xfree(queryname);
			for (;*s != '.' && *s != '\0';s++);
			if (*s != '\0')
				s++;
	}
	while (*s != '\0');
	s = settings->hostname;
	for (;*s != '.';s++);
	s++;
	settings->kerberos_realm = xstrdup(s);
#endif

	return 0;
}
示例#9
0
static void afsdb_hosts_to_addrs(char *vllist[],
				 int *vlsnum,
				 ns_msg handle,
				 ns_sect section,
				 unsigned mask,
				 unsigned long *_ttl)
{
	int rrnum;
	ns_rr rr;
	int subtype, i, ret;
	unsigned int ttl = UINT_MAX, rr_ttl;

	debug("AFSDB RR count is %d", ns_msg_count(handle, section));

	/* Look at all the resource records in this section. */
	for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) {
		/* Expand the resource record number rrnum into rr. */
		if (ns_parserr(&handle, section, rrnum, &rr)) {
			_error("ns_parserr failed : %m");
			continue;
		}

		/* We're only interested in AFSDB records */
		if (ns_rr_type(rr) == ns_t_afsdb) {
			vllist[*vlsnum] = malloc(MAXDNAME);
			if (!vllist[*vlsnum])
				error("Out of memory");

			subtype = ns_get16(ns_rr_rdata(rr));

			/* Expand the name server's domain name */
			if (ns_name_uncompress(ns_msg_base(handle),
					       ns_msg_end(handle),
					       ns_rr_rdata(rr) + 2,
					       vllist[*vlsnum],
					       MAXDNAME) < 0)
				error("ns_name_uncompress failed");

			rr_ttl = ns_rr_ttl(rr);
			if (ttl > rr_ttl)
				ttl = rr_ttl;

			/* Check the domain name we've just unpacked and add it to
			 * the list of VL servers if it is not a duplicate.
			 * If it is a duplicate, just ignore it.
			 */
			for (i = 0; i < *vlsnum; i++)
				if (strcasecmp(vllist[i], vllist[*vlsnum]) == 0)
					goto next_one;

			/* Turn the hostname into IP addresses */
			ret = dns_resolver(vllist[*vlsnum], mask);
			if (ret) {
				debug("AFSDB RR can't resolve."
				      "subtype:%d, server name:%s, netmask:%u",
				      subtype, vllist[*vlsnum], mask);
				goto next_one;
			}

			info("AFSDB RR subtype:%d, server name:%s, ip:%*.*s, ttl:%u",
			     subtype, vllist[*vlsnum],
			     (int)payload[payload_index - 1].iov_len,
			     (int)payload[payload_index - 1].iov_len,
			     (char *)payload[payload_index - 1].iov_base,
			     ttl);

			/* prepare for the next record */
			*vlsnum += 1;
			continue;

		next_one:
			free(vllist[*vlsnum]);
		}
	}

	*_ttl = ttl;
	info("ttl: %u", ttl);
}
示例#10
0
/**
 *  create_naptr_record()
 */
static NAPTR_record *create_naptr_record(const ns_msg *handle,
                                         const ns_rr *rr) {
   size_t rdchars;
   const u_char *rdata, *edata;
   const u_char *message = ns_msg_base(*handle);
   size_t message_len = ns_msg_size(*handle);
   char buf[NS_MAXDNAME]; /* defined in nameser.h */
   NAPTR_record *naptr_record = malloc(sizeof(NAPTR_record));
   memset(naptr_record,0,sizeof(NAPTR_record));

   /*
   ** Domain field
   */
   naptr_record->domain = strdup(ns_rr_name(*rr));

   /*
   ** TTL field
   */
   naptr_record->ttl = ns_rr_ttl(*rr);

   /*
   ** Copy from rdata
   ** (borrowed from BIND-8.2.2 ns_print.c)
   */
   rdata = ns_rr_rdata(*rr);
   edata = rdata+ns_rr_rdlen(*rr);

   /*
   ** Order & preference field
   */
   naptr_record->order = ns_get16(rdata);
   rdata += NS_INT16SZ;
   naptr_record->preference = ns_get16(rdata);
   rdata += NS_INT16SZ;

   /*
   ** Flags field
   */
   if((naptr_record->flags = get_rdata_str(rdata,edata,&rdchars))==NULL) {
      free_naptr_record(naptr_record);
      return NULL;
   }
   rdata += rdchars;

   /*
   ** Service field
   */
   if((naptr_record->service = get_rdata_str(rdata,edata,&rdchars))==NULL) {
      free_naptr_record(naptr_record);
      return NULL;
   }
   rdata += rdchars;

   /*
   ** RegExp field
   */
   if((naptr_record->regexp = get_rdata_str(rdata,edata,&rdchars))==NULL) {
      free_naptr_record(naptr_record);
      return NULL;
   }
   rdata += rdchars;

   /*
   ** Replacement field
   **  Note: dn_expand() sets the first character to '\0' for the root,
   **        we are going to set it back to '.'
   */
   if(dn_expand(message,message+message_len,rdata,buf,NS_MAXDNAME)==-1) {
      free_naptr_record(naptr_record);
      return NULL;
   }
   if(buf[0]=='\0') {
      buf[0]='.';
      buf[1]='\0';
   }
   naptr_record->replacement = strdup(buf);

   return naptr_record;
}
示例#11
0
static void test_res_fake_cname_query(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    char cname[MAXDNAME];
    char addr[INET_ADDRSTRLEN];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_cname,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 256);

    ns_initparse(answer, 256, &handle);
    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type CNAME and have the cname as in the
     * fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "web.cwrap.org");

    /* The CNAME points to an A record that's present in the additional
     * section
     */
    assert_int_equal(ns_msg_count(handle, ns_s_ar), 2);

    assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);
    assert_string_equal(ns_rr_name(rr), "web.cwrap.org");
    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "www.cwrap.org");

    assert_int_equal(ns_parserr(&handle, ns_s_ar, 1, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_a);
    assert_string_equal(ns_rr_name(rr), "www.cwrap.org");
    assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "127.0.0.22");
}
示例#12
0
static void test_res_fake_a_via_cname(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    char cname[MAXDNAME];
    char addr[INET_ADDRSTRLEN];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    /* Query for A record, but the key is a CNAME. The expected result is
     * that the whole chain of CNAMEs will be included in the answer section
     * along with the resulting A
     */
    rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_a,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 256);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have three answers and the answers
     * must be a parseable RR of type CNAME and have the cname as in the
     * fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 3);

    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "web.cwrap.org");

    assert_int_equal(ns_parserr(&handle, ns_s_an, 1, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "www.cwrap.org");

    assert_int_equal(ns_parserr(&handle, ns_s_an, 2, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_a);
    assert_string_equal(ns_rr_name(rr), "www.cwrap.org");
    assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "127.0.0.22");
}
示例#13
0
static void test_res_fake_soa_query(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    char nameser[MAXDNAME];
    char admin[MAXDNAME];
    int serial;
    int refresh;
    int retry;
    int expire;
    int minimum;

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "cwrap.org", ns_c_in, ns_t_soa,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 100);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type SOA and have the data as in the fake
     * hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_soa);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            nameser, MAXDNAME);
    assert_int_not_equal(rv, -1);
    rrdata += rv;

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            admin, MAXDNAME);
    assert_int_not_equal(rv, -1);
    rrdata += rv;

    NS_GET32(serial, rrdata);
    NS_GET32(refresh, rrdata);
    NS_GET32(retry, rrdata);
    NS_GET32(expire, rrdata);
    NS_GET32(minimum, rrdata);

    assert_string_equal(nameser, "ns1.cwrap.org");
    assert_string_equal(admin, "admin.cwrap.org");
    assert_int_equal(serial, 2014100457);
    assert_int_equal(refresh, 3600);
    assert_int_equal(retry, 300);
    assert_int_equal(expire, 1814400);
    assert_int_equal(minimum, 600);
}
示例#14
0
/*
 * Test the case of a SRV record query where the
 * fake hosts file entry is minimal in the sense
 * that it omits the priority and weight entries.
 * The server then fills in some default values.
 */
static void test_res_fake_srv_query_minimal(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    int prio;
    int weight;
    int port;
    char hostname[MAXDNAME];
    char addr[INET_ADDRSTRLEN];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "_krb5._tcp.cwrap.org", ns_c_in, ns_t_srv,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 256);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type SRV and have the priority, weight,
     * port and hostname as in the fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_srv);

    rrdata = ns_rr_rdata(rr);
    NS_GET16(prio, rrdata);
    NS_GET16(weight, rrdata);
    NS_GET16(port, rrdata);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            hostname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_int_equal(prio, 1);
    assert_int_equal(weight, 100);
    assert_int_equal(port, 88);
    assert_string_equal(hostname, "krb5.cwrap.org");

    /* The additional section contains the A record of krb5.cwrap.org */
    assert_int_equal(ns_msg_count(handle, ns_s_ar), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_a);
    assert_string_equal(ns_rr_name(rr), "krb5.cwrap.org");
    assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "127.0.0.23");
}
示例#15
0
static void
dump_dns_rr(ns_msg *msg, ns_rr *rr, ns_sect sect, FILE *trace) {
	char buf[NS_MAXDNAME];
	u_int class, type;
	const u_char *rd;
	u_int32_t soa[5];
	u_int16_t mx;
	int n;

    memset(buf, 0, sizeof(buf));
	class = ns_rr_class(*rr);
	type = ns_rr_type(*rr);
	fprintf(trace, "%s,%s,%s",
		ns_rr_name(*rr),
		p_class(class),
		p_type(type));
	if (sect == ns_s_qd)
		return;
	fprintf(trace, ",%lu", (u_long)ns_rr_ttl(*rr));
	rd = ns_rr_rdata(*rr);
	switch (type) {
	case ns_t_soa:
		n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg),
				       rd, buf, sizeof buf);
		if (n < 0)
			goto error;
		putc(',', trace);
		fputs(buf, trace);
		rd += n;
		n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg),
				       rd, buf, sizeof buf);
		if (n < 0)
			goto error;
		putc(',', trace);
		fputs(buf, trace);
		rd += n;
		if (ns_msg_end(*msg) - rd < 5*NS_INT32SZ)
			goto error;
		for (n = 0; n < 5; n++)
			MY_GET32(soa[n], rd);
		sprintf(buf, "%u,%u,%u,%u,%u",
			soa[0], soa[1], soa[2], soa[3], soa[4]);
		break;
	case ns_t_a:
		if (ns_msg_end(*msg) - rd < 4)
			goto error;
		inet_ntop(AF_INET, rd, buf, sizeof buf);
		break;
	case ns_t_aaaa:
		if (ns_msg_end(*msg) - rd < 16)
			goto error;
		inet_ntop(AF_INET6, rd, buf, sizeof buf);
		break;
	case ns_t_mx:
		if (ns_msg_end(*msg) - rd < 2)
			goto error;
		MY_GET16(mx, rd);
		fprintf(trace, ",%u", mx);
		/* FALLTHROUGH */
	case ns_t_ns:
	case ns_t_ptr:
	case ns_t_cname:
		n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg),
				       rd, buf, sizeof buf);
		if (n < 0)
			goto error;
		break;
	/*
	 * GGM 2014/09/04 deal with edns0 a bit more clearly
	 */
	case ns_t_opt:
		{
			u_long  edns0csize;
			u_short edns0version;
			u_short edns0rcode;
			u_char  edns0dobit;
			u_char  edns0z;

			/* class encodes client UDP size accepted */
			edns0csize = (u_long)(class);

			/*
			 * the first two bytes of ttl encode edns0 version, and the extended rcode
			 */
			edns0version = ((u_long)ns_rr_ttl(*rr) & 0x00ff0000) >> 16;
			edns0rcode = ((u_long)ns_rr_ttl(*rr) & 0xff000000) >> 24;

			/*
			 *  the next two bytes of ttl encode DO bit as the top bit, and the remainder is the 'z' value
			 */
			edns0dobit = (u_long)ns_rr_ttl(*rr) & 0x8000 ? '1' : '0';
			edns0z = (u_long)ns_rr_ttl(*rr) & 0x7fff;

			/* optlen is the size of the OPT rdata */
			u_short optlen = ns_rr_rdlen(*rr);

			fprintf(trace, ",edns0[len=%d,UDP=%lu,ver=%d,rcode=%d,DO=%c,z=%d] %c\n\t",
				optlen, edns0csize, edns0version, edns0rcode, edns0dobit, edns0z, '\\');

			/* if we have any data */
			while (optlen >= 4) {
				/* the next two shorts are the edns0 opt code, and the length of the optionsection */
				u_short edns0optcod;
				u_short edns0lenopt;
				MY_GET16(edns0optcod, rd);
				MY_GET16(edns0lenopt, rd);
				optlen -= 4;
				fprintf(trace, "edns0[code=%d,codelen=%d] ", edns0optcod, edns0lenopt);

				/*
				 * Check that the OPTION-LENGTH for this EDNS0 option doesn't
				 * exceed the size of the remaining OPT record rdata.  If it does,
				 * just bail.
				 */
				if (edns0lenopt > optlen)
					goto error;

				/*
				 * "pre-consume" edns0lenopt bytes from optlen here because
				 * below we're going to decrement edns0lenopt as we go.
				 * At this point optlen will refer to the size of the remaining
			         * OPT_T rdata after parsing the current option.
				 */
				optlen -= edns0lenopt;

				/* if we have edns0_client_subnet */
				if (edns0optcod == 0x08) {
					if (edns0lenopt < 4)
						goto error;
					u_short afi;
					MY_GET16(afi, rd);
					u_short masks;
					MY_GET16(masks, rd);
					edns0lenopt -= 4;
					u_short srcmask = (masks & 0xff00) >> 8;
					u_short scomask = (masks & 0xff);

					char buf[128];
					u_char addr[16];
					memset(addr, 0, sizeof addr);
					memcpy(addr, rd, edns0lenopt < sizeof(addr) ? edns0lenopt : sizeof(addr));

					if (afi == 0x1) {
						inet_ntop(AF_INET, addr, buf, sizeof buf);
					} else if (afi == 0x2) {
						inet_ntop(AF_INET6, addr, buf, sizeof buf);
					} else {
						fprintf(trace, "unknown AFI %d\n", afi);
						strcpy(buf,"<unknown>");
					}
					fprintf(trace, "edns0_client_subnet=%s/%d (scope %d)", buf, srcmask, scomask);
				}
				/* increment the rd pointer by the remaining option data size */
				rd += edns0lenopt;
			}
		}
		break;

	default:
 error:
		sprintf(buf, "[%u]", ns_rr_rdlen(*rr));
	}
	if (buf[0] != '\0') {
		putc(',', trace);
		fputs(buf, trace);
	}
}
示例#16
0
/* Attempt to resolve the target FQDN for a context */
const char *
radiodns_resolve_target(radiodns_t *context)
{
	int len, c;
	ns_msg handle;
	ns_rr rr;
	char domain[MAXDNAME + 1], dnbuf[MAXDNAME + 1];

	/* reset these to help with error handling in callers */
	h_errno = NETDB_INTERNAL;
	errno = 0;
	if(!context->answer)
	{
		if(NULL == (context->answer = (unsigned char *) malloc(RDNS_ANSWERBUFLEN)))
		{
			return NULL;
		}
	}
	free(context->target);
	context->target = NULL;
	strcpy(domain, context->domain);
	for(;;)
	{
		h_errno = 0;
		if(0 >= (len = res_query(domain, ns_c_in, ns_t_any, context->answer, RDNS_ANSWERBUFLEN)))
		{
			if(NETDB_INTERNAL == h_errno)
			{
				return NULL;
			}
			break;
		}
		if(0 > ns_initparse(context->answer, len, &handle))
		{
			break;
		}
		if(0 > (len = ns_msg_count(handle, ns_s_an)))
		{
			break;
		}
		/* Resolvers tend towards the sane: the last result in a set of
		 * DNAME and CNAME replies will be the one we care about. If
		 * you're building against a resolver which for some reason
		 * behaves differently, you'll need a workaround here.
		 */
		dnbuf[0] = 0;
		for(c = 0; c < len; c++)
		{
			if(ns_parserr(&handle, ns_s_an, c, &rr))
			{
				/* Parse failed? Hmm. */
				continue;
			}
			if(ns_rr_class(rr) != ns_c_in)
			{
				continue;
			}
			if(ns_rr_type(rr) == ns_t_dname || ns_rr_type(rr) == ns_t_cname)
			{
				dn_expand(ns_msg_base(handle), ns_msg_base(handle) + ns_msg_size(handle), ns_rr_rdata(rr), dnbuf, sizeof(dnbuf));
			}
		}      
		if(dnbuf[0])
		{
			if(0 == strcmp(domain, dnbuf))
			{
				break;
			}
			strcpy(domain, dnbuf);
			continue;
		}
		break;
	}
	/* Whatever we found last is the target, unless we found nothing at all,
	 * in which case the target is the same as the original domain.
	 */
	if(NULL == (context->target = strdup(domain)))
	{
		return NULL;
	}    
	return context->target;
}
示例#17
0
static int 
app_follow_ptr(radiodns_app_t *app, unsigned char *abuf, ns_msg phandle, ns_rr prr)
{
	char dnbuf[MAXDNAME + 1], dbuf[4];
	char *d, *p, *endp;
	ns_msg handle;
	ns_rr rr;
	int c, len, r;
	
	dn_expand(ns_msg_base(phandle), ns_msg_base(phandle) + ns_msg_size(phandle), ns_rr_rdata(prr), dnbuf, sizeof(dnbuf));	
	if(!(app->name = (char *) calloc(1, strlen(dnbuf))))
	{
		return -2;
	}
	d = app->name;
	p = dnbuf;
	while(*p && *p != '.')
	{
		if(*p == '\\' && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]))
		{
			dbuf[0] = p[1];
			dbuf[1] = p[2];
			dbuf[2] = p[3];
			dbuf[3] = 0;
			c = strtol(dbuf, NULL, 10);
			*d = c;
			d++;
			p += 4;
			continue;
		}
		else if(*p == '\\' && p[1])
		{
			/* Skip the backslash, allowing it to escape the '.' */
			p++;
		}
		*d = *p;
		d++;
		p++;
	}
	*d = 0;
	if(0 >= (len = res_query(dnbuf, ns_c_in, ns_t_any, abuf, RDNS_ANSWERBUFLEN)))
	{
		return -1;
	}
	if(0 > ns_initparse(abuf, len, &handle))
	{
		return -1;
	}
	if(0 > (len = ns_msg_count(handle, ns_s_an)))
	{
		return -1;
	}
	if(!(app->srv = (radiodns_srv_t *) calloc(len, sizeof(radiodns_srv_t))))
	{
		return -2;
	}
	for(c = 0; c < len; c++)
	{
		if(ns_parserr(&handle, ns_s_an, c, &rr))
		{
			continue;
		}
		if(ns_rr_class(rr) != ns_c_in)
		{
			continue;
		}
		if(ns_rr_type(rr) == ns_t_txt)
		{
			app_parse_txt(app, handle, rr, dnbuf);
		}
		if(ns_rr_type(rr) == ns_t_srv)
		{
			r = app_parse_srv(app, handle, rr, dnbuf, &(app->srv[app->nsrv]));
			if(r == 0)
			{
				app->nsrv++;
			}
			else
			{
				return r;
			}
		}
				
	}
	if(app->nsrv)
	{
		return 0;
	}
	return -1;
}
示例#18
0
文件: dns.c 项目: bond/dma
int
dns_get_mx_list(const char *host, int port, struct mx_hostentry **he, int no_mx)
{
	char outname[MAXDNAME];
	ns_msg msg;
	ns_rr rr;
	const char *searchhost;
	const unsigned char *cp;
	unsigned char *ans;
	struct mx_hostentry *hosts = NULL;
	size_t nhosts = 0;
	size_t anssz;
	int pref;
	int cname_recurse;
	int err;
	int i;

	res_init();
	searchhost = host;
	cname_recurse = 0;

	anssz = 65536;
	ans = malloc(anssz);
	if (ans == NULL)
		return (1);

	if (no_mx)
		goto out;

repeat:
	err = res_search(searchhost, ns_c_in, ns_t_mx, ans, anssz);
	if (err < 0) {
		switch (h_errno) {
		case NO_DATA:
			/*
			 * Host exists, but no MX (or CNAME) entry.
			 * Not an error, use host name instead.
			 */
			goto out;
		case TRY_AGAIN:
			/* transient error */
			goto transerr;
		case NO_RECOVERY:
		case HOST_NOT_FOUND:
		default:
			errno = ENOENT;
			goto err;
		}
	}

	if (!ns_initparse(ans, anssz, &msg))
		goto transerr;

	switch (ns_msg_getflag(msg, ns_f_rcode)) {
	case ns_r_noerror:
		break;
	case ns_r_nxdomain:
		goto err;
	default:
		goto transerr;
	}

	for (i = 0; i < ns_msg_count(msg, ns_s_an); i++) {
		if (ns_parserr(&msg, ns_s_an, i, &rr))
			goto transerr;

		cp = ns_rr_rdata(rr);

		switch (ns_rr_type(rr)) {
		case ns_t_mx:
			pref = ns_get16(cp);
			cp += 2;
			err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
						 cp, outname, sizeof(outname));
			if (err < 0)
				goto transerr;

			add_host(pref, outname, port, &hosts, &nhosts);
			break;

		case ns_t_cname:
			err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
						 cp, outname, sizeof(outname));
			if (err < 0)
				goto transerr;

			/* Prevent a CNAME loop */
			if (cname_recurse++ > 10)
				goto err;

			searchhost = outname;
			goto repeat;

		default:
			break;
		}
	}

out:
	err = 0;
	if (0) {
transerr:
		if (nhosts == 0)
			err = 1;
	}
	if (0) {
err:
		err = -1;
	}

	free(ans);

	if (!err) {
		/*
		 * If we didn't find any MX, use the hostname instead.
		 */
		if (nhosts == 0)
			add_host(0, searchhost, port, &hosts, &nhosts);

		qsort(hosts, nhosts, sizeof(*hosts), sort_pref);
	}

	if (nhosts > 0) {
		/* terminate list */
		*hosts[nhosts].host = 0;
	} else {
		if (hosts != NULL)
			free(hosts);
		hosts = NULL;
	}

	*he = hosts;
	return (err);

	free(ans);
	if (hosts != NULL)
		free(hosts);
	return (err);
}
示例#19
0
文件: dns.c 项目: Brenhilt/libpki
/*! \brief Returns a MEM STACK with the requested DNS records */
PKI_MEM_STACK *URL_get_data_dns_url(URL *url, ssize_t size) {

	PKI_MEM_STACK *ret = NULL;

#ifdef HAVE_LIBRESOLV

	int type = T_A;
	PKI_MEM *obj = NULL;

	if( (!url) || (!url->addr)) {
		return NULL;
	}

	unsigned char response[NS_PACKETSZ];

	ns_msg dnsMessage;
	ns_rr dnsRecord;

	int dnsRecordSection = ns_s_an;
	int dns_msgCount = 0;
	int len = 0;

	// Check the Type of record
	if ((type = URL_get_dns_type(url->attrs)) == -1) return NULL;

	PKI_log_debug("DNS URI: Searching for %s (%s/%d)",
		url->addr, url->attrs, type);

	if ((len = res_search(url->addr, C_IN, type, response, sizeof(response))) < 0)
	{
		// An Error Occurred
		PKI_log_err("DNS URI: search failed\n");
		return NULL;
	}

	if (ns_initparse(response, len, &dnsMessage) < 0)
	{
		// This should not happen if the record is correct
		PKI_log_err("DNS URI: can not init DNS parsing of the dnsMessage\n");
		return NULL;
	}

	len = ns_msg_count(dnsMessage, dnsRecordSection);
	PKI_log_debug("DNS_URI: msg count ==> %d\n", len);

	if (len <= 0) return NULL;

	if((ret = PKI_STACK_MEM_new()) == NULL ) {
		PKI_log_debug ("DNS URI: Memory Failure");
		return NULL;
	}

	for (dns_msgCount = 0; dns_msgCount < len; dns_msgCount++)
	{
		PKI_log_debug("DNS URI: Retrieving DNS record #%d",dns_msgCount);

		if (ns_parserr(&dnsMessage, dnsRecordSection, dns_msgCount, &dnsRecord))
		{
			// ERROR: ns_parserr failed, let's continue to the next record
			PKI_log_err("DNS URI: Can not parse record %d of %d", dns_msgCount, len);
			continue;
		}

		PKI_log_debug("DNS URI: type = %d (req: %d)\n", ns_rr_type(dnsRecord), type);

		if (type == pki_ns_t_address)
		{
			switch (ns_rr_type(dnsRecord))
			{
				case T_A:
				case T_AAAA:
				case T_CNAME:
					break;
				default:
					continue;
			}
		}
		else if (type != ns_rr_type(dnsRecord))
		{
			PKI_log_debug("DNS URI: recived type %d is different from requested (%d)", 
				type, ns_rr_type(dnsRecord));
			// continue;
		}

		// int i = 0;
		int rv = 0;
		// int len = 0;
		int offset = 0;

		char dnsRecordName[MAXDNAME];

		memset(dnsRecordName, '\x0', MAXDNAME);
		// Parse the different types of DNS records
		if ((ns_rr_type(dnsRecord) == T_A) || (ns_rr_type(dnsRecord) == T_AAAA))
		{
			// These require Translation using IPv4/IPv6 functions
			int family = AF_INET;

			if (ns_rr_type(dnsRecord) == T_A) family = AF_INET;
			else family = AF_INET6;

			if(inet_ntop(family, ns_rr_rdata(dnsRecord), dnsRecordName, 
				sizeof(dnsRecordName)) == NULL)
			{
				// Can not convert
				continue;
			}
		}
		else if ((ns_rr_type(dnsRecord) == T_CNAME) || (ns_rr_type(dnsRecord) == T_MX) ||
			(ns_rr_type(dnsRecord) == T_NS))
		{
			if (ns_rr_type(dnsRecord) == T_MX) offset = NS_INT16SZ;

			rv = ns_name_uncompress(ns_msg_base(dnsMessage), ns_msg_end(dnsMessage),
				ns_rr_rdata(dnsRecord) + offset, dnsRecordName, MAXDNAME);

			// ERROR, can not uncompress the names
			if (rv < 0) continue;
		}
		else if (ns_rr_type(dnsRecord) == T_SRV)
		{
			// This requires special handling, the format is [SHORT][SHORT][SHORT][DATA]
			// unsigned short *pri = (unsigned short *) ns_rr_rdata(dnsRecord);
			// unsigned short *weight = (unsigned short *) &(ns_rr_rdata(dnsRecord)[2]);
			// unsigned short *port = (unsigned short *) &(ns_rr_rdata(dnsRecord)[4]);

			// Shall we return the additional data too ?
			// printf("PRI : %d\n", *pri);
			// printf("WEIGHT : %d\n", ntohs(*weight));
			// printf("PORT : %d\n", ntohs(*port));

			offset = 6;
			rv = ns_name_uncompress(ns_msg_base(dnsMessage), ns_msg_end(dnsMessage),
				ns_rr_rdata(dnsRecord) + offset, dnsRecordName, MAXDNAME);

			if (rv < 0) continue;
		}
		else if (ns_rr_type(dnsRecord) == T_TXT)
		{
			// Special handling required. Format is [BYTE][DATA]
			unsigned char *p = (unsigned char *)ns_rr_rdata(dnsRecord);

			snprintf(dnsRecordName, (size_t) *p+1, "%s", &ns_rr_rdata(dnsRecord)[1]);
		}
		else
		{
			PKI_log_debug("DNS URI: record type not supported [%d]", ns_rr_type(dnsRecord));
			continue;
		}

		if((obj = PKI_MEM_new_null()) == NULL ) {
			// Memory Allocation Error, we abort
			break;
		}

		if (strlen(dnsRecordName) > 0) {
			// If it is a printable value, we add the parsed version of the
			// record
			if(PKI_MEM_add(obj, (char *) dnsRecordName, strlen(dnsRecordName)) == PKI_ERR) {
				/* ERROR in memory growth */;
				PKI_log_err("DNS URI: Memory Allocation Error");
				break;
			}
		} else {
			// The value is not parsed/parsable, we return the raw data
			// the application should know what to do with the data!
			if(PKI_MEM_add(obj, (char *) ns_rr_rdata(dnsRecord), 
					ns_rr_rdlen(dnsRecord)) == PKI_ERR) {
				/* ERROR in memory growth */;
				PKI_log_err("DNS URI: Memory Allocation Error");
				break;
			}
		}

/*
		printf("MSG Data [%d]:\n", ns_rr_rdlen(dnsRecord));
		for (i=0; i < ns_rr_rdlen(dnsRecord); i++)
		{
			unsigned char *kk;

			kk = (unsigned char *) &ns_rr_rdata(dnsRecord)[i];
			printf("%x:", *kk);
		};
		printf("\n");

		fprintf(stderr, "DEBUG: RV => %d (err: %d, %s)\n", rv, h_errno, hstrerror(h_errno));
		fprintf(stderr, "DEBUG: name => %s (%s)\n", ns_rr_name(dnsRecord), url->addr);
		fprintf(stderr, "DEBUG: value => %s\n", dnsRecordName);
		fprintf(stderr, "DEBUG: type => %d\n", ns_rr_type(dnsRecord));
		fprintf(stderr, "DEBUG: class => %d\n", ns_rr_class(dnsRecord));
*/

		PKI_STACK_MEM_push(ret, obj);

		// PKI_log_debug("DNS URI: Added object #%d to stack", PKI_STACK_MEM_elements(ret));
	}

#endif

	return ret;
};