xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-asyncmeta/map.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: map.c,v 1.2 2021/08/14 16:14:59 christos Exp $	*/
2 
3 /* map.c - ldap backend mapping routines */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2016-2021 The OpenLDAP Foundation.
8  * Portions Copyright 2016 Symas Corporation.
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 
20 /* ACKNOWLEDGEMENTS:
21  * This work was developed by Symas Corporation
22  * based on back-meta module for inclusion in OpenLDAP Software.
23  * This work was sponsored by Ericsson. */
24 
25 /* This is an altered version */
26 /*
27  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
28  *
29  * Permission is granted to anyone to use this software for any purpose
30  * on any computer system, and to alter it and redistribute it, subject
31  * to the following restrictions:
32  *
33  * 1. The author is not responsible for the consequences of use of this
34  *    software, no matter how awful, even if they arise from flaws in it.
35  *
36  * 2. The origin of this software must not be misrepresented, either by
37  *    explicit claim or by omission.  Since few users ever read sources,
38  *    credits should appear in the documentation.
39  *
40  * 3. Altered versions must be plainly marked as such, and must not be
41  *    misrepresented as being the original software.  Since few users
42  *    ever read sources, credits should appear in the documentation.
43  *
44  * 4. This notice may not be removed or altered.
45  *
46  *
47  *
48  * Copyright 2016, Symas Corporation
49  *
50  * This is based on the back-meta/map.c version by Pierangelo Masarati.
51  * The previously reported conditions apply to the modified code as well.
52  * Changes in the original code are highlighted where required.
53  * Credits for the original code go to the author, Howard Chu.
54  */
55 
56 #include <sys/cdefs.h>
57 __RCSID("$NetBSD: map.c,v 1.2 2021/08/14 16:14:59 christos Exp $");
58 
59 #include "portable.h"
60 
61 #include <stdio.h>
62 
63 #include <ac/string.h>
64 #include <ac/socket.h>
65 
66 #include "slap.h"
67 #include "lutil.h"
68 #include "../back-ldap/back-ldap.h"
69 #include "back-asyncmeta.h"
70 
71 void
asyncmeta_referral_result_rewrite(a_dncookie * dc,BerVarray a_vals)72 asyncmeta_referral_result_rewrite(
73 	a_dncookie		*dc,
74 	BerVarray		a_vals
75 )
76 {
77 	int		i, last;
78 
79 	assert( dc != NULL );
80 	assert( a_vals != NULL );
81 
82 	for ( last = 0; !BER_BVISNULL( &a_vals[ last ] ); last++ )
83 		;
84 	last--;
85 
86 	for ( i = 0; !BER_BVISNULL( &a_vals[ i ] ); i++ ) {
87 		struct berval	dn,
88 				olddn = BER_BVNULL;
89 		int		rc;
90 		LDAPURLDesc	*ludp;
91 
92 		rc = ldap_url_parse( a_vals[ i ].bv_val, &ludp );
93 		if ( rc != LDAP_URL_SUCCESS ) {
94 			/* leave attr untouched if massage failed */
95 			continue;
96 		}
97 
98 		/* FIXME: URLs like "ldap:///dc=suffix" if passed
99 		 * thru ldap_url_parse() and ldap_url_desc2str()
100 		 * get rewritten as "ldap:///dc=suffix??base";
101 		 * we don't want this to occur... */
102 		if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
103 			ludp->lud_scope = LDAP_SCOPE_DEFAULT;
104 		}
105 
106 		ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
107 
108 		asyncmeta_dn_massage( dc, &olddn, &dn );
109 		/* leave attr untouched if massage did nothing */
110 		if ( olddn.bv_val != dn.bv_val )
111 		{
112 			char	*newurl;
113 
114 			ludp->lud_dn = dn.bv_val;
115 			newurl = ldap_url_desc2str( ludp );
116 			dc->op->o_tmpfree( dn.bv_val, dc->memctx );
117 			if ( newurl )
118 			{
119 				/* FIXME: leave attr untouched
120 				 * even if ldap_url_desc2str failed...
121 				 */
122 
123 				ber_memfree_x( a_vals[ i ].bv_val, dc->op->o_tmpmemctx );
124 				ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], dc->memctx );
125 				ber_memfree( newurl );
126 				ludp->lud_dn = olddn.bv_val;
127 			}
128 		}
129 		ldap_free_urldesc( ludp );
130 	}
131 }
132 
133 void
asyncmeta_dnattr_result_rewrite(a_dncookie * dc,BerVarray a_vals)134 asyncmeta_dnattr_result_rewrite(
135 	a_dncookie		*dc,
136 	BerVarray		a_vals
137 )
138 {
139 	struct berval	bv;
140 	int		i;
141 
142 	assert( a_vals != NULL );
143 
144 	for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
145 		asyncmeta_dn_massage( dc, &a_vals[i], &bv );
146 		if ( bv.bv_val != a_vals[i].bv_val ) {
147 			ber_memfree_x( a_vals[i].bv_val, dc->memctx );
148 			a_vals[i] = bv;
149 		}
150 	}
151 }
152 
153 /*
154  * asyncmeta_dn_massage
155  *
156  * Aliases the suffix.
157  */
158 void
asyncmeta_dn_massage(a_dncookie * dc,struct berval * odn,struct berval * res)159 asyncmeta_dn_massage(
160 	a_dncookie *dc,
161 	struct berval *odn,
162 	struct berval *res
163 )
164 {
165 	struct berval pretty = {0,NULL}, *dn = odn;
166 	struct berval *osuff, *nsuff;
167 	int diff;
168 
169 	assert( res );
170 
171 	BER_BVZERO(res);
172 	if ( dn == NULL )
173 		return;
174 
175 	/* no suffix massage configured */
176 	if ( !dc->target->mt_lsuffixm.bv_val ) {
177 		*res = *dn;
178 		return;
179 	}
180 
181 	if ( dc->to_from == MASSAGE_REQ ) {
182 		osuff = &dc->target->mt_lsuffixm;
183 		nsuff = &dc->target->mt_rsuffixm;
184 	} else {
185 		osuff = &dc->target->mt_rsuffixm;
186 		nsuff = &dc->target->mt_lsuffixm;
187 		/* DN from remote server may be in arbitrary form.
188 		 * Pretty it so we can parse reliably.
189 		 */
190 		dnPretty( NULL, dn, &pretty, dc->op->o_tmpmemctx );
191 		if (pretty.bv_val) dn = &pretty;
192 	}
193 
194 	diff = dn->bv_len - osuff->bv_len;
195 	/* DN is shorter than suffix - ignore */
196 	if ( diff < 0 ) {
197 ignore:
198 		*res = *odn;
199 		if (pretty.bv_val)
200 			dc->op->o_tmpfree( pretty.bv_val, dc->op->o_tmpmemctx );
201 		return;
202 	}
203 
204 	/* DN longer than our suffix and doesn't match */
205 	if ( diff > 0 && !DN_SEPARATOR(dn->bv_val[diff-1]))
206 		goto ignore;
207 
208 	/* suffix is same length as ours, but doesn't match */
209 	if ( strcasecmp( osuff->bv_val, &dn->bv_val[diff] ))
210 		goto ignore;
211 
212 	res->bv_len = diff + nsuff->bv_len;
213 	res->bv_val = dc->op->o_tmpalloc( res->bv_len + 1, dc->memctx );
214 	strncpy( res->bv_val, dn->bv_val, diff );
215 	strcpy( &res->bv_val[diff], nsuff->bv_val );
216 
217 	if (pretty.bv_val)
218 		dc->op->o_tmpfree( pretty.bv_val, dc->op->o_tmpmemctx );
219 }
220