/* MIT Copyright Notice Copyright 2003 M.I.T. Permission is hereby granted, without written agreement or royalty fee, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following three paragraphs appear in all copies of this software. IN NO EVENT SHALL M.I.T. BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF M.I.T. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. M.I.T. SPECIFICALLY DISCLAIMS ANY WARRANTIES INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE SOFTWARE IS PROVIDED ON AN "AS-IS" BASIS AND M.I.T. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. $Author: tleek $ $Date: 2004/01/05 17:27:47 $ $Header: /mnt/leo2/cvs/sabo/hist-040105/sendmail/s7/txt-dns-file-bad.c,v 1.1.1.1 2004/01/05 17:27:47 tleek Exp $ */ /* Sendmail Copyright Notice Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers. All rights reserved. Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved. By using this file, you agree to the terms and conditions set forth in the LICENSE file which can be found at the top level of the sendmail distribution. $Author: tleek $ $Date: 2004/01/05 17:27:47 $ $Header: /mnt/leo2/cvs/sabo/hist-040105/sendmail/s7/txt-dns-file-bad.c,v 1.1.1.1 2004/01/05 17:27:47 tleek Exp $ */ /* */ #include "txt-dns.h" /* I believe these are needed for dn_expand to work */ #include #include #include #include #include #include #ifdef CCURED // prototypes for ccured wrappers extern int dn_expand(const u_char *msg, const u_char *eomorig, const u_char *comp_dn, char *exp_dn, int length); extern int res_search(const char *dname, int class, int type, u_char *answer, int anslen); // informing ccured about wrappers #pragma ccuredwrapper("dn_expand_wrapper", of ("dn_expand" )) #pragma ccuredwrapper("res_search_wrapper", of ("res_search")) // ccured wrappers int dn_expand_wrapper(const u_char *msg, const u_char *eomorig, const u_char *comp_dn, char *exp_dn, int length) { __write_at_least(exp_dn, length); __verify_nul(comp_dn); return ( dn_expand(__ptrof(msg), __ptrof(eomorig), __ptrof(comp_dn), __ptrof(exp_dn), length) ); } int res_search_wrapper (const char *dname, int class, int type, u_char *answer, int anslen) { __write_at_least(answer, anslen); __verify_nul(dname); return ( res_search(__ptrof(dname), class, type, __ptrof(answer), anslen) ); } #endif /* CCURED wrappers */ char *DNSFILE = "dns-file"; int DNS_REC_LEN; #if DNSMAP /* this is the type variable specifying the type of DNS queries we're interested in */ /* setting DNSMAP to TXT would lead to a potential buffer overflow */ void *xalloc(size_t sz); size_t strlcpy(char *, const char *, size_t); int read_record_from_file(unsigned char *, int); /* ** DNS_FREE_DATA -- free all components of a DNS_REPLY_T ** ** Parameters: ** r -- pointer to DNS_REPLY_T ** ** Returns: ** none. */ /* modified version of dns_free_data...calls to sm_free() were replaced with free() */ void dns_free_data(r) DNS_REPLY_T *r; { RESOURCE_RECORD_T *rr; if (r->dns_r_q.dns_q_domain != NULL) free(r->dns_r_q.dns_q_domain); for (rr = r->dns_r_head; rr != NULL; ) { RESOURCE_RECORD_T *tmp = rr; if (rr->rr_domain != NULL) free(rr->rr_domain); if (rr->rr_u.rr_data != NULL) free(rr->rr_u.rr_data); rr = rr->rr_next; free(tmp); } free(r); } /* ** PARSE_DNS_REPLY -- parse DNS reply data. ** ** Parameters: ** data -- pointer to dns data ** len -- len of data ** ** Returns: ** pointer to DNS_REPLY_T if succeeded. ** NULL otherwise. */ /* Misha: I've replaced sm_strdup with strdup and sm_srlcpy with strlcpy */ static DNS_REPLY_T * parse_dns_reply(data, len) unsigned char *data; int len; { unsigned char *p; int status; size_t l; char host[MAXHOSTNAMELEN]; DNS_REPLY_T *r; RESOURCE_RECORD_T **rr; printf("parse_dns_reply called..\n"); r = (DNS_REPLY_T *) xalloc(sizeof(*r)); memset(r, 0, sizeof(*r)); if (r == NULL) return NULL; p = data; /* doesn't work on Crays? */ memcpy((void *) &r->dns_r_h, (void *) p, (size_t) sizeof(HEADER)); p += sizeof(HEADER); /* status = dn_expand(data, data + len, p, host, sizeof host); */ strcpy(host, "LL.MIT.EDU"); /* create "compressed domain name" manually */ status = strlen(host); /* define status to be len of compressed host name */ if (status < 0) { dns_free_data(r); return NULL; } r->dns_r_q.dns_q_domain = (char *) strdup(host); if (r->dns_r_q.dns_q_domain == NULL) { dns_free_data(r); return NULL; } p += status; GETSHORT(r->dns_r_q.dns_q_type, p); printf("Record type queried = %d\n",r->dns_r_q.dns_q_type); GETSHORT(r->dns_r_q.dns_q_class, p); rr = &r->dns_r_head; while (p < data + len) { int type, class, ttl, size; strcpy(host,"BLAH.MIT.EDU"); /*status = dn_expand(data, data + len, p, host, sizeof host);*/ status = strlen(host); printf("status returned = %d\n", status); if (status < 0) { dns_free_data(r); return NULL; } p += status; GETSHORT(type, p); GETSHORT(class, p); GETLONG(ttl, p); GETSHORT(size, p); *rr = (RESOURCE_RECORD_T *) xalloc(sizeof(RESOURCE_RECORD_T)); if (*rr == NULL) { dns_free_data(r); return NULL; } (*rr)->rr_domain = (char *) strdup(host); if ((*rr)->rr_domain == NULL) { dns_free_data(r); return NULL; } (*rr)->rr_type = type; (*rr)->rr_class = class; (*rr)->rr_ttl = ttl; (*rr)->rr_size = size; printf("query type = %d\n", type); switch (type) { case T_NS: case T_CNAME: case T_PTR: status = dn_expand(data, data + len, p, host, sizeof host); if (status < 0) { dns_free_data(r); return NULL; } (*rr)->rr_u.rr_txt = (char *) strdup(host); if ((*rr)->rr_u.rr_txt == NULL) { dns_free_data(r); return NULL; } break; case T_MX: case T_AFSDB: status = dn_expand(data, data + len, p + 2, host, sizeof host); if (status < 0) { dns_free_data(r); return NULL; } l = strlen(host) + 1; (*rr)->rr_u.rr_mx = (MX_RECORD_T *) xalloc(sizeof(MX_RECORD_T) + l); if ((*rr)->rr_u.rr_mx == NULL) { dns_free_data(r); return NULL; } (*rr)->rr_u.rr_mx->mx_r_preference = (p[0] << 8) | p[1]; (void) strlcpy((*rr)->rr_u.rr_mx->mx_r_domain, host, l); break; case T_SRV: status = dn_expand(data, data + len, p + 6, host, sizeof host); if (status < 0) { dns_free_data(r); return NULL; } l = strlen(host) + 1; (*rr)->rr_u.rr_srv = (SRV_RECORDT_T*) xalloc(sizeof(SRV_RECORDT_T) + l); if ((*rr)->rr_u.rr_srv == NULL) { dns_free_data(r); return NULL; } (*rr)->rr_u.rr_srv->srv_r_priority = (p[0] << 8) | p[1]; (*rr)->rr_u.rr_srv->srv_r_weight = (p[2] << 8) | p[3]; (*rr)->rr_u.rr_srv->srv_r_port = (p[4] << 8) | p[5]; (void) strlcpy((*rr)->rr_u.rr_srv->srv_r_target, host, l); break; case T_TXT: printf("We are in the T_TXT switch block\n"); (*rr)->rr_u.rr_txt = (char *) xalloc(size + 1); if ((*rr)->rr_u.rr_txt == NULL) { dns_free_data(r); return NULL; } printf("Copying TXT record!!!\n"); printf("Copying %d bytes into a buffer of size %d!!!\n", *p, size+1); /* BAD */ (void) strncpy((*rr)->rr_u.rr_txt, (char*) p + 1, *p); /*BAD*/ (*rr)->rr_u.rr_txt[*p] = 0; break; default: (*rr)->rr_u.rr_data = (unsigned char*) xalloc(size); if (size != 0 && (*rr)->rr_u.rr_data == NULL) { dns_free_data(r); return NULL; } memcpy((void *) (*rr)->rr_u.rr_data, (void *) p, (size_t) size); } p += size; rr = &(*rr)->rr_next; } *rr = NULL; return r; } /* ** MISHA ZITSER: Instead of querying a DNS server, read info from file ** DNS_LOOKUP_INT -- looks up DNS record information in a file ** ** Parameters: ** domain -- name to lookup ** rr_class -- resource record class ** rr_type -- resource record type ** retrans -- retransmission timeout ** retry -- number of retries ** ** Returns: ** result of lookup if succeeded. ** NULL otherwise. */ DNS_REPLY_T * dns_lookup_int(domain, rr_class, rr_type, retrans, retry) const char *domain; int rr_class; int rr_type; time_t retrans; int retry; { int len; time_t save_retrans = 0; int save_retry = 0; DNS_REPLY_T *r = NULL; unsigned char reply[1024]; if (retrans > 0) { save_retrans = _res.retrans; _res.retrans = retrans; } if (retry > 0) { save_retry = _res.retry; _res.retry = retry; } if (rr_type == T_TXT){ printf("Reading from file = %s ...\n", DNSFILE); len = read_record_from_file(reply, sizeof(reply)); /* read TXT record from file */ printf("read_record_from_file returned len = %d\n", len); } else len = res_search(domain, rr_class, rr_type, reply, sizeof reply); if (len >= 0) r = parse_dns_reply(reply, len); if (retrans > 0) _res.retrans = save_retrans; if (retry > 0) _res.retry = save_retry; return r; } int read_record_from_file(unsigned char *reply, int size){ FILE *f; int i; unsigned char *temp; temp = reply; if (DNS_REC_LEN > size) return -1; /* record too big */ else{ f = fopen(DNSFILE, "r"); /* read in TXT record data */ for(i=0; idns_r_q.dns_q_domain; */ /*printf("dns_domain = %s\n", dns_domain); */ return 0; } #endif /*DNSMAP*/ /* */