Back to index

courier  0.68.2
rfc1035reply.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 1999 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "rfc1035.h"
00007 #include      <stdlib.h>
00008 #include      <string.h>
00009 #include      <errno.h>
00010 
00011 
00012 void rfc1035_replyfree(struct rfc1035_reply *p)
00013 {
00014 struct rfc1035_reply *q;
00015 
00016        while (p)
00017        {
00018               q=p->next;
00019               if (p->mallocedbuf)  free(p->mallocedbuf);
00020               if (p->qdptr) free(p->qdptr);
00021               if (p->anptr) free(p->anptr);
00022               if (p->nsptr) free(p->nsptr);
00023               if (p->arptr) free(p->arptr);
00024               if (p->allrrs)       free(p->allrrs);
00025               free(p);
00026               p=q;
00027        }
00028 }
00029 
00030 const char *rfc1035_replyuncompress(const char **ptr,
00031        const struct rfc1035_reply *reply, char *namebuf)
00032 {
00033 unsigned i=0;
00034 unsigned l;
00035 const char *end=reply->reply+reply->replylen;
00036 const char *newptr=0;
00037 int    cnt=0;
00038 
00039        for (;;)
00040        {
00041               if ( (*ptr) == end)  return (0);
00042               l=(unsigned char)*(*ptr)++;
00043               if (l > 63)
00044               {
00045                      if ((l & 0xC0) != 0xC0)     return (0);
00046                      if ( (*ptr) == end)  return (0);
00047                      l= ((l & 63) << 8) + (unsigned char)*(*ptr)++;
00048                      if (l >= reply->replylen)   return (0);
00049                      ptr= &newptr;
00050                      newptr=reply->reply+l;
00051                      if ( ++cnt > 100)    return (0);
00052                                           /* Detect loops */
00053 
00054                      continue;
00055               }
00056               if (l == 0)   break;
00057               if (i)
00058               {
00059                      if (i >= RFC1035_MAXNAMESIZE)      return (0);
00060                      if (namebuf) namebuf[i]='.';
00061                      ++i;
00062               }
00063               if (RFC1035_MAXNAMESIZE-i < l)     return (0);
00064 
00065               if (reply->reply + reply->replylen - (*ptr) < l)
00066                      return (0);
00067 
00068               if (namebuf)
00069                      memcpy(namebuf+i, *ptr, l);
00070               i += l;
00071               *ptr += l;
00072        }
00073 
00074        if (namebuf)  namebuf[i]=0;
00075        return (namebuf ? namebuf:"");
00076 }
00077 
00078 const char *rfc1035_replyhostname( const struct rfc1035_reply *r, const char *n,
00079        char *namebuf)
00080 {
00081 const char *p=rfc1035_replyuncompress(&n, r, namebuf);
00082 
00083        if (!p)       strcpy(namebuf, "error");
00084        return (p);
00085 }
00086 
00087 static void doparse(struct rfc1035_reply *, struct rfc1035_rr *);
00088 
00089 struct rfc1035_reply *rfc1035_replyparse(const char *p, unsigned l)
00090 {
00091 struct rfc1035_reply *r=(struct rfc1035_reply *)
00092        malloc(sizeof(struct rfc1035_reply));
00093 char   c;
00094 unsigned n;
00095 int    pass;
00096 unsigned *lenptrs[3];
00097 struct rfc1035_rr *rrptrs[3];
00098 const char *end=p+l;
00099 unsigned allcnt;
00100 
00101        if (!r)       return (0);
00102        r->next=0;
00103        r->reply=p;
00104        r->replylen=l;
00105        r->mallocedbuf=0;
00106        memset(&r->server_addr, 0, sizeof(r->server_addr));
00107        r->qdptr=0;
00108        r->anptr=0;
00109        r->nsptr=0;
00110        r->arptr=0;
00111        r->allrrs=0;
00112 
00113        if (l < 12)
00114        {
00115               errno=EINVAL;
00116               rfc1035_replyfree(r);
00117               return (0);
00118        }
00119 
00120        c=p[2];
00121        r->rd= c & 1;
00122        c >>= 1;
00123        r->tc= c & 1;
00124        c >>= 1;
00125        r->aa= c & 1;
00126        c >>= 1;
00127        r->opcode= c & 15;
00128        c >>= 4;
00129        r->qr= c & 1;
00130 
00131        r->ra=(p[3] >> 7) & 1;
00132        r->ad=(p[3] >> 5) & 1;
00133        r->cd=(p[3] >> 4) & 1;
00134        r->rcode=p[3] & 15;
00135 
00136        r->qdcount= ((unsigned)(unsigned char)p[4] << 8) | (unsigned char)p[5];
00137        r->ancount= ((unsigned)(unsigned char)p[6] << 8) | (unsigned char)p[7];
00138        r->nscount= ((unsigned)(unsigned char)p[8] << 8) | (unsigned char)p[9];
00139        r->arcount= ((unsigned)(unsigned char)p[10]<< 8) | (unsigned char)p[11];
00140 
00141        if (r->qdcount >= l || r->ancount >= l || r->nscount >= l ||
00142               r->arcount >= l ||
00143               (n=r->qdcount + r->ancount) >= l ||
00144               (n += r->nscount) >= l ||
00145               n + r->arcount >= l)
00146        {
00147               errno=EINVAL;
00148               rfc1035_replyfree(r);
00149               return (0);
00150        }
00151 
00152        if ((r->qdcount && (r->qdptr=malloc(sizeof(struct rfc1035_query)
00153                             * r->qdcount)) == 0) ||
00154               (r->ancount && (r->anptr=malloc(sizeof(struct rfc1035_rr)
00155                             * r->ancount)) == 0) ||
00156               (r->nscount && (r->nsptr=malloc(sizeof(struct rfc1035_rr)
00157                             * r->nscount)) == 0) ||
00158               (r->arcount && (r->arptr=malloc(sizeof(struct rfc1035_rr)
00159                             * r->arcount)) == 0) ||
00160               (r->ancount + r->nscount + r->arcount &&
00161                      (r->allrrs=malloc(sizeof(*r->allrrs)*(
00162                             r->ancount + r->nscount + r->arcount))) == 0)
00163               )
00164        {
00165               rfc1035_replyfree(r);
00166               return (0);
00167        }
00168 
00169        p += 12;
00170        l -= 12;
00171        for (n=0; n<r->qdcount; n++)
00172        {
00173               r->qdptr[n].name=p;
00174               if (rfc1035_replyuncompress( &p, r, 0 ) == 0)
00175               {
00176                      errno=EINVAL;
00177                      rfc1035_replyfree(r);
00178                      return (0);
00179               }
00180 
00181               if (p > end-4)       return (0);
00182 
00183               r->qdptr[n].qtype=((unsigned)(unsigned char)p[0] << 8)
00184                             | (unsigned char)p[1];
00185               p += 2;
00186               r->qdptr[n].qclass=((unsigned)(unsigned char)p[0] << 8)
00187                             | (unsigned char)p[1];
00188               p += 2;
00189        }
00190 
00191        lenptrs[0]= &r->ancount;
00192        lenptrs[1]= &r->nscount;
00193        lenptrs[2]= &r->arcount;
00194        rrptrs[0]= r->anptr;
00195        rrptrs[1]= r->nsptr;
00196        rrptrs[2]= r->arptr;
00197 
00198        allcnt=0;
00199 
00200        for (pass=0; pass<3; pass++)
00201        {
00202        struct rfc1035_rr *rrp= rrptrs[pass];
00203 
00204               for (n=0; n< *lenptrs[pass]; n++)
00205               {
00206                      r->allrrs[allcnt++]=rrp;
00207                      rrp->rrname=p;
00208                      if (rfc1035_replyuncompress( &p, r, 0 )
00209                             == 0)
00210                      {
00211                             errno=EINVAL;
00212                             rfc1035_replyfree(r);
00213                             return (0);
00214                      }
00215 
00216                      if (p > end-10)      return (0);
00217                      rrp->rrtype=((unsigned)(unsigned char)p[0] << 8)
00218                             | (unsigned char)p[1];
00219                      p += 2;
00220                      rrp->rrclass=((unsigned)(unsigned char)p[0] << 8)
00221                             | (unsigned char)p[1];
00222                      p += 2;
00223                      rrp->ttl=((RFC1035_UINT32)(unsigned char)p[0] << 24) |
00224                             ((RFC1035_UINT32)(unsigned char)p[1] << 16) |
00225                             ((RFC1035_UINT32)(unsigned char)p[2] << 8) |
00226                             (unsigned char)p[3];
00227                      p += 4;
00228 
00229                      rrp->rdlength=((unsigned)(unsigned char)p[0] << 8)
00230                             | (unsigned char)p[1];
00231                      p += 2;
00232                      rrp->rdata= rrp->rdlength ? p:0;
00233                      if (end - p < rrp->rdlength)
00234                      {
00235                             errno=EINVAL;
00236                             rfc1035_replyfree(r);
00237                             return (0);
00238                      }
00239                      p += rrp->rdlength;
00240                      doparse(r, rrp);
00241                      ++rrp;
00242               }
00243        }
00244        return (r);
00245 }
00246 
00247 static void doparse(struct rfc1035_reply *r, struct rfc1035_rr *rr)
00248 {
00249 const char *p;
00250 static const char error[]="\005error";
00251 
00252        memset(&rr->rr, '\0', sizeof(rr->rr));
00253        if (rr->rrclass != RFC1035_CLASS_IN)      return;
00254 
00255        switch (rr->rrtype)  {
00256        case RFC1035_TYPE_A:
00257 
00258               if (rr->rdlength < 4)
00259                      rr->rr.inaddr.s_addr=0;
00260               else
00261                      memcpy(&rr->rr.inaddr.s_addr,
00262                             rr->rdata, 4);
00263               break;
00264 #if    RFC1035_IPV6
00265        case RFC1035_TYPE_AAAA:
00266               memset(&rr->rr.in6addr, 0, sizeof(rr->rr.in6addr));
00267               if (rr->rdlength >= sizeof(struct in6_addr))
00268                      memcpy(&rr->rr.in6addr, rr->rdata,
00269                             sizeof(rr->rr.in6addr));
00270               break;
00271 #endif
00272        case RFC1035_TYPE_CNAME:
00273        case RFC1035_TYPE_MB:
00274        case RFC1035_TYPE_MG:
00275        case RFC1035_TYPE_MR:
00276        case RFC1035_TYPE_MD:
00277        case RFC1035_TYPE_MF:
00278        case RFC1035_TYPE_NS:
00279        case RFC1035_TYPE_PTR:
00280               rr->rr.domainname=p=rr->rdata;
00281               if (rfc1035_replyuncompress(&p, r, 0) == 0 ||
00282                      p > rr->rdata + rr->rdlength)
00283                      rr->rr.domainname=error;
00284               break;
00285 
00286        case RFC1035_TYPE_SOA:
00287               rr->rr.soa.mname_label=p=rr->rdata;
00288 
00289               if (rr->rdlength < 20 ||
00290                      rfc1035_replyuncompress(&p, r, 0) == 0 ||
00291                             p > rr->rdata + rr->rdlength ||
00292                      (rr->rr.soa.rname_label=p, rfc1035_replyuncompress(&p,
00293                             r, 0)) == 0 ||
00294                             p > rr->rdata + rr->rdlength - 20)
00295               {
00296                      rr->rr.soa.mname_label=error;
00297                      rr->rr.soa.rname_label=error;
00298                      rr->rr.soa.serial=0;
00299                      rr->rr.soa.refresh=0;
00300                      rr->rr.soa.retry=0;
00301                      rr->rr.soa.expire=0;
00302                      rr->rr.soa.minimum=0;
00303               }
00304               else
00305               {
00306                      rr->rr.soa.serial=
00307                             ((RFC1035_UINT32)(unsigned char)p[0] << 24) |
00308                             ((RFC1035_UINT32)(unsigned char)p[1] << 16) |
00309                             ((RFC1035_UINT32)(unsigned char)p[2] << 8) |
00310                             (unsigned char)p[3];
00311                      p += 4;
00312                      rr->rr.soa.refresh=
00313                             ((RFC1035_UINT32)(unsigned char)p[0] << 24) |
00314                             ((RFC1035_UINT32)(unsigned char)p[1] << 16) |
00315                             ((RFC1035_UINT32)(unsigned char)p[2] << 8) |
00316                             (unsigned char)p[3];
00317                      p += 4;
00318                      rr->rr.soa.retry=
00319                             ((RFC1035_UINT32)(unsigned char)p[0] << 24) |
00320                             ((RFC1035_UINT32)(unsigned char)p[1] << 16) |
00321                             ((RFC1035_UINT32)(unsigned char)p[2] << 8) |
00322                             (unsigned char)p[3];
00323                      p += 4;
00324                      rr->rr.soa.expire=
00325                             ((RFC1035_UINT32)(unsigned char)p[0] << 24) |
00326                             ((RFC1035_UINT32)(unsigned char)p[1] << 16) |
00327                             ((RFC1035_UINT32)(unsigned char)p[2] << 8) |
00328                             (unsigned char)p[3];
00329                      p += 4;
00330                      rr->rr.soa.minimum=
00331                             ((RFC1035_UINT32)(unsigned char)p[0] << 24) |
00332                             ((RFC1035_UINT32)(unsigned char)p[1] << 16) |
00333                             ((RFC1035_UINT32)(unsigned char)p[2] << 8) |
00334                             (unsigned char)p[3];
00335               }
00336               break;
00337        case RFC1035_TYPE_MX:
00338               p=rr->rdata;
00339               if (rr->rdlength < 2)
00340               {
00341                      rr->rr.mx.preference=0;
00342                      rr->rr.mx.mx_label=error;
00343               }
00344               else
00345               {
00346                      rr->rr.mx.preference=
00347                             ((unsigned)(unsigned char)p[0] << 8) |
00348                             (unsigned char)p[1];
00349                      p += 2;
00350                      rr->rr.mx.mx_label=p;
00351                      if (rfc1035_replyuncompress(&p, r, 0) == 0
00352                             || p > rr->rdata + rr->rdlength)
00353                      {
00354                             rr->rr.mx.preference=0;
00355                             rr->rr.mx.mx_label=error;
00356                      }
00357               }
00358               break;
00359 
00360        case RFC1035_TYPE_HINFO:
00361               p=rr->rdata;
00362               rr->rr.hinfo.hinfo_str=error;
00363               rr->rr.hinfo.os_str=error;
00364               if (rr->rdlength && (unsigned char)*p < rr->rdlength)
00365               {
00366               const char *q=p+1+(unsigned char)*p;
00367 
00368                      if (q < rr->rdata + rr->rdlength &&
00369                             q+(unsigned char)*q < rr->rdata + rr->rdlength)
00370                      {
00371                             rr->rr.hinfo.hinfo_str=p;
00372                             rr->rr.hinfo.os_str=q;
00373                      }
00374               }
00375               break;
00376 
00377        case RFC1035_TYPE_MINFO:
00378               rr->rr.minfo.rmailbx_label=p=rr->rdata;
00379               if (rfc1035_replyuncompress(&p, r, 0) == 0 ||
00380                      p > rr->rdata + rr->rdlength ||
00381                      (rr->rr.minfo.emailbx_label=p,
00382                             rfc1035_replyuncompress(&p, r, 0)) == 0 ||
00383                             p > rr->rdata + rr->rdlength)
00384               {
00385                      rr->rr.minfo.rmailbx_label=error;
00386                      rr->rr.minfo.emailbx_label=error;
00387               }
00388               break;
00389        case RFC1035_TYPE_RRSIG:
00390 
00391               p=rr->rdata;
00392 
00393               if (rr->rdlength < 18 ||
00394 
00395                   ((rr->rr.rrsig.type_covered=
00396                     ((unsigned)(unsigned char)p[0] << 8)
00397                     | (unsigned char)p[1]),
00398 
00399                    (rr->rr.rrsig.algorithm=p[2]),
00400                    (rr->rr.rrsig.labels=p[3]),
00401                    (rr->rr.rrsig.original_ttl=
00402                     ((RFC1035_UINT32)(unsigned char)p[4] << 24) |
00403                     ((RFC1035_UINT32)(unsigned char)p[5] << 16) |
00404                     ((RFC1035_UINT32)(unsigned char)p[6] << 8) |
00405                     (unsigned char)p[7]),
00406                    (rr->rr.rrsig.signature_expiration=
00407                     ((RFC1035_UINT32)(unsigned char)p[8] << 24) |
00408                     ((RFC1035_UINT32)(unsigned char)p[9] << 16) |
00409                     ((RFC1035_UINT32)(unsigned char)p[10] << 8) |
00410                     (unsigned char)p[11]),
00411                    (rr->rr.rrsig.signature_inception=
00412                     ((RFC1035_UINT32)(unsigned char)p[12] << 24) |
00413                     ((RFC1035_UINT32)(unsigned char)p[13] << 16) |
00414                     ((RFC1035_UINT32)(unsigned char)p[14] << 8) |
00415                     (unsigned char)p[15]),
00416                    (rr->rr.rrsig.key_tag=
00417                     ((RFC1035_UINT16)(unsigned char)p[16] << 8) |
00418                     (unsigned char)p[17]),
00419                    (rr->rr.rrsig.signer_name=(p += 18)),
00420 
00421                    rfc1035_replyuncompress(&p, r, 0) == 0) ||
00422                   p > rr->rdata + rr->rdlength)
00423               {
00424                      memset(&rr->rr.rrsig, 0, sizeof(rr->rr.rrsig));
00425                      rr->rr.rrsig.signer_name=error;
00426                      break;
00427               }
00428 
00429               rr->rr.rrsig.signature=p;
00430               rr->rr.rrsig.signature_len=rr->rdata + rr->rdlength - p;
00431               break;
00432 
00433        default:
00434               break;
00435        }
00436 }
00437 
00438 /*
00439 ** Randomize order of resource records.
00440 */
00441 
00442 static void rr_random(struct rfc1035_rr *p, unsigned n)
00443 {
00444        unsigned i;
00445 
00446        for (i=0; i<n; i++)
00447        {
00448               size_t j=rand() % n;
00449 
00450               {
00451                      struct rfc1035_rr buf=p[j];
00452 
00453                      p[j]=p[i];
00454                      p[i]=buf;
00455               }
00456        }
00457 }
00458 
00459 void rfc1035_rr_rand_an(struct rfc1035_reply *rr)
00460 {
00461        rr_random(rr->anptr, rr->ancount);
00462 }
00463 
00464 void rfc1035_rr_rand_ns(struct rfc1035_reply *rr)
00465 {
00466        rr_random(rr->nsptr, rr->nscount);
00467 }
00468 
00469 void rfc1035_rr_rand_ar(struct rfc1035_reply *rr)
00470 {
00471        rr_random(rr->arptr, rr->arcount);
00472 }
00473 
00474 void rfc1035_rr_rand(struct rfc1035_reply *rr)
00475 {
00476        rfc1035_rr_rand_an(rr);
00477        rfc1035_rr_rand_ns(rr);
00478        rfc1035_rr_rand_ar(rr);
00479 }