]> git.sur5r.net Git - openldap/blob - libraries/libldap/dnssrv.c
Fix up NT port after thread changes
[openldap] / libraries / libldap / dnssrv.c
1 /* $OpenLDAP$ */
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 *dn;
200     char *hostlist = NULL;
201     int rc, len, cur = 0;
202     unsigned char reply[1024];
203
204         if( domain == NULL || *domain == '\0' ) {
205                 return LDAP_PARAM_ERROR;
206         }
207
208         if( list == NULL ) {
209                 return LDAP_PARAM_ERROR;
210         }
211
212     request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
213     if (request == NULL) {
214         rc = LDAP_NO_MEMORY;
215         goto out;
216     }
217     sprintf(request, "_ldap._tcp.%s", domain);
218
219 #ifdef LDAP_R_COMPILE
220     ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
221 #endif
222
223     rc = LDAP_UNAVAILABLE;
224     len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
225     if (len >= 0) {
226         unsigned char *p;
227         char host[1024];
228         int status;
229         u_short port;
230         /* int priority, weight; */
231
232         /* Parse out query */
233         p = reply;
234         p += sizeof(HEADER);
235         status = dn_expand(reply, reply + len, p, host, sizeof(host));
236         if (status < 0) {
237             goto out;
238         }
239         p += status;
240         p += 4;
241
242         while (p < reply + len) {
243             int type, class, ttl, size;
244             status = dn_expand(reply, reply + len, p, host, sizeof(host));
245             if (status < 0) {
246                 goto out;
247             }
248             p += status;
249             type = (p[0] << 8) | p[1];
250             p += 2;
251             class = (p[0] << 8) | p[1];
252             p += 2;
253             ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
254             p += 4;
255             size = (p[0] << 8) | p[1];
256             p += 2;
257             if (type == T_SRV) {
258                 int buflen;
259                 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
260                 if (status < 0) {
261                     goto out;
262                 }
263                 /* ignore priority and weight for now */
264                 /* priority = (p[0] << 8) | p[1]; */
265                 /* weight = (p[2] << 8) | p[3]; */
266                 port = (p[4] << 8) | p[5];
267
268                 buflen = strlen(host) + sizeof(":65355");
269                 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
270                 if (hostlist == NULL) {
271                     rc = LDAP_NO_MEMORY;
272                     goto out;
273                 }
274                 if (cur > 0) {
275                     /* not first time around */
276                     hostlist[cur++] = ' ';
277                 }
278                 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
279             }
280             p += size;
281         }
282     }
283     if (hostlist == NULL) {
284         /* No LDAP servers found in DNS. */
285         rc = LDAP_UNAVAILABLE;
286         goto out;
287     }
288
289     rc = LDAP_SUCCESS;
290         *list = hostlist;
291
292   out:
293 #ifdef LDAP_R_COMPILE
294     ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
295 #endif
296
297     if (request != NULL) {
298         LDAP_FREE(request);
299     }
300     if (rc != LDAP_SUCCESS && hostlist != NULL) {
301         LDAP_FREE(hostlist);
302     }
303     return rc;
304 #else
305     return LDAP_NOT_SUPPORTED;
306 #endif /* HAVE_RES_QUERY */
307 }