~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to libraries/libldap/dnssrv.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $OpenLDAP: pkg/ldap/libraries/libldap/dnssrv.c,v 1.39.2.4 2008/02/11 23:26:41 kurt Exp $ */
 
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
3
 *
 
4
 * Copyright 1998-2008 The OpenLDAP Foundation.
 
5
 * All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted only as authorized by the OpenLDAP
 
9
 * Public License.
 
10
 *
 
11
 * A copy of this license is available in the file LICENSE in the
 
12
 * top-level directory of the distribution or, alternatively, at
 
13
 * <http://www.OpenLDAP.org/license.html>.
 
14
 */
 
15
 
 
16
/*
 
17
 * locate LDAP servers using DNS SRV records.
 
18
 * Location code based on MIT Kerberos KDC location code.
 
19
 */
 
20
#include "portable.h"
 
21
 
 
22
#include <stdio.h>
 
23
 
 
24
#include <ac/stdlib.h>
 
25
 
 
26
#include <ac/param.h>
 
27
#include <ac/socket.h>
 
28
#include <ac/string.h>
 
29
#include <ac/time.h>
 
30
 
 
31
#include "ldap-int.h"
 
32
 
 
33
#ifdef HAVE_ARPA_NAMESER_H
 
34
#include <arpa/nameser.h>
 
35
#endif
 
36
#ifdef HAVE_RESOLV_H
 
37
#include <resolv.h>
 
38
#endif
 
39
 
 
40
int ldap_dn2domain(
 
41
        LDAP_CONST char *dn_in,
 
42
        char **domainp)
 
43
{
 
44
        int i, j;
 
45
        char *ndomain;
 
46
        LDAPDN dn = NULL;
 
47
        LDAPRDN rdn = NULL;
 
48
        LDAPAVA *ava = NULL;
 
49
        struct berval domain = BER_BVNULL;
 
50
        static const struct berval DC = BER_BVC("DC");
 
51
        static const struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25");
 
52
 
 
53
        assert( dn_in != NULL );
 
54
        assert( domainp != NULL );
 
55
 
 
56
        *domainp = NULL;
 
57
 
 
58
        if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) {
 
59
                return -2;
 
60
        }
 
61
 
 
62
        if( dn ) for( i=0; dn[i] != NULL; i++ ) {
 
63
                rdn = dn[i];
 
64
 
 
65
                for( j=0; rdn[j] != NULL; j++ ) {
 
66
                        ava = rdn[j];
 
67
 
 
68
                        if( rdn[j+1] == NULL &&
 
69
                                (ava->la_flags & LDAP_AVA_STRING) &&
 
70
                                ava->la_value.bv_len &&
 
71
                                ( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0
 
72
                                || ber_bvcmp( &ava->la_attr, &DCOID ) == 0 ) )
 
73
                        {
 
74
                                if( domain.bv_len == 0 ) {
 
75
                                        ndomain = LDAP_REALLOC( domain.bv_val,
 
76
                                                ava->la_value.bv_len + 1);
 
77
 
 
78
                                        if( ndomain == NULL ) {
 
79
                                                goto return_error;
 
80
                                        }
 
81
 
 
82
                                        domain.bv_val = ndomain;
 
83
 
 
84
                                        AC_MEMCPY( domain.bv_val, ava->la_value.bv_val,
 
85
                                                ava->la_value.bv_len );
 
86
 
 
87
                                        domain.bv_len = ava->la_value.bv_len;
 
88
                                        domain.bv_val[domain.bv_len] = '\0';
 
89
 
 
90
                                } else {
 
91
                                        ndomain = LDAP_REALLOC( domain.bv_val,
 
92
                                                ava->la_value.bv_len + sizeof(".") + domain.bv_len );
 
93
 
 
94
                                        if( ndomain == NULL ) {
 
95
                                                goto return_error;
 
96
                                        }
 
97
 
 
98
                                        domain.bv_val = ndomain;
 
99
                                        domain.bv_val[domain.bv_len++] = '.';
 
100
                                        AC_MEMCPY( &domain.bv_val[domain.bv_len],
 
101
                                                ava->la_value.bv_val, ava->la_value.bv_len );
 
102
                                        domain.bv_len += ava->la_value.bv_len;
 
103
                                        domain.bv_val[domain.bv_len] = '\0';
 
104
                                }
 
105
                        } else {
 
106
                                domain.bv_len = 0;
 
107
                        }
 
108
                } 
 
109
        }
 
