]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/external_acl/kerberos_ldap_group/support_resolv.cc
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 * -----------------------------------------------------------------------------
12 * Author: Markus Moeller (markus_moeller at compuserve.com)
14 * Copyright (C) 2007 Markus Moeller. All rights reserved.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
30 * -----------------------------------------------------------------------------
44 #include <netinet/in.h>
49 #if HAVE_ARPA_NAMESER_H
50 #include <arpa/nameser.h>
53 void nsError(int nserror
, char *server
);
54 static int compare_hosts(struct hstruct
*h1
, struct hstruct
*h2
);
55 static void swap(struct hstruct
*a
, struct hstruct
*b
);
56 static void sort(struct hstruct
*array
, int nitems
, int (*cmp
) (struct hstruct
*, struct hstruct
*), int begin
, int end
);
57 static void msort(struct hstruct
*array
, size_t nitems
, int (*cmp
) (struct hstruct
*, struct hstruct
*));
60 * See http://www.ietf.org/rfc/rfc1035.txt
63 * See http://www.ietf.org/rfc/rfc2782.txt
67 nsError(int nserror
, char *service
)
71 error((char *) "%s| %s: ERROR: res_search: Unknown service record: %s\n", LogTime(), PROGRAM
, service
);
74 error((char *) "%s| %s: ERROR: res_search: No SRV record for %s\n", LogTime(), PROGRAM
, service
);
77 error((char *) "%s| %s: ERROR: res_search: No response for SRV query\n", LogTime(), PROGRAM
);
80 error((char *) "%s| %s: ERROR: res_search: Unexpected error: %s\n", LogTime(), PROGRAM
, strerror(nserror
));
85 swap(struct hstruct
*a
, struct hstruct
*b
)
90 c
.priority
= a
->priority
;
93 a
->priority
= b
->priority
;
94 a
->weight
= b
->weight
;
96 b
->priority
= c
.priority
;
101 sort(struct hstruct
*array
, int nitems
, int (*cmp
) (struct hstruct
*, struct hstruct
*), int begin
, int end
)
108 if (cmp(&array
[l
], &array
[pivot
]) <= 0) {
112 swap(&array
[l
], &array
[r
]);
116 swap(&array
[begin
], &array
[l
]);
117 sort(array
, nitems
, cmp
, begin
, l
);
118 sort(array
, nitems
, cmp
, r
, end
);
123 msort(struct hstruct
*array
, size_t nitems
, int (*cmp
) (struct hstruct
*, struct hstruct
*))
125 sort(array
, (int)nitems
, cmp
, 0, (int)(nitems
- 1));
129 compare_hosts(struct hstruct
*host1
, struct hstruct
*host2
)
133 * The comparison function must return an integer less than, equal to,
134 * or greater than zero if the first argument is considered to be
135 * respectively less than, equal to, or greater than the second.
137 if ((host1
->priority
< host2
->priority
) && (host1
->priority
!= -1))
139 if ((host1
->priority
< host2
->priority
) && (host1
->priority
== -1))
141 if ((host1
->priority
> host2
->priority
) && (host2
->priority
!= -1))
143 if ((host1
->priority
> host2
->priority
) && (host2
->priority
== -1))
145 if (host1
->priority
== host2
->priority
) {
146 if (host1
->weight
> host2
->weight
)
148 if (host1
->weight
< host2
->weight
)
155 free_hostname_list(struct hstruct
**hlist
, size_t nhosts
)
157 struct hstruct
*hp
= NULL
;
161 for (i
= 0; i
< nhosts
; ++i
) {
171 get_hostname_list(struct hstruct
**hlist
, size_t nhosts
, char *name
)
173 struct addrinfo
*hres
= NULL
, *hres_list
;
175 struct hstruct
*hp
= NULL
;
181 rc
= getaddrinfo((const char *) name
, NULL
, NULL
, &hres
);
183 error((char *) "%s| %s: ERROR: Error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM
, gai_strerror(rc
));
190 hres_list
= hres_list
->ai_next
;
196 * char host[sysconf(_SC_HOST_NAME_MAX)];
199 rc
= getnameinfo(hres_list
->ai_addr
, hres_list
->ai_addrlen
, host
, sizeof(host
), NULL
, 0, 0);
201 error((char *) "%s| %s: ERROR: Error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM
, gai_strerror(rc
));
207 debug((char *) "%s| %s: DEBUG: Resolved address %d of %s to %s\n", LogTime(), PROGRAM
, count
, name
, host
);
209 hp
= (struct hstruct
*) xrealloc(hp
, sizeof(struct hstruct
) * (nhosts
+ 1));
210 hp
[nhosts
].host
= xstrdup(host
);
211 hp
[nhosts
].port
= -1;
212 hp
[nhosts
].priority
= -1;
213 hp
[nhosts
].weight
= -1;
216 hres_list
= hres_list
->ai_next
;
225 get_ldap_hostname_list(struct main_args
*margs
, struct hstruct
**hlist
, size_t nh
, char *domain
)
229 * char name[sysconf(_SC_HOST_NAME_MAX)];
232 char *service
= NULL
;
233 struct hstruct
*hp
= NULL
;
234 struct lsstruct
*ls
= NULL
;
239 u_char
*buffer
= NULL
;
244 debug((char *) "%s| %s: DEBUG: Ldap server loop: lserver@domain %s@%s\n", LogTime(), PROGRAM
, ls
->lserver
, ls
->domain
?ls
->domain
:"NULL");
245 if (ls
->domain
&& !strcasecmp(ls
->domain
, domain
)) {
246 debug((char *) "%s| %s: DEBUG: Found lserver@domain %s@%s\n", LogTime(), PROGRAM
, ls
->lserver
, ls
->domain
);
247 hp
= (struct hstruct
*) xrealloc(hp
, sizeof(struct hstruct
) * (nhosts
+ 1));
248 hp
[nhosts
].host
= xstrdup(ls
->lserver
);
249 hp
[nhosts
].port
= -1;
250 hp
[nhosts
].priority
= -2;
251 hp
[nhosts
].weight
= -2;
253 } else if ( !ls
->domain
|| !strcasecmp(ls
->domain
, "") ) {
254 debug((char *) "%s| %s: DEBUG: Found lserver@domain %s@%s\n", LogTime(), PROGRAM
, ls
->lserver
, ls
->domain
?ls
->domain
:"NULL");
255 hp
= (struct hstruct
*) xrealloc(hp
, sizeof(struct hstruct
) * (nhosts
+ 1));
256 hp
[nhosts
].host
= xstrdup(ls
->lserver
);
257 hp
[nhosts
].port
= -1;
258 hp
[nhosts
].priority
= -2;
259 hp
[nhosts
].weight
= -2;
265 /* found ldap servers in predefined list -> exit */
270 service
= (char *) xmalloc(strlen("_ldaps._tcp.") + strlen(domain
) + 1);
271 strcpy(service
, "_ldaps._tcp.");
273 service
= (char *) xmalloc(strlen("_ldap._tcp.") + strlen(domain
) + 1);
274 strcpy(service
, "_ldap._tcp.");
276 strcat(service
, domain
);
278 #ifndef PACKETSZ_MULT
280 * It seems Solaris doesn't give back the real length back when res_search uses a to small buffer
281 * Set a bigger one here
283 #define PACKETSZ_MULT 10
287 buffer
= (u_char
*) xmalloc(PACKETSZ_MULT
* NS_PACKETSZ
);
288 if ((len
= res_search(service
, ns_c_in
, ns_t_srv
, (u_char
*) buffer
, PACKETSZ_MULT
* NS_PACKETSZ
)) < 0) {
289 error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM
, service
);
290 nsError(h_errno
, service
);
293 service
= (char *) xmalloc(strlen("_ldap._tcp.") + strlen(domain
) + 1);
294 strcpy(service
, "_ldap._tcp.");
295 strcat(service
, domain
);
296 if ((len
= res_search(service
, ns_c_in
, ns_t_srv
, (u_char
*) buffer
, PACKETSZ_MULT
* NS_PACKETSZ
)) < 0) {
297 error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM
, service
);
298 nsError(h_errno
, service
);
305 if (len
> PACKETSZ_MULT
* NS_PACKETSZ
) {
307 buffer
= (u_char
*) xrealloc(buffer
, (size_t)len
);
308 if ((len
= res_search(service
, ns_c_in
, ns_t_srv
, (u_char
*) buffer
, len
)) < 0) {
309 error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM
, service
);
310 nsError(h_errno
, service
);
314 error((char *) "%s| %s: ERROR: Reply to big: buffer: %d reply length: %d\n", LogTime(), PROGRAM
, olen
, len
);
319 p
+= 6 * NS_INT16SZ
; /* Header(6*16bit) = id + flags + 4*section count */
320 if (p
> buffer
+ len
) {
321 error((char *) "%s| %s: ERROR: Message to small: %d < header size\n", LogTime(), PROGRAM
, len
);
324 if ((size
= dn_expand(buffer
, buffer
+ len
, p
, name
, sizeof(name
))) < 0) {
325 error((char *) "%s| %s: ERROR: Error while expanding query name with dn_expand: %s\n", LogTime(), PROGRAM
, strerror(errno
));
328 p
+= size
; /* Query name */
329 p
+= 2 * NS_INT16SZ
; /* Query type + class (2*16bit) */
330 if (p
> buffer
+ len
) {
331 error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class \n", LogTime(), PROGRAM
, len
);
334 while (p
< buffer
+ len
) {
336 if ((size
= dn_expand(buffer
, buffer
+ len
, p
, name
, sizeof(name
))) < 0) {
337 error((char *) "%s| %s: ERROR: Error while expanding answer name with dn_expand: %s\n", LogTime(), PROGRAM
, strerror(errno
));
340 p
+= size
; /* Resource Record name */
341 if (p
> buffer
+ len
) {
342 error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name\n", LogTime(), PROGRAM
, len
);
345 NS_GET16(type
, p
); /* RR type (16bit) */
346 p
+= NS_INT16SZ
+ NS_INT32SZ
; /* RR class + ttl (16bit+32bit) */
347 if (p
> buffer
+ len
) {
348 error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name + RR type,class,ttl\n", LogTime(), PROGRAM
, len
);
351 NS_GET16(rdlength
, p
); /* RR data length (16bit) */
353 if (type
== ns_t_srv
) { /* SRV record */
354 int priority
, weight
, port
;
355 char host
[NS_MAXDNAME
];
356 if (p
> buffer
+ len
) {
357 error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name + RR type,class,ttl + RR data length\n", LogTime(), PROGRAM
, len
);
360 NS_GET16(priority
, p
); /* Priority (16bit) */
361 if (p
> buffer
+ len
) {
362 error((char *) "%s| %s: ERROR: Message to small: %d < SRV RR + priority\n", LogTime(), PROGRAM
, len
);
365 NS_GET16(weight
, p
); /* Weight (16bit) */
366 if (p
> buffer
+ len
) {
367 error((char *) "%s| %s: ERROR: Message to small: %d < SRV RR + priority + weight\n", LogTime(), PROGRAM
, len
);
370 NS_GET16(port
, p
); /* Port (16bit) */
371 if (p
> buffer
+ len
) {
372 error((char *) "%s| %s: ERROR: Message to small: %d < SRV RR + priority + weight + port\n", LogTime(), PROGRAM
, len
);
375 if ((size
= dn_expand(buffer
, buffer
+ len
, p
, host
, NS_MAXDNAME
)) < 0) {
376 error((char *) "%s| %s: ERROR: Error while expanding SRV RR name with dn_expand: %s\n", LogTime(), PROGRAM
, strerror(errno
));
379 debug((char *) "%s| %s: DEBUG: Resolved SRV %s record to %s\n", LogTime(), PROGRAM
, service
, host
);
380 hp
= (struct hstruct
*) xrealloc(hp
, sizeof(struct hstruct
) * (nh
+ 1));
381 hp
[nh
].host
= xstrdup(host
);
383 hp
[nh
].priority
= priority
;
384 hp
[nh
].weight
= weight
;
390 if (p
> buffer
+ len
) {
391 error((char *) "%s| %s: ERROR: Message to small: %d < SRV RR + priority + weight + port + name\n", LogTime(), PROGRAM
, len
);
395 if (p
!= buffer
+ len
) {
396 #if (SIZEOF_LONG == 8)
397 error("%s| %s: ERROR: Inconsistence message length: %ld!=0\n", LogTime(), PROGRAM
, buffer
+ len
- p
);
399 error((char *) "%s| %s: ERROR: Inconsistence message length: %d!=0\n", LogTime(), PROGRAM
, buffer
+ len
- p
);
405 nhosts
= get_hostname_list(&hp
, nh
, domain
);
407 debug("%s| %s: DEBUG: Adding %s to list\n", LogTime(), PROGRAM
, domain
);
409 hp
= (struct hstruct
*) xrealloc(hp
, sizeof(struct hstruct
) * (nhosts
+ 1));
410 hp
[nhosts
].host
= xstrdup(domain
);
411 hp
[nhosts
].port
= -1;
412 hp
[nhosts
].priority
= -2;
413 hp
[nhosts
].weight
= -2;
417 /* Remove duplicates */
418 for (i
= 0; i
< nhosts
; ++i
) {
419 for (j
= i
+ 1; j
< nhosts
; ++j
) {
420 if (!strcasecmp(hp
[i
].host
, hp
[j
].host
)) {
421 if (hp
[i
].port
== hp
[j
].port
||
422 (hp
[i
].port
== -1 && hp
[j
].port
== 389) ||
423 (hp
[i
].port
== 389 && hp
[j
].port
== -1)) {
425 for (k
= j
+ 1; k
< nhosts
; ++k
) {
426 hp
[k
- 1].host
= hp
[k
].host
;
427 hp
[k
- 1].port
= hp
[k
].port
;
428 hp
[k
- 1].priority
= hp
[k
].priority
;
429 hp
[k
- 1].weight
= hp
[k
].weight
;
433 hp
= (struct hstruct
*) xrealloc(hp
, sizeof(struct hstruct
) * (nhosts
+ 1));
439 /* Sort by Priority / Weight */
440 msort(hp
, (size_t)nhosts
, compare_hosts
);
443 debug((char *) "%s| %s: DEBUG: Sorted ldap server names for domain %s:\n", LogTime(), PROGRAM
, domain
);
444 for (i
= 0; i
< nhosts
; ++i
) {
445 debug((char *) "%s| %s: DEBUG: Host: %s Port: %d Priority: %d Weight: %d\n", LogTime(), PROGRAM
, hp
[i
].host
, hp
[i
].port
, hp
[i
].priority
, hp
[i
].weight
);