1 /* $NetBSD: escapemap.c,v 1.2 2025/09/05 21:16:23 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 2000-2024 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* ACKNOWLEDGEMENT: 18 * This work was initially developed by Ondej Kuznk for inclusion in OpenLDAP 19 * Software. 20 */ 21 22 #include <portable.h> 23 24 #define LDAP_DEPRECATED 1 25 #include "rewrite-int.h" 26 #include "rewrite-map.h" 27 28 #include <ldap_pvt.h> 29 30 typedef int (escape_fn)( struct berval *input, struct berval *output ); 31 32 /* 33 * Map configuration, a NULL-terminated list of escape_fn pointers 34 */ 35 struct escape_map_data { 36 escape_fn **fn; 37 }; 38 39 /* 40 * (un)escape functions 41 */ 42 43 static int 44 map_escape_to_filter( struct berval *input, struct berval *output ) 45 { 46 return ldap_bv2escaped_filter_value( input, output ); 47 } 48 49 static int 50 map_unescape_filter( struct berval *input, struct berval *output ) 51 { 52 ber_slen_t len; 53 54 if ( ber_dupbv( output, input ) == NULL ) { 55 return REWRITE_ERR; 56 } 57 58 len = ldap_pvt_filter_value_unescape( output->bv_val ); 59 if ( len < 0 ) { 60 ber_memfree( output->bv_val ); 61 return REWRITE_ERR; 62 } 63 output->bv_len = len; 64 65 return LDAP_SUCCESS; 66 } 67 68 static int 69 map_escape_to_dn( struct berval *input, struct berval *output ) 70 { 71 LDAPAVA ava = { .la_attr = BER_BVC("uid"), 72 .la_value = *input, 73 .la_flags = LDAP_AVA_STRING }, 74 *ava_[] = { &ava, NULL }; 75 LDAPRDN rdn[] = { ava_, NULL }; 76 LDAPDN dn = rdn; 77 struct berval dnstr; 78 char *p; 79 int rc; 80 81 rc = ldap_dn2bv( dn, &dnstr, LDAP_DN_FORMAT_LDAPV3 ); 82 if ( rc != LDAP_SUCCESS ) { 83 return REWRITE_ERR; 84 } 85 86 p = strchr( dnstr.bv_val, '=' ); 87 p++; 88 89 output->bv_len = dnstr.bv_len - ( p - dnstr.bv_val ); 90 output->bv_val = malloc( output->bv_len + 1 ); 91 if ( output->bv_val == NULL ) { 92 free( dnstr.bv_val ); 93 return REWRITE_ERR; 94 } 95 memcpy( output->bv_val, p, output->bv_len ); 96 output->bv_val[output->bv_len] = '\0'; 97 98 free( dnstr.bv_val ); 99 return REWRITE_SUCCESS; 100 } 101 102 static int 103 map_unescape_dn( struct berval *input, struct berval *output ) 104 { 105 LDAPDN dn; 106 struct berval fake_dn; 107 char *p; 108 int rc = REWRITE_SUCCESS; 109 110 fake_dn.bv_len = STRLENOF("uid=") + input->bv_len; 111 fake_dn.bv_val = p = malloc( fake_dn.bv_len + 1 ); 112 if ( p == NULL ) { 113 return REWRITE_ERR; 114 } 115 116 memcpy( p, "uid=", STRLENOF("uid=") ); 117 p += STRLENOF("uid="); 118 memcpy( p, input->bv_val, input->bv_len ); 119 fake_dn.bv_val[fake_dn.bv_len] = '\0'; 120 121 if ( ldap_bv2dn( &fake_dn, &dn, LDAP_DN_FORMAT_LDAPV3 ) != LDAP_SUCCESS ) { 122 free( fake_dn.bv_val ); 123 return REWRITE_ERR; 124 } 125 if ( ber_dupbv( output, &dn[0][0]->la_value ) == NULL ) { 126 rc = REWRITE_ERR; 127 } 128 ldap_dnfree( dn ); 129 free( fake_dn.bv_val ); 130 return rc; 131 } 132 133 /* Registered callbacks */ 134 135 static void * 136 map_escape_parse( 137 const char *fname, 138 int lineno, 139 int argc, 140 char **argv 141 ) 142 { 143 escape_fn **fns; 144 int i; 145 146 assert( fname != NULL ); 147 assert( argv != NULL ); 148 149 if ( argc < 1 ) { 150 Debug( LDAP_DEBUG_ANY, 151 "[%s:%d] escape map needs at least one operation\n", 152 fname, lineno ); 153 return NULL; 154 } 155 156 fns = calloc( sizeof(escape_fn *), argc + 1 ); 157 if ( fns == NULL ) { 158 return NULL; 159 } 160 161 for ( i = 0; i < argc; i++ ) { 162 if ( strcasecmp( argv[i], "escape2dn" ) == 0 ) { 163 fns[i] = map_escape_to_dn; 164 } else if ( strcasecmp( argv[i], "escape2filter" ) == 0 ) { 165 fns[i] = map_escape_to_filter; 166 } else if ( strcasecmp( argv[i], "unescapedn" ) == 0 ) { 167 fns[i] = map_unescape_dn; 168 } else if ( strcasecmp( argv[i], "unescapefilter" ) == 0 ) { 169 fns[i] = map_unescape_filter; 170 } else { 171 Debug( LDAP_DEBUG_ANY, 172 "[%s:%d] unknown option %s (ignored)\n", 173 fname, lineno, argv[i] ); 174 free( fns ); 175 return NULL; 176 } 177 } 178 179 return (void *)fns; 180 } 181 182 static int 183 map_escape_apply( 184 void *private, 185 const char *input, 186 struct berval *output ) 187 { 188 escape_fn **fns = private; 189 struct berval tmpin, tmpout = BER_BVNULL; 190 int i; 191 192 assert( private != NULL ); 193 assert( input != NULL ); 194 assert( output != NULL ); 195 196 ber_str2bv( input, 0, 1, &tmpin ); 197 198 for ( i=0; fns[i]; i++ ) { 199 int rc = fns[i]( &tmpin, &tmpout ); 200 free( tmpin.bv_val ); 201 if ( rc != REWRITE_SUCCESS ) { 202 return rc; 203 } 204 tmpin = tmpout; 205 BER_BVZERO( &tmpout ); 206 } 207 *output = tmpin; 208 209 return REWRITE_SUCCESS; 210 } 211 212 static int 213 map_escape_destroy( 214 void *private 215 ) 216 { 217 struct ldap_map_data *data = private; 218 219 assert( private != NULL ); 220 free( data ); 221 222 return 0; 223 } 224 225 const rewrite_mapper rewrite_escape_mapper = { 226 "escape", 227 map_escape_parse, 228 map_escape_apply, 229 map_escape_destroy 230 }; 231