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