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