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