Logo Search packages:      
Sourcecode: ldapdns version File versions  Download package

ldapdns.c

/* this file contains information for navigating the various LDAP schema */
#include "ldapdns.h"
#include "config.h"
#include "dns.h"
#include "ip.h"

#include <time.h>

void inline ldapdns_list_unique(list_t *p)
{
      list_t x = 0;
      list_t seen = 0;
      list_t lp, sp;

      for (lp = (*p); lp; lp = lp->next) {
            for (sp = seen; sp; sp = sp->next) {
                  if (str_equal(sp->str, lp->str)) {
                        goto HIT;
                  }
            }
            list_push(&x, lp->str);
            list_push(&seen, lp->str);
HIT:
      }

      lp = *p;
      while (list_pop(&lp));
      while (list_pop(&seen));
      *p = x;
}

static void inline ldap_escape(str_t retbuf, char *s)
{
      while (*s) {
            if (*s == ',') {
                  str_addch(retbuf, '\\');
            }
            str_addch(retbuf, *s);
            s++;
      }
}

void name_to_ldap(str_t retbuf, char *name)
{
      list_t p = 0;
      char *x;
      int i;

      str_init(retbuf);

      switch (ldapdns.dn_mode) {
      case DN_MODE_COSINE:
      case DN_MODE_LDAPDNS: /* dc=www, dc=example, dc=com */
      case DN_MODE_RFC1279: /* dc=www, dc=example, dc=com */
            p = split_name_parts(name);
            i = 0; while ((x = list_pop(&p))) { 
                  str_cat(retbuf, "dc=");
                  ldap_escape(retbuf, x);
                  str_cat(retbuf, ", ");
                  i++;
            }
            if (i) str_chopn(retbuf, 2);
            break;
      case DN_MODE_MSDNS:   /* dc=www.example.com */
            str_cat(retbuf, "dc=");
            ldap_escape(retbuf, x);
            break;
      };
}

list_t ldap_into_parts(char *dn)
{
      /* safe if dn is infact an asciiZ string */
      list_t p = 0;
      register char *x = dn, *y;
      str_t s;

      /* split into parts */
      str_init(s);
      while (*x == ' ' || *x == ',') x++; /* mostly safe :) */
      while (*x) {
            /* looking for: \s*,\s* but !~ \\. */
            if (*x == '\\') {
                  x++;
                  str_addch(s, *x);
                  x++;
            } else if (*x == ',') {
                  /* pull off excess whitespace from previous */
                  y = strchr(str(s), '\0');
                  if (y) {
                        y--;
                        while (*y == ' ') y--;
                        if (*y) y++;
                        if (*y) *y = 0;
                  }

                  list_push(&p, str(s));
                  str_init(s);
                  while (*x == ',' || *x == ' ') x++;
            } else {
                  str_addch(s, *x);
                  x++;
            }
      }

      return p;
}

void ldap_to_name(str_t retbuf, char *dn)
{
      /* safe if dn is asciiz */
      list_t z, b, p = ldap_into_parts(dn);
      char *x, *y, *q;

      /* we need the suffix here in order to pull it off */
      if (ldapdns.ldap_suffix && *ldapdns.ldap_suffix) {
            b = ldap_into_parts(ldapdns.ldap_suffix);

            for (z = b; z; z = z->next) {
                  if (str_diffi(z->str, p->str)) {
                        break;
                  } else {
                        q = list_pop(&p);
                        mem_free(q);
                  }
            }
            while ((x = list_pop(&b))) {
                  if (str_diffi(x, p->str)) {
                        mem_free(x);
                        while ((x = list_pop(&b)))
                              mem_free(x);
                        break;
                  }
                  q = list_pop(&p);
                  mem_free(q);
                  mem_free(x);
            }
      }

      /* flip p around; we have to have this in it's own list */
      list_reverse(&p);

      str_init(retbuf);
      while ((x = list_pop(&p))) {
            if (str_start(x, "dc=")) {
                  y = x + 3;
                  while (*y == ' ') y++;
                  if (*y != ',') {
                        str_cat(retbuf, y);
                        str_addch(retbuf, '.');
                  }
            }
            mem_free(x);
      }
      str_chop(retbuf);
}

