home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / libldap / dnssrv.c < prev    next >
C/C++ Source or Header  |  2000-09-15  |  6KB  |  307 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/libldap/dnssrv.c,v 1.12.2.2 2000/09/15 00:54:28 bcollins Exp $ */
  2. /*
  3.  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
  4.  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  5.  */
  6.  
  7. /*
  8.  * locate LDAP servers using DNS SRV records.
  9.  * Location code based on MIT Kerberos KDC location code.
  10.  */
  11. #include "portable.h"
  12.  
  13. #include <stdio.h>
  14.  
  15. #include <ac/stdlib.h>
  16.  
  17. #include <ac/param.h>
  18. #include <ac/socket.h>
  19. #include <ac/string.h>
  20. #include <ac/time.h>
  21.  
  22. #include "ldap-int.h"
  23.  
  24. #ifdef HAVE_ARPA_NAMESER_H
  25. #include <arpa/nameser.h>
  26. #endif
  27. #ifdef HAVE_RESOLV_H
  28. #include <resolv.h>
  29. #endif
  30.  
  31. /* Sometimes this is not defined. */
  32. #ifndef T_SRV
  33. #define T_SRV            33
  34. #endif                /* T_SRV */
  35.  
  36. int ldap_dn2domain(
  37.     LDAP_CONST char *dn_in,
  38.     char **domainp)
  39. {
  40.     int i;
  41.     char *domain = NULL;
  42.     char **dn;
  43.  
  44.     if( dn_in == NULL || domainp == NULL ) {
  45.         return -1;
  46.     }
  47.  
  48.     dn = ldap_explode_dn( dn_in, 0 );
  49.  
  50.     if( dn == NULL ) {
  51.         return -2;
  52.     }
  53.  
  54.     for( i=0; dn[i] != NULL; i++ ) {
  55.         char ** rdn = ldap_explode_rdn( dn[i], 0 );
  56.  
  57.         if( rdn == NULL || *rdn == NULL ) {
  58.             LDAP_FREE( rdn );
  59.             LDAP_FREE( domain );
  60.             LDAP_VFREE( dn );
  61.             return -3;
  62.         }
  63.  
  64.  
  65.         if( rdn[1] == NULL ) {
  66.             /*
  67.              * single-valued RDN
  68.              */
  69.             char *dc;
  70.  
  71. #define LDAP_DC "dc="
  72. #define LDAP_DCOID "0.9.2342.19200300.100.1.25="
  73.  
  74.             if( strncasecmp( rdn[0],
  75.                 LDAP_DC, sizeof(LDAP_DC)-1 ) == 0 )
  76.             {
  77.                 dc = &rdn[0][sizeof(LDAP_DC)-1];
  78.  
  79.             } else if( strncmp( rdn[0],
  80.                 LDAP_DCOID, sizeof(LDAP_DCOID)-1 ) == 0 )
  81.             {
  82.                 dc = &rdn[0][sizeof(LDAP_DCOID)-1];
  83.  
  84.             } else {
  85.                 dc = NULL;
  86.             }
  87.  
  88.             if( dc != NULL ) {
  89.                 char *ndomain;
  90.  
  91.                 if( *dc == '\0' ) {
  92.                     /* dc value is empty! */
  93.                     LDAP_FREE( rdn );
  94.                     LDAP_FREE( domain );
  95.                     LDAP_VFREE( dn );
  96.                     LDAP_VFREE( rdn );
  97.                     return -4;
  98.                 }
  99.  
  100.                 ndomain = LDAP_REALLOC( domain,
  101.                     ( domain == NULL ? 0 : strlen(domain) )
  102.                     + strlen(dc) + sizeof(".") );
  103.  
  104.                 if( ndomain == NULL ) {
  105.                     LDAP_FREE( rdn );
  106.                     LDAP_FREE( domain );
  107.                     LDAP_VFREE( dn );
  108.                     LDAP_VFREE( rdn );
  109.                     return -5;
  110.                 }
  111.  
  112.                 if( domain == NULL ) {
  113.                     ndomain[0] = '\0';
  114.                 } else {
  115.                     strcat( ndomain, "." );
  116.                 }
  117.  
  118.                 strcat( ndomain, dc );
  119.  
  120.                 domain = ndomain;
  121.                 continue;
  122.             }
  123.         }
  124.  
  125.         /*
  126.          * multi-valued RDN or fall thru
  127.          */
  128.  
  129.         LDAP_VFREE( rdn );
  130.         LDAP_FREE( domain );
  131.         domain = NULL;
  132.     } 
  133.  
  134.     if( domain != NULL &&  *domain == '\0' ) {
  135.         LDAP_FREE( domain );
  136.         domain = NULL;
  137.     }
  138.  
  139.     *domainp = domain;
  140.     return 0;
  141. }
  142.  
  143. int ldap_domain2dn(
  144.     LDAP_CONST char *domain_in,
  145.     char **dnp)
  146. {
  147.     char *domain, *s, *tok_r, *dn;
  148.     size_t loc;
  149.  
  150.     if (domain_in == NULL || dnp == NULL) {
  151.     return LDAP_NO_MEMORY;
  152.     }
  153.     domain = LDAP_STRDUP(domain_in);
  154.     if (domain == NULL) {
  155.     return LDAP_NO_MEMORY;
  156.     }
  157.     dn = NULL;
  158.     loc = 0;
  159.  
  160.     for (s = ldap_pvt_strtok(domain, ".", &tok_r);
  161.      s != NULL;
  162.      s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
  163.     size_t len = strlen(s);
  164.  
  165.     dn = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
  166.     if (dn == NULL) {
  167.         LDAP_FREE(domain);
  168.         return LDAP_NO_MEMORY;
  169.     }
  170.     if (loc > 0) {
  171.         /* not first time. */
  172.         strcpy(dn + loc, ",");
  173.         loc++;
  174.     }
  175.     strcpy(dn + loc, "dc=");
  176.     loc += sizeof("dc=")-1;
  177.  
  178.     strcpy(dn + loc, s);
  179.     loc += len;
  180.     }
  181.  
  182.     LDAP_FREE(domain);
  183.  
  184.     *dnp = dn;
  185.  
  186.     return LDAP_SUCCESS;
  187. }
  188.  
  189. /*
  190.  * Lookup and return LDAP servers for domain (using the DNS
  191.  * SRV record _ldap._tcp.domain).
  192.  */
  193. int ldap_domain2hostlist(
  194.     LDAP_CONST char *domain,
  195.     char **list )
  196. {
  197. #ifdef HAVE_RES_QUERY
  198.     char *request;
  199.     char *hostlist = NULL;
  200.     int rc, len, cur = 0;
  201.     unsigned char reply[1024];
  202.  
  203.     if( domain == NULL || *domain == '\0' ) {
  204.         return LDAP_PARAM_ERROR;
  205.     }
  206.  
  207.     if( list == NULL ) {
  208.         return LDAP_PARAM_ERROR;
  209.     }
  210.  
  211.     request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
  212.     if (request == NULL) {
  213.     rc = LDAP_NO_MEMORY;
  214.     goto out;
  215.     }
  216.     sprintf(request, "_ldap._tcp.%s", domain);
  217.  
  218. #ifdef LDAP_R_COMPILE
  219.     ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
  220. #endif
  221.  
  222.     rc = LDAP_UNAVAILABLE;
  223.     len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
  224.     if (len >= 0) {
  225.     unsigned char *p;
  226.     char host[1024];
  227.     int status;
  228.     u_short port;
  229.     /* int priority, weight; */
  230.  
  231.     /* Parse out query */
  232.     p = reply;
  233.     p += sizeof(HEADER);
  234.     status = dn_expand(reply, reply + len, p, host, sizeof(host));
  235.     if (status < 0) {
  236.         goto out;
  237.     }
  238.     p += status;
  239.     p += 4;
  240.  
  241.     while (p < reply + len) {
  242.         int type, class, ttl, size;
  243.         status = dn_expand(reply, reply + len, p, host, sizeof(host));
  244.         if (status < 0) {
  245.         goto out;
  246.         }
  247.         p += status;
  248.         type = (p[0] << 8) | p[1];
  249.         p += 2;
  250.         class = (p[0] << 8) | p[1];
  251.         p += 2;
  252.         ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
  253.         p += 4;
  254.         size = (p[0] << 8) | p[1];
  255.         p += 2;
  256.         if (type == T_SRV) {
  257.         int buflen;
  258.         status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
  259.         if (status < 0) {
  260.             goto out;
  261.         }
  262.         /* ignore priority and weight for now */
  263.         /* priority = (p[0] << 8) | p[1]; */
  264.         /* weight = (p[2] << 8) | p[3]; */
  265.         port = (p[4] << 8) | p[5];
  266.  
  267.         buflen = strlen(host) + sizeof(":65355");
  268.         hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
  269.         if (hostlist == NULL) {
  270.             rc = LDAP_NO_MEMORY;
  271.             goto out;
  272.         }
  273.         if (cur > 0) {
  274.             /* not first time around */
  275.             hostlist[cur++] = ' ';
  276.         }
  277.         cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
  278.         }
  279.         p += size;
  280.     }
  281.     }
  282.     if (hostlist == NULL) {
  283.     /* No LDAP servers found in DNS. */
  284.     rc = LDAP_UNAVAILABLE;
  285.     goto out;
  286.     }
  287.  
  288.     rc = LDAP_SUCCESS;
  289.     *list = hostlist;
  290.  
  291.   out:
  292. #ifdef LDAP_R_COMPILE
  293.     ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
  294. #endif
  295.  
  296.     if (request != NULL) {
  297.     LDAP_FREE(request);
  298.     }
  299.     if (rc != LDAP_SUCCESS && hostlist != NULL) {
  300.     LDAP_FREE(hostlist);
  301.     }
  302.     return rc;
  303. #else
  304.     return LDAP_NOT_SUPPORTED;
  305. #endif /* HAVE_RES_QUERY */
  306. }
  307.