1 /* $NetBSD: info.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2000-2021 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 Pierangelo Masarati for
19 * inclusion in OpenLDAP Software.
20 */
21
22 #include <portable.h>
23
24 #include "rewrite-int.h"
25
26 /*
27 * Global data
28 */
29
30 /*
31 * This becomes the running context for subsequent calls to
32 * rewrite_parse; it can be altered only by a
33 * rewriteContext config line or by a change in info.
34 */
35 struct rewrite_context *rewrite_int_curr_context = NULL;
36
37 /*
38 * Inits the info
39 */
40 struct rewrite_info *
rewrite_info_init(int mode)41 rewrite_info_init(
42 int mode
43 )
44 {
45 struct rewrite_info *info;
46 struct rewrite_context *context;
47
48 switch ( mode ) {
49 case REWRITE_MODE_ERR:
50 case REWRITE_MODE_OK:
51 case REWRITE_MODE_COPY_INPUT:
52 case REWRITE_MODE_USE_DEFAULT:
53 break;
54 default:
55 mode = REWRITE_MODE_USE_DEFAULT;
56 break;
57 /* return NULL */
58 }
59
60 /*
61 * Resets the running context for parsing ...
62 */
63 rewrite_int_curr_context = NULL;
64
65 info = calloc( sizeof( struct rewrite_info ), 1 );
66 if ( info == NULL ) {
67 return NULL;
68 }
69
70 info->li_state = REWRITE_DEFAULT;
71 info->li_max_passes = REWRITE_MAX_PASSES;
72 info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
73 info->li_rewrite_mode = mode;
74
75 /*
76 * Add the default (empty) rule
77 */
78 context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
79 if ( context == NULL ) {
80 free( info );
81 return NULL;
82 }
83
84 #ifdef USE_REWRITE_LDAP_PVT_THREADS
85 if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
86 ldap_avl_free( info->li_context, rewrite_context_free );
87 free( info );
88 return NULL;
89 }
90 if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
91 ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
92 ldap_avl_free( info->li_context, rewrite_context_free );
93 free( info );
94 return NULL;
95 }
96 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
97
98 return info;
99 }
100
101 /*
102 * Cleans up the info structure
103 */
104 int
rewrite_info_delete(struct rewrite_info ** pinfo)105 rewrite_info_delete(
106 struct rewrite_info **pinfo
107 )
108 {
109 struct rewrite_info *info;
110
111 assert( pinfo != NULL );
112 assert( *pinfo != NULL );
113
114 info = *pinfo;
115
116 if ( info->li_context ) {
117 ldap_avl_free( info->li_context, rewrite_context_free );
118 }
119 info->li_context = NULL;
120
121 if ( info->li_maps ) {
122 ldap_avl_free( info->li_maps, rewrite_builtin_map_free );
123 }
124 info->li_maps = NULL;
125
126 rewrite_session_destroy( info );
127
128 #ifdef USE_REWRITE_LDAP_PVT_THREADS
129 ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
130 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
131
132 rewrite_param_destroy( info );
133
134 #ifdef USE_REWRITE_LDAP_PVT_THREADS
135 ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
136 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
137
138 free( info );
139 *pinfo = NULL;
140
141 return REWRITE_SUCCESS;
142 }
143
144 /*
145 * Rewrites a string according to context.
146 * If the engine is off, OK is returned, but the return string will be NULL.
147 * In case of 'unwilling to perform', UNWILLING is returned, and the
148 * return string will also be null. The same in case of error.
149 * Otherwise, OK is returned, and result will hold a newly allocated string
150 * with the rewriting.
151 *
152 * What to do in case of non-existing rewrite context is still an issue.
153 * Four possibilities:
154 * - error,
155 * - ok with NULL result,
156 * - ok with copy of string as result,
157 * - use the default rewrite context.
158 */
159 int
rewrite(struct rewrite_info * info,const char * rewriteContext,const char * string,char ** result)160 rewrite(
161 struct rewrite_info *info,
162 const char *rewriteContext,
163 const char *string,
164 char **result
165 )
166 {
167 return rewrite_session( info, rewriteContext,
168 string, NULL, result );
169 }
170
171 int
rewrite_session(struct rewrite_info * info,const char * rewriteContext,const char * string,const void * cookie,char ** result)172 rewrite_session(
173 struct rewrite_info *info,
174 const char *rewriteContext,
175 const char *string,
176 const void *cookie,
177 char **result
178 )
179 {
180 struct rewrite_context *context;
181 struct rewrite_op op = { 0, 0, NULL, NULL, NULL };
182 int rc;
183
184 assert( info != NULL );
185 assert( rewriteContext != NULL );
186 assert( string != NULL );
187 assert( result != NULL );
188
189 /*
190 * cookie can be null; means: don't care about session stuff
191 */
192
193 *result = NULL;
194 op.lo_cookie = cookie;
195
196 /*
197 * Engine not on means no failure, but explicit no rewriting
198 */
199 if ( info->li_state != REWRITE_ON ) {
200 rc = REWRITE_REGEXEC_OK;
201 goto rc_return;
202 }
203
204 /*
205 * Undefined context means no rewriting also
206 * (conservative, are we sure it's what we want?)
207 */
208 context = rewrite_context_find( info, rewriteContext );
209 if ( context == NULL ) {
210 switch ( info->li_rewrite_mode ) {
211 case REWRITE_MODE_ERR:
212 rc = REWRITE_REGEXEC_ERR;
213 goto rc_return;
214
215 case REWRITE_MODE_OK:
216 rc = REWRITE_REGEXEC_OK;
217 goto rc_return;
218
219 case REWRITE_MODE_COPY_INPUT:
220 *result = strdup( string );
221 rc = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR;
222 goto rc_return;
223
224 case REWRITE_MODE_USE_DEFAULT:
225 context = rewrite_context_find( info,
226 REWRITE_DEFAULT_CONTEXT );
227 break;
228 }
229 }
230
231 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
232 op.lo_string = strdup( string );
233 if ( op.lo_string == NULL ) {
234 rc = REWRITE_REGEXEC_ERR;
235 goto rc_return;
236 }
237 #endif
238
239 /*
240 * Applies rewrite context
241 */
242 rc = rewrite_context_apply( info, &op, context, string, result );
243 assert( op.lo_depth == 0 );
244
245 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
246 free( op.lo_string );
247 #endif
248
249 switch ( rc ) {
250 /*
251 * Success
252 */
253 case REWRITE_REGEXEC_OK:
254 case REWRITE_REGEXEC_STOP:
255 /*
256 * If rewrite succeeded return OK regardless of how
257 * the successful rewriting was obtained!
258 */
259 rc = REWRITE_REGEXEC_OK;
260 break;
261
262
263 /*
264 * Internal or forced error, return = NULL; rc already OK.
265 */
266 case REWRITE_REGEXEC_UNWILLING:
267 case REWRITE_REGEXEC_ERR:
268 if ( *result != NULL ) {
269 if ( *result != string ) {
270 free( *result );
271 }
272 *result = NULL;
273 }
274
275 default:
276 break;
277 }
278
279 rc_return:;
280 if ( op.lo_vars ) {
281 rewrite_var_delete( op.lo_vars );
282 }
283
284 return rc;
285 }
286
287