110
 
 
111
 
 
112
        if( domain.bv_len == 0 && domain.bv_val != NULL ) {
 
113
                LDAP_FREE( domain.bv_val );
 
114
                domain.bv_val = NULL;
 
115
        }
 
116
 
 
117
        ldap_dnfree( dn );
 
118
        *domainp = domain.bv_val;
 
119
        return 0;
 
120
 
 
121
return_error:
 
122
        ldap_dnfree( dn );
 
123
        LDAP_FREE( domain.bv_val );
 
124
        return -1;
 
125
}
 
126
 
 
127
int ldap_domain2dn(
 
128
        LDAP_CONST char *domain_in,
 
129
        char **dnp)
 
130
{
 
131
        char *domain, *s, *tok_r, *dn, *dntmp;
 
132
        size_t loc;
 
133
 
 
134
        assert( domain_in != NULL );
 
135
        assert( dnp != NULL );
 
136
 
 
137
        domain = LDAP_STRDUP(domain_in);
 
138
        if (domain == NULL) {
 
139
                return LDAP_NO_MEMORY;
 
140
        }
 
141
        dn = NULL;
 
142
        loc = 0;
 
143
 
 
144
        for (s = ldap_pvt_strtok(domain, ".", &tok_r);
 
145
                s != NULL;
 
146
                s = ldap_pvt_strtok(NULL, ".", &tok_r))
 
147
        {
 
148
                size_t len = strlen(s);
 
149
 
 
150
                dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
 
151
                if (dntmp == NULL) {
 
152
                    if (dn != NULL)
 
153
                        LDAP_FREE(dn);
 
154
                    LDAP_FREE(domain);
 
155
                    return LDAP_NO_MEMORY;
 
156
                }
 
157
 
 
158
                dn = dntmp;
 
159
 
 
160
                if (loc > 0) {
 
161
                    /* not first time. */
 
162
                    strcpy(dn + loc, ",");
 
163
                    loc++;
 
164
                }
 
165
                strcpy(dn + loc, "dc=");
 
166
                loc += sizeof("dc=")-1;
 
167
 
 
168
                strcpy(dn + loc, s);
 
169
                loc += len;
 
170
    }
 
171
 
 
172
        LDAP_FREE(domain);
 
173
        *dnp = dn;
 
174
        return LDAP_SUCCESS;
 
175
}
 
176
 
 
177
/*
 
178
 * Lookup and return LDAP servers for domain (using the DNS
 
179
 * SRV record _ldap._tcp.domain).
 
180
 */
 
181
int ldap_domain2hostlist(
 
182
        LDAP_CONST char *domain,
 
183
        char **list )
 
