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