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
71void
72asyncmeta_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
133void
134asyncmeta_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 */
158void
159asyncmeta_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 ) {
197ignore:
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