1 /*        $NetBSD: var.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  * Compares two vars
28  */
29 static int
rewrite_var_cmp(const void * c1,const void * c2)30 rewrite_var_cmp(
31                     const void *c1,
32                     const void *c2
33 )
34 {
35           const struct rewrite_var *v1, *v2;
36 
37           v1 = ( const struct rewrite_var * )c1;
38           v2 = ( const struct rewrite_var * )c2;
39 
40           assert( v1 != NULL );
41           assert( v2 != NULL );
42           assert( v1->lv_name != NULL );
43           assert( v2->lv_name != NULL );
44 
45           return strcasecmp( v1->lv_name, v2->lv_name );
46 }
47 
48 /*
49  * Duplicate var ?
50  */
51 static int
rewrite_var_dup(void * c1,void * c2)52 rewrite_var_dup(
53                     void *c1,
54                     void *c2
55 )
56 {
57           struct rewrite_var *v1, *v2;
58 
59           v1 = ( struct rewrite_var * )c1;
60           v2 = ( struct rewrite_var * )c2;
61 
62           assert( v1 != NULL );
63           assert( v2 != NULL );
64           assert( v1->lv_name != NULL );
65           assert( v2->lv_name != NULL );
66 
67           return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 );
68 }
69 
70 /*
71  * Frees a var
72  */
73 static void
rewrite_var_free(void * v_var)74 rewrite_var_free(
75                     void *v_var
76 )
77 {
78           struct rewrite_var *var = v_var;
79           assert( var != NULL );
80 
81           assert( var->lv_name != NULL );
82           assert( var->lv_value.bv_val != NULL );
83 
84           if ( var->lv_flags & REWRITE_VAR_COPY_NAME )
85                     free( var->lv_name );
86           if ( var->lv_flags & REWRITE_VAR_COPY_VALUE )
87                     free( var->lv_value.bv_val );
88           free( var );
89 }
90 
91 /*
92  * Deletes a var tree
93  */
94 int
rewrite_var_delete(Avlnode * tree)95 rewrite_var_delete(
96                     Avlnode *tree
97 )
98 {
99           ldap_avl_free( tree, rewrite_var_free );
100           return REWRITE_SUCCESS;
101 }
102 
103 /*
104  * Finds a var
105  */
106 struct rewrite_var *
rewrite_var_find(Avlnode * tree,const char * name)107 rewrite_var_find(
108                     Avlnode *tree,
109                     const char *name
110 )
111 {
112           struct rewrite_var var;
113 
114           assert( name != NULL );
115 
116           var.lv_name = ( char * )name;
117           return ( struct rewrite_var * )ldap_avl_find( tree,
118                               ( caddr_t )&var, rewrite_var_cmp );
119 }
120 
121 int
rewrite_var_replace(struct rewrite_var * var,const char * value,int flags)122 rewrite_var_replace(
123                     struct rewrite_var *var,
124                     const char *value,
125                     int flags
126 )
127 {
128           ber_len_t len;
129 
130           assert( value != NULL );
131 
132           len = strlen( value );
133 
134           if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
135                     if ( flags & REWRITE_VAR_COPY_VALUE ) {
136                               if ( len <= var->lv_value.bv_len ) {
137                                         AC_MEMCPY(var->lv_value.bv_val, value, len + 1);
138 
139                               } else {
140                                         free( var->lv_value.bv_val );
141                                         var->lv_value.bv_val = strdup( value );
142                               }
143 
144                     } else {
145                               free( var->lv_value.bv_val );
146                               var->lv_value.bv_val = (char *)value;
147                               var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
148                     }
149 
150           } else {
151                     if ( flags & REWRITE_VAR_COPY_VALUE ) {
152                               var->lv_value.bv_val = strdup( value );
153                               var->lv_flags |= REWRITE_VAR_COPY_VALUE;
154 
155                     } else {
156                               var->lv_value.bv_val = (char *)value;
157                     }
158           }
159 
160           if ( var->lv_value.bv_val == NULL ) {
161                     return -1;
162           }
163 
164           var->lv_value.bv_len = len;
165 
166           return 0;
167 }
168 
169 /*
170  * Inserts a newly created var
171  */
172 struct rewrite_var *
rewrite_var_insert_f(Avlnode ** tree,const char * name,const char * value,int flags)173 rewrite_var_insert_f(
174                     Avlnode **tree,
175                     const char *name,
176                     const char *value,
177                     int flags
178 )
179 {
180           struct rewrite_var *var;
181           int rc = 0;
182 
183           assert( tree != NULL );
184           assert( name != NULL );
185           assert( value != NULL );
186 
187           var = rewrite_var_find( *tree, name );
188           if ( var != NULL ) {
189                     if ( flags & REWRITE_VAR_UPDATE ) {
190                               (void)rewrite_var_replace( var, value, flags );
191                               goto cleanup;
192                     }
193                     rc = -1;
194                     goto cleanup;
195           }
196 
197           var = calloc( sizeof( struct rewrite_var ), 1 );
198           if ( var == NULL ) {
199                     return NULL;
200           }
201 
202           memset( var, 0, sizeof( struct rewrite_var ) );
203 
204           if ( flags & REWRITE_VAR_COPY_NAME ) {
205                     var->lv_name = strdup( name );
206                     if ( var->lv_name == NULL ) {
207                               rc = -1;
208                               goto cleanup;
209                     }
210                     var->lv_flags |= REWRITE_VAR_COPY_NAME;
211 
212           } else {
213                     var->lv_name = (char *)name;
214           }
215 
216           if ( flags & REWRITE_VAR_COPY_VALUE ) {
217                     var->lv_value.bv_val = strdup( value );
218                     if ( var->lv_value.bv_val == NULL ) {
219                               rc = -1;
220                               goto cleanup;
221                     }
222                     var->lv_flags |= REWRITE_VAR_COPY_VALUE;
223 
224           } else {
225                     var->lv_value.bv_val = (char *)value;
226           }
227           var->lv_value.bv_len = strlen( value );
228           rc = ldap_avl_insert( tree, ( caddr_t )var,
229                               rewrite_var_cmp, rewrite_var_dup );
230 
231 cleanup:;
232           if ( rc != 0 && var ) {
233                     ldap_avl_delete( tree, ( caddr_t )var, rewrite_var_cmp );
234                     rewrite_var_free( var );
235                     var = NULL;
236           }
237 
238           return var;
239 }
240 
241 /*
242  * Sets/inserts a var
243  */
244 struct rewrite_var *
rewrite_var_set_f(Avlnode ** tree,const char * name,const char * value,int flags)245 rewrite_var_set_f(
246                     Avlnode **tree,
247                     const char *name,
248                     const char *value,
249                     int flags
250 )
251 {
252           struct rewrite_var *var;
253 
254           assert( tree != NULL );
255           assert( name != NULL );
256           assert( value != NULL );
257 
258           var = rewrite_var_find( *tree, name );
259           if ( var == NULL ) {
260                     if ( flags & REWRITE_VAR_INSERT ) {
261                               return rewrite_var_insert_f( tree, name, value, flags );
262 
263                     } else {
264                               return NULL;
265                     }
266 
267           } else {
268                     assert( var->lv_value.bv_val != NULL );
269 
270                     (void)rewrite_var_replace( var, value, flags );
271           }
272 
273           return var;
274 }
275 
276