1 /*	$NetBSD: referral.c,v 1.1.1.3 2010/12/12 15:23:01 adam Exp $	*/
2 
3 /* referral.c - DNS SRV backend referral handler */
4 /* OpenLDAP: pkg/ldap/servers/slapd/back-dnssrv/referral.c,v 1.26.2.6 2010/04/13 20:23:27 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2000-2010 The OpenLDAP Foundation.
8  * Portions Copyright 2000-2003 Kurt D. Zeilenga.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was originally developed by Kurt D. Zeilenga for inclusion
21  * in OpenLDAP Software.
22  */
23 
24 #include "portable.h"
25 
26 #include <stdio.h>
27 
28 #include <ac/string.h>
29 #include <ac/socket.h>
30 
31 #include "slap.h"
32 #include "proto-dnssrv.h"
33 
34 int
35 dnssrv_back_referrals(
36     Operation	*op,
37     SlapReply	*rs )
38 {
39 	int i;
40 	int rc = LDAP_OTHER;
41 	char *domain = NULL;
42 	char *hostlist = NULL;
43 	char **hosts = NULL;
44 	BerVarray urls = NULL;
45 
46 	if ( BER_BVISEMPTY( &op->o_req_dn ) ) {
47 		/* FIXME: need some means to determine whether the database
48 		 * is a glue instance */
49 		if ( SLAP_GLUE_INSTANCE( op->o_bd ) ) {
50 			return LDAP_SUCCESS;
51 		}
52 
53 		rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed";
54 		return LDAP_UNWILLING_TO_PERFORM;
55 	}
56 
57 	if( get_manageDSAit( op ) ) {
58 		if( op->o_tag == LDAP_REQ_SEARCH ) {
59 			return LDAP_SUCCESS;
60 		}
61 
62 		rs->sr_text = "DNS SRV problem processing manageDSAit control";
63 		return LDAP_OTHER;
64 	}
65 
66 	if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) {
67 		rs->sr_err = LDAP_REFERRAL;
68 		rs->sr_ref = default_referral;
69 		send_ldap_result( op, rs );
70 		rs->sr_ref = NULL;
71 		return LDAP_REFERRAL;
72 	}
73 
74 	Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n",
75 		op->o_req_dn.bv_val, domain, 0 );
76 
77 	i = ldap_domain2hostlist( domain, &hostlist );
78 	if ( i ) {
79 		Debug( LDAP_DEBUG_TRACE,
80 			"DNSSRV: domain2hostlist(%s) returned %d\n",
81 			domain, i, 0 );
82 		rs->sr_text = "no DNS SRV RR available for DN";
83 		rc = LDAP_NO_SUCH_OBJECT;
84 		goto done;
85 	}
86 
87 	hosts = ldap_str2charray( hostlist, " " );
88 
89 	if( hosts == NULL ) {
90 		Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 );
91 		rs->sr_text = "problem processing DNS SRV records for DN";
92 		goto done;
93 	}
94 
95 	for( i=0; hosts[i] != NULL; i++) {
96 		struct berval url;
97 
98 		url.bv_len = STRLENOF( "ldap://" ) + strlen( hosts[i] );
99 		url.bv_val = ch_malloc( url.bv_len + 1 );
100 
101 		strcpy( url.bv_val, "ldap://" );
102 		strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] );
103 
104 		if ( ber_bvarray_add( &urls, &url ) < 0 ) {
105 			free( url.bv_val );
106 			rs->sr_text = "problem processing DNS SRV records for DN";
107 			goto done;
108 		}
109 	}
110 
111 	Statslog( LDAP_DEBUG_STATS,
112 	    "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n",
113 	    op->o_log_prefix, op->o_protocol,
114 		op->o_req_dn.bv_val, urls[0].bv_val, 0 );
115 
116 	Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> url=\"%s\"\n",
117 		op->o_req_dn.bv_val, urls[0].bv_val, 0 );
118 
119 	rs->sr_ref = urls;
120 	send_ldap_error( op, rs, LDAP_REFERRAL,
121 		"DNS SRV generated referrals" );
122 	rs->sr_ref = NULL;
123 	rc = LDAP_REFERRAL;
124 
125 done:
126 	if( domain != NULL ) ch_free( domain );
127 	if( hostlist != NULL ) ch_free( hostlist );
128 	if( hosts != NULL ) ldap_charray_free( hosts );
129 	ber_bvarray_free( urls );
130 	return rc;
131 }
132