From: zacheiss Date: Mon, 19 May 2008 20:21:56 +0000 (+0000) Subject: Check for domains that have MX records but no A record. X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/commitdiff_plain/b4b129ddf094f7d000bcdc9489ccd17b446e78b1 Check for domains that have MX records but no A record. --- diff --git a/server/mr_server.h b/server/mr_server.h index 3ae29197..05630980 100644 --- a/server/mr_server.h +++ b/server/mr_server.h @@ -45,6 +45,12 @@ typedef struct _client { int hslen; /* Length of data in hsbuf */ } client; +struct mxentry +{ + char *name; + int pref; +}; + extern char krb_realm[REALM_SZ]; /* max length of query argument allowed */ @@ -157,6 +163,7 @@ int access_zephyr(struct query *q, char *argv[], client *cl); int access_container(struct query *q, char *argv[], client *cl); int access_update_user(struct query *q, char *argv[], client *cl); int check_mail_string(char *mailstring); +struct mxentry *getmxrecords(const char *); /* prototypes from qfollow.pc */ int followup_fix_modby(struct query *q, struct save_queue *sq, diff --git a/server/qaccess.pc b/server/qaccess.pc index 0b1d5138..a0b13783 100644 --- a/server/qaccess.pc +++ b/server/qaccess.pc @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include EXEC SQL INCLUDE sqlca; @@ -822,6 +825,7 @@ int check_mail_string(char *mailstring) EXEC SQL END DECLARE SECTION; char *p, *host, *hostdomain; struct hostent *hp; + struct mxentry *mxrecords = NULL; int index; p = strchr(mailstring, '@'); @@ -848,9 +852,12 @@ int check_mail_string(char *mailstring) } else { - /* couldn't resolve hostname, return MR_PERM. */ - free(host); - return MR_BAD_MAIL_STRING; + /* Possibly a host with no A record but MX records. Check. */ + mxrecords = getmxrecords(host); + if (!mxrecords) + return MR_BAD_MAIL_STRING; + else + return MR_SUCCESS; } if (!strcasecmp(host, "MIT.EDU")) @@ -891,3 +898,91 @@ int check_mail_string(char *mailstring) return MR_SUCCESS; } + +/* + * This ought to be in the bind library. It's adapted from sendmail. + */ + +/* + * These are defined in RFC833. Some bind interface headers don't declare them. + * Ghod help us if they're ever actually incompatible with what's in + * the arpa/nameser.h header. + */ +#ifndef PACKETSZ +#define PACKETSZ 512 /* maximum packet size */ +#endif +#ifndef HFIXEDSZ +#define HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#endif +#ifndef INT32SZ +#define INT32SZ 4 /* for systems without 32-bit ints */ +#endif +#ifndef INT16SZ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#endif + +/* minimum possible size of MX record in packet */ +#define MIN_MX_SIZE 8 /* corresp to "a.com 0" w/ terminating space */ + +struct mxentry *getmxrecords(const char *name) +{ + char answer[PACKETSZ], *eom, *cp, *bp; + int n, ancount, qdcount, buflen, type, pref, ind; + static struct mxentry pmx[(PACKETSZ - HFIXEDSZ) / MIN_MX_SIZE]; + static char MXHostBuf[PACKETSZ - HFIXEDSZ]; + HEADER *hp; + + pmx->name = (char *)NULL; + pmx->pref = -1; + n = res_search(name, C_IN,T_MX, (unsigned char *)&answer, sizeof(answer)); + if (n == -1) + return((struct mxentry *)NULL); + if ((size_t)n > sizeof(answer)) + n = sizeof(answer); + + hp = (HEADER *)&answer; + cp = answer + HFIXEDSZ; + eom = answer + n; + h_errno = 0; + for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ) + if ((n = dn_skipname((unsigned char *)cp, (unsigned char *)eom)) < 0) + return((struct mxentry *)NULL); + buflen = sizeof(MXHostBuf) - 1; + bp = MXHostBuf; + ind = 0; + ancount = ntohs(hp->ancount); + while (--ancount >= 0 && cp < eom) + { + if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom, + (unsigned char *)cp, bp, buflen)) < 0) + break; + cp += n; + GETSHORT(type, cp); + cp += INT16SZ + INT32SZ; + GETSHORT(n, cp); + if (type != T_MX) + { + cp += n; + continue; + } + GETSHORT(pref, cp); + if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom, + (unsigned char *)cp, bp, buflen)) < 0) + break; + cp += n; + + pmx[ind].name = bp; + pmx[ind].pref = pref; + ++ind; + + n = strlen((const char *)bp); + bp += n; + *bp++ = '\0'; + + buflen -= n + 1; + } + + pmx[ind].name = (char *)NULL; + pmx[ind].pref = -1; + return(pmx); +}