static int inline __parse_soa(dns_ctx *c, bin_t rrdata, int flag)
{
      register unsigned int i, j;
      unsigned long ar[5];
      register char *q;
      str_t tmp, tmp2;

      q = caddr(rrdata);
      if (flag) {
            if (clen(rrdata) >= 1 && *q == '*') {
                  c->wantdie=1;
                  return 0;
            }
            /* don't want anything else */
            if (clen(rrdata) == 1)
                  return 0;
      }
      if (c->soahack) return 1;     /* skip */

      /* remainder is of the format is serial [ttl retry expire minimum] */
      for (j = i = 0; j < 5; j++) { /* safe: bounded */
            if (!(i < clen(rrdata))) break;
            while (isspace(((unsigned int)q[i])) && i < clen(rrdata)) i++;
            if (!(i < clen(rrdata))) break;
            ar[j] = 0;
            while (isdigit(((unsigned int)q[i])) && i < clen(rrdata)) {
                  ar[j] *= 10;
                  switch (q[i]) {
                  case '0': ar[j] += 0; break;
                  case '1': ar[j] += 1; break;
                  case '2': ar[j] += 2; break;
                  case '3': ar[j] += 3; break;
                  case '4': ar[j] += 4; break;
                  case '5': ar[j] += 5; break;
                  case '6': ar[j] += 6; break;
                  case '7': ar[j] += 7; break;
                  case '8': ar[j] += 8; break;
                  case '9': ar[j] += 9; break;
                  };
                  i++;
            }
      }
      if (j < 4 || ar[4] == 0) {
            /* if j == 1 then... */
            switch (j) {
            case 2: c->refresh = ar[1];
            case 1: if (ar[0]) c->serial = ar[0];
            };
            return 0;
      }
      /* these are kept in host-endian form (for now) */
      if (ar[0]) c->serial = ar[0];
      c->refresh = ar[1];
      c->retry = ar[2];
      c->expire = ar[3];
      c->minimum = ar[4];
      c->ttl = c->minimum;
      if (i < clen(rrdata)) {
            /* grap ADM as well */
            str_init(tmp);
            str_catb(tmp, caddr(rrdata)+i, clen(rrdata)-i);
            name_to_dns_fix(tmp2, str(tmp), 2); /* email address? */
            list_push(&c->ADM, str(tmp2));
            mem_free(str(tmp));
      }
      c->soahack = 1;

      return 1;
}
static char inline *__parse_name(dns_ctx *c, bin_t rrdata)
{
      str_t tmp;
      bin_t retval;
      int addzone;

      /* name is in ascii form.... convert to DNS */
      bin_init(retval);
      bin_copy(retval, caddr(rrdata), clen(rrdata));
      addzone = 0;
      if (ldapdns.relative_names) {
            /* if . is the last character... */
            if (clen(retval) && caddr(retval)[clen(retval)-1] != '.') {
                  addzone = 1;
            }
      }
      bin_0(retval);
      name_to_dns(tmp, (char *)caddr(retval));
      if (addzone && c->request_name_zone) {
            /* add the zone to the end */
            str_cat(tmp, c->request_name_zone);
      }
      bin_copy(retval, str(tmp), dns_domain_length(str(tmp)));

      return (char *)caddr(retval);
}
static char inline *__parse_mx(dns_ctx *c, bin_t rrdata)
{
      str_t tmp;
      bin_t retval;
      unsigned short pref;
      char *q;
      register int b, len;
      int addzone;

      /* name is in ascii form.... convert to DNS */
      bin_init(retval);
      q = (char *)caddr(rrdata);
      len = clen(rrdata);
      pref = 0;
      while (len > 0 && *q) {
            switch (*q) {
            case '0': b = 0; break;
            case '1': b = 1; break;
            case '2': b = 2; break;
            case '3': b = 3; break;
            case '4': b = 4; break;
            case '5': b = 5; break;
            case '6': b = 6; break;
            case '7': b = 7; break;
            case '8': b = 8; break;
            case '9': b = 9; break;
            default: b = -1; break;
            };
            if (b == -1) break;
            pref *= 10;
            pref += b;
            q++; len--;
      }
      while (len > 0 && *q == ' ') { q++; len--; }

      bin_copy(retval, q, len);
      addzone = 0;
      if (ldapdns.relative_names) {
            /* if . is the last character... */
            if (caddr(retval)[clen(retval)-1] != '.') {
                  addzone = 1;
            }
      }
      bin_0(retval);
      name_to_dns(tmp, (char *)caddr(retval));
      if (addzone && c->request_name_zone) {
            /* add the zone to the end */
            str_cat(tmp, c->request_name_zone);
      }

      /* Clib */
      pref = htons(pref);
      bin_copy(retval, (char *)&pref, 2);
      bin_cat(retval, str(tmp), dns_domain_length(str(tmp)));
      mem_free(str(tmp));

      return (char *)caddr(retval);
}
static char inline *__parse_ipv4(dns_ctx *c, bin_t rrdata)
{
      /* rrdata is in the form of A.B.C.D; so length bind it... */
      unsigned char ip[8];
      register int i, j, a, b, r;
      bin_t retval;
      int cflag;

      bin_init(retval);
      ip[4] = ip[5] = ip[6] = ip[7] = 0;
      for (i = j = a = cflag = 0; (cflag || j < 4) && i < clen(rrdata); i++) {
            switch (rrdata->buf[i]) {
            case '0': b = 0; break;
            case '1': b = 1; break;
            case '2': b = 2; break;
            case '3': b = 3; break;
            case '4': b = 4; break;
            case '5': b = 5; break;
            case '6': b = 6; break;
            case '7': b = 7; break;
            case '8': b = 8; break;
            case '9': b = 9; break;
            case '.': ip[j] = a; a = 0; j++; continue;
            case '/': /* i think we're making a subnet-switch */
                  if (!c) /* fail early */
                        return 0;
                  ip[j] = a;
                  j = 4;
                  a = 0;
                  cflag = 1;
                  continue;
            case '=':
                  if (!c) /* fail early */
                        return 0;
                  ip[j] = a;
                  if (j == 0) {
                        ip[4] = 0xff;
                        ip[5] = ip[6] = ip[7] = 0;
                  } else if (j == 1) {
                        ip[4] = ip[5] = 0xff;
                        ip[6] = ip[7] = 0;
                  } else if (j == 2) {
                        ip[4] = ip[5] = ip[6] = 0xff;
                        ip[7] = 0;
                  } else if (j == 3) {
                        ip[4] = ip[5] = ip[6] = ip[7] = 0xff;
                  } else if (j == 4) {
                        if (ip[4] == 0) {
                              /* exact match */
                              ip[4] = ip[5] = ip[6] = ip[7] = 255;
                        } else if (ip[4] == 255) {
                              /* 255.0.0.0 */
                              ip[4] = 255;
                              ip[5] = ip[6] = ip[7] = 0;
                        } else {
                              /* okay /CIDR notation */
                              r = ip[4];
                              ip[4] = ip[5] = ip[6] = ip[7] = 255;
                              if (r < 8) {
                                    ip[4] = (255 << (8 - r));
                                    ip[5] = ip[6] = ip[7] = 0;
                              } else if (r < 16) {
                                    ip[5] = (255 << (16 - r));
                                    ip[6] = ip[7] = 0;
                              } else if (r < 24) {
                                    ip[6] = (255 << (24 - r));
                                    ip[7] = 0;
                              } else {
                                    ip[7] = (255 << (32 - r));
                              }
                        }
                  }
                  if (ipv4_in_subnet(ip, c->ip)) {
                        /* reset and start over */
                        j = b = a = 0;
                        cflag = 0;
                        /* note, we also blop
                         * 'c' so we can't do this again */
                        c = (dns_ctx *)0;
                        continue;
                  }
                  return 0; /* don't return anything */
            case '%':
                  if (c && j == 3) {
                        if (!c->swm) return 0;
                        /* next chars are "switch" */
                        b = 0; i++;
                        while (i < clen(rrdata)) {
                              /* make sure it matches switch */
                              if (c->swm[b] != rrdata->buf[i])
                                    return 0;
                              b++; i++;
                        }
                        goto done_parsing_l;
                  }
                  /* fall through */
            default:
                  /* invalid */
                  warning("invalid IPV4 address (%c, %d)", rrdata->buf[i], i);
                  return 0;
            };

            /* digit */
            a *= 10; a += b;
      }
done_parsing_l:
      ip[j] = a;
      bin_copy(retval, ip, 4);
      return (char *)caddr(retval);
}
static char inline *__parse_email(bin_t rrdata)
{
      str_t tmp;
      bin_t retval;

      /* name is in ascii form.... convert to DNS */
      bin_init(retval);
      bin_copy(retval, caddr(rrdata), clen(rrdata));
      bin_0(retval);
      name_to_dns_fix(tmp, (char *)caddr(retval), 2);
      bin_copy(retval, str(tmp), dns_domain_length(str(tmp)));

      return (char *)caddr(retval);
}
static char inline *__parse_txt(bin_t rrdata)
{
      str_t tmp;
      bin_t retval;

      /* don't dns-encode the TXT segment */
      bin_init(retval);
      bin_addch(retval, clen(rrdata));
      bin_cat(retval, caddr(rrdata), clen(rrdata));
      bin_0(retval);

      return (char *)caddr(retval);
}
static char inline *__parse_generic(bin_t rrdata)
{
      /* return MUST contain length:
       * order:   rr len data....
       */
      bin_t retval;
      unsigned short n;

      bin_init(retval);
      bin_copy(retval, caddr(rrdata), 2);
      /* n is in host-byte order */
      n = clen(rrdata)-2;
      bin_copy(retval, (char *)&n, 2);
      bin_copy(retval, caddr(rrdata)+2, n);

      return (char *)caddr(retval);
}