184
{
 
185
#ifdef HAVE_RES_QUERY
 
186
#define DNSBUFSIZ (64*1024)
 
187
    char *request;
 
188
    char *hostlist = NULL;
 
189
    int rc, len, cur = 0;
 
190
    unsigned char reply[DNSBUFSIZ];
 
191
 
 
192
        assert( domain != NULL );
 
193
        assert( list != NULL );
 
194
 
 
195
        if( *domain == '\0' ) {
 
196
                return LDAP_PARAM_ERROR;
 
197
        }
 
198
 
 
199
    request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
 
200
    if (request == NULL) {
 
201
                return LDAP_NO_MEMORY;
 
202
    }
 
203
    sprintf(request, "_ldap._tcp.%s", domain);
 
204
 
 
205
#ifdef LDAP_R_COMPILE
 
206
    ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
 
207
#endif
 
208
 
 
209
    rc = LDAP_UNAVAILABLE;
 
210
#ifdef NS_HFIXEDSZ
 
211
        /* Bind 8/9 interface */
 
212
    len = res_query(request, ns_c_in, ns_t_srv, reply, sizeof(reply));
 
213
#       ifndef T_SRV
 
214
#               define T_SRV ns_t_srv
 
215
#       endif
 
216
#else
 
217
        /* Bind 4 interface */
 
218
#       ifndef T_SRV
 
219
#               define T_SRV 33
 
220
#       endif
 
221
 
 
222
    len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
 
223
#endif
 
224
    if (len >= 0) {
 
225
        unsigned char *p;
 
226
        char host[DNSBUFSIZ];
 
227
        int status;
 
228
        u_short port;
 
229
        /* int priority, weight; */
 
230
 
 
231
        /* Parse out query */
 
232
        p = reply;
 
233
 
 
234
#ifdef NS_HFIXEDSZ
 
235
        /* Bind 8/9 interface */
 
236
        p += NS_HFIXEDSZ;
 
237
#elif defined(HFIXEDSZ)
 
238
        /* Bind 4 interface w/ HFIXEDSZ */
 
239
        p += HFIXEDSZ;
 
240
#else
 
241
        /* Bind 4 interface w/o HFIXEDSZ */
 
242
        p += sizeof(HEADER);
 
243
#endif
 
244
 
 
245
        status = dn_expand(reply, reply + len, p, host, sizeof(host));
 
246
        if (status < 0) {
 
247
            goto out;
 
248
        }
 
249
        p += status;
 
250
        p += 4;
 
251
 
 
252
        while (p < reply + len) {
 
253
            int type, class, ttl, size;
 
254
            status = dn_expand(reply, reply + len, p, host, sizeof(host));
 
255
            if (status < 0) {
 
256
                goto out;
 
257
            }
 
258
            p += status;
 
259
            type = (p[0] << 8) | p[1];
 
260
            p += 2;
 
261
            class = (p[0] << 8) | p[1];
 
262
            p += 2;
 
263
            ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
 
264
            p += 4;
 
265
            size = (p[0] << 8) | p[1];
 
266
            p += 2;
 
267
            if (type == T_SRV) {
 
268
                int buflen;
 
269
                status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
 
270
                if (status < 0) {
 
271
                    goto out;
 
272
                }
 
273
                /* ignore priority and weight for now */
 
274
                /* priority = (p[0] << 8) | p[1]; */
 
275
                /* weight = (p[2] << 8) | p[3]; */
 
276
                port = (p[4] << 8) | p[5];
 
277
 
 
278
                if ( port == 0 || host[ 0 ] == '\0' ) {
 
279
                    goto add_size;
 
280
                }
 
281
 
 
282
                buflen = strlen(host) + STRLENOF(":65355 ");
 
283
                hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen + 1);
 
284
                if (hostlist == NULL) {
 
285
                    rc = LDAP_NO_MEMORY;
 
286
                    goto out;
 
287
                }
 
288
                if (cur > 0) {
 
289
                    /* not first time around */
 
290
                    hostlist[cur++] = ' ';
 
291
                }
 
292
                cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
 
293
            }
 
294
add_size:;
 
295
            p += size;
 
296
        }
 
297
    }
 
298
    if (hostlist == NULL) {
 
299
        /* No LDAP servers found in DNS. */
 
300
        rc = LDAP_UNAVAILABLE;
 
301
        goto out;
 
302
    }
 
303
 
 
304
    rc = LDAP_SUCCESS;
 
305
        *list = hostlist;
 
306
 
 
307
  out:
 
308
#ifdef LDAP_R_COMPILE
 
309
    ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
 
310
#endif
 
311
 
 
312
    if (request != NULL) {
 
313
        LDAP_FREE(request);
 
314
    }
 
315
    if (rc != LDAP_SUCCESS && hostlist != NULL) {
 
316
        LDAP_FREE(hostlist);
 
317
    }
 
318
    return rc;
 
319
#else
 
320
    return LDAP_NOT_SUPPORTED;
 
321
#endif /* HAVE_RES_QUERY */
 
322
}