/* bind-style */
static int inline ldap_dnsrecord_rfc1279(dns_ctx *c, bin_t rrdata)
{
      register char *q;
      register int len;
      char rr[2];
      bin_t tmp;
      int r;

      /* IN rr [str] */
      if (clen(rrdata) < 4) return 0;
      if (!(tolower((unsigned int)(caddr(rrdata)[0])) == 'i'
      && tolower((unsigned int)(caddr(rrdata)[1])) == 'n')) {
            return 0;
      }

      /* step over whitespace[s] */
      q = caddr(rrdata) + 2; len = clen(rrdata) - 2;
      while (len > 0 && (*q == ' ' || *q == '\t')) { q++; len--; }
      if (len < 2) return 0;

      /* parse word */
#define _setrr(x) do { rr[0] = x[0]; rr[1] = x[1]; } while (0)
      q[0] = toupper(((unsigned int)q[0])); /* modifying rrdata! */
      if (q[0] == 'A') {
            /* modifying rrdata */
            if (toupper(((unsigned int)q[1])) == 'A') {
                  /* AAAA: not supported (yet) */
                  return 0;
            }
            /* A: address record */
            _setrr(DNS_T_A);
      } else if (q[0] == 'C') {
            /* CNAME: alias */
            _setrr(DNS_T_CNAME);
      } else if (q[0] == 'T') {
            /* TXT: text record */
            _setrr(DNS_T_TXT);
      } else if (q[0] == 'P') {
            /* PTR: pointer-name */
            _setrr(DNS_T_PTR);
      } else if (q[0] == 'M') {
            /* MX: mail exchanger */
            _setrr(DNS_T_MX);
      } else if (q[0] == 'N') {
            /* NS: name server */
            _setrr(DNS_T_NS);
      } else if (q[0] == 'S') {
            /* SOA: start of authority */
            _setrr(DNS_T_SOA);
      }
#undef _setrr

      /* parse RR -- pass everything but SOA to their ldapdns parser */
      while (len > 0 && (*q != ' ' && *q != '\t')) { q++; len--; }
      if (len < 2) return 0;

      while (len > 0 && (*q == ' ' || *q == '\t')) { q++; len--; }
      if (len < 2) return 0;

#define _eq4(x) (rr[0] == x[0] && rr[1] == x[1])
      if (_eq4(DNS_T_SOA)) {
            /* start of authority */
            if (*q == '(') {
                  q++; len--;
                  if (len < 2) return 0;
                  while (len > 0 && (*q == ' ' || *q == '\t')) { q++; len--; }
                  if (len < 2) return 0;
            }
            for (r = 0; r < len; r++) {
                  if (q[r] == ')') {
                        r--;
                        while ((q[r] == ' ' || q[r] == '\t') && r > 0)
                              r--;
                        len = r;
                        break;
                  }
            }
            /* fall through */
      }

      bin_init(tmp);
      bin_copy(tmp, q, len);
      r = 1;
      if (_eq4(DNS_T_A)) {
            /* disables client differentiation */
            list_push(&c->A, __parse_ipv4((dns_ctx *)0, tmp));
      } else if (_eq4(DNS_T_PTR)) {
            list_push(&c->PTR, __parse_name(c, tmp));
      } else if (!c->subreq) {
            if (_eq4(DNS_T_MX)) {
                  list_push(&c->MX, __parse_mx(c, tmp));
            } else if (_eq4(DNS_T_CNAME)) {
                  list_push(&c->CNAME, __parse_name(c, tmp));
            } else if (_eq4(DNS_T_NS)) {
                  list_push(&c->NS, __parse_name(c, tmp));
            } else if (_eq4(DNS_T_TXT)) {
                  list_push(&c->TXT, __parse_txt(tmp));
            } else if (_eq4(DNS_T_SOA)) {
                  r = __parse_soa(c, tmp, 0);
            } else
                  r = 0;
      } else
            r = 0;
#undef _eq4
      mem_free(caddr(tmp));
      return r;
}
/* microsoft-style */
static int inline ldap_dnsrecord_msdns(dns_ctx *c, bin_t rrdata)
{
      register char *q;
      bin_t retval;

      if (clen(rrdata) < 24) return 0;

      /* data is in a binary-packed format which i'm not 100% on:
       * each two-character blob is a single octet. some things are
       * in network byte-order, other things are NOT. this can be
       * confusing quick...
       *
       * note that places where I've marked the field as 'xx' means i don't
       * know what it is. 0x means that it's always 00 (in my tests)
       * but that i still don't know what it is...
       *
       * HEADER:
       *
       * xx xx    [0-1]
       * RR RR    16-bit: resource record [2-3]
       * xx xx 0x 0x xx xx 0x 0x [4-11]
       * TT TT TT TT    32-bit: time to live [12-15]
       * 0x 0x 0x 0x xx xx xx xx [16-23]
       *          -- last dword has significance for A-records
       *
       * what follows is RR-data [24]:
       *
       * SOA-RR:
       *    SS SS SS SS serial
       *    AA AA AA AA refresh
       *    BB BB BB BB retry
       *    CC CC CC CC expire
       *    DD DD DD DD minimum
       *
       * (44)     ll el d.d.d length (ll), elements (el), dns-encoded NS1
       *    ll el d.d.d length (ll), elements (el), hostmaster
       *
       * NS-RR
       *    ll el d.d.d length (ll), elements (el), dns-encoded name
       *
       * A-RR
       *    a. b. c. d. ip address
       *
       * MX-RR
       *    pp pp       preference
       *    ll el d.d.d length (ll), elements (el), mail server
       *
       * CNAME-RR
       *    (same as ns)
       * PTR-RR
       *    (same as ns)
       * TXT-RR
       *    (same as ns; BUT there's ALWAYS only 1 segment)
       *
       */
#define _eq3(a) (a[0] == (caddr(rrdata)[2]) && a[1] == (caddr(rrdata)[3]))
      bin_init(retval);
      if (_eq3(DNS_T_SOA)) {
            /* Clib */
            c->refresh = ntohl(*((unsigned long *)(caddr(rrdata)+12)));
            c->serial = ntohl(*((unsigned long *)(caddr(rrdata)+24)));
            c->retry  = ntohl(*((unsigned long *)(caddr(rrdata)+32)));
            c->expire = ntohl(*((unsigned long *)(caddr(rrdata)+36)));
            c->minimum = ntohl(*((unsigned long *)(caddr(rrdata)+40)));
            c->ttl = c->minimum;

            q = caddr(rrdata) + 44;
            q++; q++; q += dns_domain_length(q)+1;
            q++; q++;
            bin_copy(retval, q, dns_domain_length(q));
            list_push(&c->ADM, caddr(retval));
      } else if (_eq3(DNS_T_NS)) {
            q = caddr(rrdata) + 26;
            bin_copy(retval, q, dns_domain_length(q));
            list_push(&c->NS, caddr(retval));
      } else if (_eq3(DNS_T_A)) {
            q = caddr(rrdata) + 24;
            bin_copy(retval, q, 4);
            list_push(&c->MX, caddr(retval));
      } else if (_eq3(DNS_T_MX)) {
            q = caddr(rrdata) + 24;
            bin_copy(retval, q, 2);
            q += 4; /* pref and ll,el */
            bin_cat(retval, q, dns_domain_length(q));
            list_push(&c->MX, caddr(retval));
      } else if (_eq3(DNS_T_CNAME)) {
            q = caddr(rrdata) + 26;
            bin_copy(retval, q, dns_domain_length(q));
            list_push(&c->CNAME, caddr(retval));
      } else if (_eq3(DNS_T_PTR)) {
            q = caddr(rrdata) + 26;
            bin_copy(retval, q, dns_domain_length(q));
            list_push(&c->PTR, caddr(retval));
      } else if (_eq3(DNS_T_TXT)) {
            q = caddr(rrdata) + 26;
            bin_copy(retval, q, dns_domain_length(q));
            list_push(&c->TXT, caddr(retval));
      } else {
            /* didn't really need it */
            mem_free(caddr(retval));
            return 0;
      }

      return 1;
}
/* me-style */
static int inline ldap_arecord(dns_ctx *c, bin_t rrdata)
{
      list_push(&c->A, __parse_ipv4(c, rrdata));
      return 1;
}
static int inline ldap_serial(dns_ctx *c, bin_t rrdata)
{
      register int i, ylen;
      unsigned int Y,M,D, h,m,s;
      struct tm tp;
      time_t trymk;

      if (c->soahack) return 1;     /* skip */

      /* this is NOT a linear number:
       * it is a timestamp... and should be treated as such
       */
      if (clen(rrdata) < 15) return 0;

      ylen = clen(rrdata) - 11;
      for (i = Y = 0; i < ylen; i++) {
            Y *= 10;
            Y += str_chtoi(caddr(rrdata)[i]);
      }
      M = str_chtoi(caddr(rrdata)[i]) * 10; i++;
      M += str_chtoi(caddr(rrdata)[i]); i++;
      D = str_chtoi(caddr(rrdata)[i]) * 10; i++;
      D += str_chtoi(caddr(rrdata)[i]); i++;

      h = str_chtoi(caddr(rrdata)[i]) * 10; i++;
      h += str_chtoi(caddr(rrdata)[i]); i++;
      m = str_chtoi(caddr(rrdata)[i]) * 10; i++;
      m += str_chtoi(caddr(rrdata)[i]); i++;
      s = str_chtoi(caddr(rrdata)[i]) * 10; i++;
      s += str_chtoi(caddr(rrdata)[i]); i++;

      tp.tm_sec = s;
      tp.tm_min = m;
      tp.tm_hour = h;
      tp.tm_mday = D;
      tp.tm_mon = M-1;
      tp.tm_year = Y-1900;
      tp.tm_wday = tp.tm_yday = 0;
      if (caddr(rrdata)[i] == 'z') {
            tp.tm_isdst = 0;
            c->serial = mktime(&tp);
      } else {
            tp.tm_isdst = 1;
            trymk  = mktime(&tp);
            if (trymk == -1 || trymk == 11 || trymk == 1) {
                  /*
                   * it would not happen if the ldapserver was always
                   * using GMT....
                   */
                  tp.tm_isdst = 0;
                  trymk  = mktime(&tp);
            }
            c->serial = trymk;
      }

      return 1;
}
static int inline ldap_mxrecord(dns_ctx *c, bin_t rrdata)
{
      if (!c->subreq) {
            list_push(&c->MX, __parse_mx(c, rrdata));
      }
      return 1;
}
static int inline ldap_mail(dns_ctx *c, bin_t rrdata)
{
      if (!c->subreq) {
            list_push(&c->ADM, __parse_email(rrdata));
      }
      return 1;
}
static int inline ldap_cnamerecord(dns_ctx *c, bin_t rrdata)
{
      static char *inaddr_str = "\007in-addr\004arpa";
      /* check to see if we're in in_addr space */
      register char *q;
      
      if (c->request_name) {
            q = c->request_name + dns_domain_length(c->request_name);
            q -= 14; /* in-addr.arpa. */

            if (str_equal(q, inaddr_str)) {
                  /* yeehaw */
                  list_push(&c->PTR, __parse_name(c, rrdata));
                  return 1;
            }
      }
      if (!c->subreq) {
            /* ignore CNAME on subrequest */
            list_push(&c->CNAME, __parse_name(c, rrdata));
      }
      return 1;
}
static int inline ldap_description(dns_ctx *c, bin_t rrdata)
{
      if (!c->subreq) {
            list_push(&c->TXT, __parse_txt(rrdata));
      }
      return 1;
}
static int inline ldap_photo(dns_ctx *c, bin_t rrdata)
{
      list_push(&c->Generic, __parse_generic(rrdata));
      return 1;
}
static int inline ldap_nsrecord(dns_ctx *c, bin_t rrdata)
{
      if (!c->subreq) {
            list_push(&c->NS, __parse_name(c, rrdata));
      } else {
            c->subreq_valid++;
      }
      return 1;
}
static int inline ldap_seealso(dns_ctx *c, bin_t rrdata)
{
      list_push(&c->PTR, __parse_name(c, rrdata));
      return 1;
}
static int inline ldap_soarecord(dns_ctx *c, bin_t rrdata)
{
      if (!c->subreq) {
            return __parse_soa(c, rrdata, 1);
      }
      return 0;
}
static void inline handle_ldap_rrdata(dns_ctx *c, char *attr, bin_t rrdata)
{
      switch (attr[0]) {
      case 'a':
            /* aRecord */
            ldap_arecord(c, rrdata);
            break;
      case 'c': /* cNAMERecord */
            ldap_cnamerecord(c, rrdata);
            break;
      case 'd':
            if (attr[1] == 'n') {
                  if (attr[2] == 's') {
                        /* dnsRecord */
                        switch (ldapdns.dn_mode) {
                        case DN_MODE_RFC1279:
                              ldap_dnsrecord_rfc1279(c, rrdata);
                              break;
                        case DN_MODE_MSDNS:
                              ldap_dnsrecord_msdns(c, rrdata);
                              break;
                        };
                  }
            } else {
                  /* description */
                  ldap_description(c, rrdata);
            }
            break;
      case 'm':
            if (attr[1] == 'o') {
                  break;

            } else if (attr[1] == 'x') {
                  /* mXRecord */
                  ldap_mxrecord(c, rrdata);
            } else {
                  /* mail */
                  ldap_mail(c, rrdata);
            }
            break;
      case 'n':
            /* nSRecord */
            ldap_nsrecord(c, rrdata);
            break;
      case 'p': /* generic record (photo) */
            ldap_photo(c, rrdata);
            break;
      case 's':
            /* sOARecord */
            if (attr[1] == 'e') {
                  /* seeAlso */
                  ldap_seealso(c, rrdata);
            } else {
                  /* sOARecord */
                  ldap_soarecord(c, rrdata);
            }
            break;
      };
}
int ldap_load_dns_attributes(dns_ctx *c, char **dn, int zonef)
{
      /* should be safe; barring any strangeness from ldap client lib */
      BerElement *ber;
      char *attr, *val;
      struct berval **bvals;
      bin_t rrdata;
      int i, len;
      LDAPMessage *m;

      m = ldap_first_entry(c->c->ldap_con, c->message);
      if (!m) {
            return 0; /* out of entries */
      }

      if (dn) {
            *dn = ldap_get_dn(c->c->ldap_con, m);
      }

      bin_init(rrdata);
      attr = ldap_first_attribute(c->c->ldap_con, m, &ber);
      while (attr) {
            if (!m) break; /* weird */

            bvals = ldap_get_values_len(c->c->ldap_con, m, attr);
            if (!bvals) /* server problem could halt here */
                  break;

            str_lc(attr);

            for (i = 0; bvals[i]; i++) {
                  len = bvals[i]->bv_len;
                  if (len < 1)
                        continue;

                  val = bvals[i]->bv_val;
                  if (!val) /* should never happen */
                        continue;

                  if (attr[0] == 'a' && attr[1] == 's') {
                        /* associated Domain */
                        c->adlen = bvals[i]->bv_len;
                        continue;
                  }


                  /* convert to bin */
                  bin_copy(rrdata, val, bvals[i]->bv_len);

                  if (attr[0] == 'm' && attr[1] == 'o') {
                        /* modify timestamp */
                        if (zonef) ldap_serial(c, rrdata);
                        continue;
                  }

                  handle_ldap_rrdata(c, attr, rrdata);
            }

            ldap_value_free_len(bvals);
            ldap_memfree(attr);

            attr = ldap_next_attribute(c->c->ldap_con, m, ber);
      }
      ber_free(ber, 0);
      mem_free(caddr(rrdata));
      while (m) m = ldap_next_entry(c->c->ldap_con, m);
      return 1;
}

Generated by  Doxygen 1.6.0   Back to index