]> git.sur5r.net Git - openldap/blob - servers/slapd/limits.c
check for update dn
[openldap] / servers / slapd / limits.c
1 /* limits.c - routines to handle regex-based size and time limits */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/regex.h>
12 #include <ac/string.h>
13
14 #include "slap.h"
15
16 int
17 get_limits( 
18         Backend                 *be, 
19         const char              *ndn, 
20         struct slap_limits_set  **limit
21 )
22 {
23         struct slap_limits **lm;
24
25         assert( be );
26         assert( limit );
27
28         /*
29          * default values
30          */
31         *limit = &be->be_def_limit;
32
33         /*
34          * anonymous or no regex-based limits? 
35          */
36         if ( be->be_limits == NULL || ndn == NULL || ndn[0] == '\0' ) {
37                 return( 0 );
38         }
39
40         for ( lm = be->be_limits; lm[0] != NULL; lm++ ) {
41                 switch ( lm[0]->lm_type) {
42                 case SLAP_LIMITS_EXACT:
43                         if ( strcmp( lm[0]->lm_dn_pat, ndn ) == 0 ) {
44                                 *limit = &lm[0]->lm_limits;
45                                 return( 0 );
46                         }
47                         break;
48
49                 case SLAP_LIMITS_REGEX:
50                         if ( regexec( &lm[0]->lm_dn_regex, ndn, 0, NULL, 0 ) == 0 ) {
51                                 *limit = &lm[0]->lm_limits;
52                                 return( 0 );
53                         }
54                         break;
55                         
56                 default:
57                         assert( 0 );    /* unreachable */
58                         return( -1 );
59                 }
60         }
61
62         return( 0 );
63 }
64
65 int
66 add_limits(
67         Backend                 *be,
68         int                     type,
69         const char              *pattern,
70         struct slap_limits_set  *limit
71 )
72 {
73         int                     i;
74         struct slap_limits      *lm;
75         
76         assert( be );
77         assert( pattern );
78         assert( limit );
79
80         lm = ( struct slap_limits * )ch_calloc( sizeof( struct slap_limits ), 1 );
81
82         switch ( type ) {
83         case SLAP_LIMITS_EXACT:
84                 lm->lm_type = SLAP_LIMITS_EXACT;
85                 lm->lm_dn_pat = ch_strdup( pattern );
86                 if ( dn_normalize( lm->lm_dn_pat ) == NULL ) {
87                         ch_free( lm->lm_dn_pat );
88                         ch_free( lm );
89                         return( -1 );
90                 }
91                 break;
92                 
93         case SLAP_LIMITS_REGEX:
94         case SLAP_LIMITS_UNDEFINED:
95                 lm->lm_type = SLAP_LIMITS_REGEX;
96                 lm->lm_dn_pat = ch_strdup( pattern );
97                 if ( regcomp( &lm->lm_dn_regex, lm->lm_dn_pat, REG_EXTENDED | REG_ICASE ) ) {
98                         ch_free( lm->lm_dn_pat );
99                         ch_free( lm );
100                         return( -1 );
101                 }
102                 break;
103         }
104
105         lm->lm_limits = *limit;
106
107         i = 0;
108         if ( be->be_limits != NULL ) {
109                 for ( ; be->be_limits[i]; i++ );
110         }
111
112         be->be_limits = ( struct slap_limits ** )ch_realloc( be->be_limits,
113                         sizeof( struct slap_limits * ) * ( i + 2 ) );
114         be->be_limits[i] = lm;
115         be->be_limits[i+1] = NULL;
116         
117         return( 0 );
118 }
119
120 int
121 parse_limits(
122         Backend     *be,
123         const char  *fname,
124         int         lineno,
125         int         argc,
126         char        **argv
127 )
128 {
129         int     type = SLAP_LIMITS_UNDEFINED;
130         char    *pattern;
131         struct slap_limits_set limit;
132         int     i;
133
134         assert( be );
135
136         if ( argc < 3 ) {
137 #ifdef NEW_LOGGING
138                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
139                         "%s : line %d: missing arg(s) in "
140                         "\"limits <pattern> <limits>\" line.\n",
141                         fname, lineno ));
142 #else
143                 Debug( LDAP_DEBUG_ANY,
144                         "%s : line %d: missing arg(s) in "
145                         "\"limits <pattern> <limits>\" line.\n%s",
146                         fname, lineno, "" );
147 #endif
148                 return( -1 );
149         }
150
151         limit = be->be_def_limit;
152
153         /*
154          * syntax:
155          *
156          * "limits" <pattern> <limit> [ ... ]
157          * 
158          * 
159          * <pattern>:
160          * 
161          * [ "dn" [ "." { "exact" | "regex" } ] "=" ] <dn pattern>
162          *
163          * 
164          * <limit>:
165          *
166          * "time" [ "." { "soft" | "hard" } ] "=" <integer>
167          *
168          * "size" [ "." { "soft" | "hard" | "unchecked" } ] "=" <integer>
169          */
170         
171         pattern = argv[1];
172         if ( strncasecmp( pattern, "dn", 2 ) == 0 ) {
173                 pattern += 2;
174                 if ( pattern[0] == '.' ) {
175                         pattern++;
176                         if ( strncasecmp( pattern, "exact", 5 ) == 0 ) {
177                                 type = SLAP_LIMITS_EXACT;
178                                 pattern += 5;
179                         } else if ( strncasecmp( pattern, "regex", 5 ) == 0 ) {
180                                 type = SLAP_LIMITS_REGEX;
181                                 pattern += 5;
182                         }
183                 }
184
185                 if ( pattern[0] != '=' ) {
186 #ifdef NEW_LOGGING
187                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
188                                 "%s : line %d: missing '=' in "
189                                 "\"dn[.{exact|regex}]=<pattern>\" in "
190                                 "\"limits <pattern> <limits>\" line.\n",
191                         fname, lineno ));
192 #else
193                         Debug( LDAP_DEBUG_ANY,
194                                 "%s : line %d: missing '=' in "
195                                 "\"dn[.{exact|regex}]=<pattern>\" in "
196                                 "\"limits <pattern> <limits>\" line.\n%s",
197                         fname, lineno, "" );
198 #endif
199                         return( -1 );
200                 }
201
202                 /* skip '=' (required) */
203                 pattern++;
204         }
205
206         for ( i = 2; i < argc; i++ ) {
207                 if ( parse_limit( argv[i], &limit ) ) {
208
209 #ifdef NEW_LOGGING
210                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
211                                 "%s : line %d: unknown limit type \"%s\" in "
212                                 "\"limits <pattern> <limits>\" line.\n",
213                         fname, lineno, argv[i] ));
214 #else
215                         Debug( LDAP_DEBUG_ANY,
216                                 "%s : line %d: unknown limit type \"%s\" in "
217                                 "\"limits <pattern> <limits>\" line.\n",
218                         fname, lineno, argv[i] );
219 #endif
220
221                         return( 1 );
222                 }
223         }
224
225         /*
226          * sanity checks ...
227          */
228         if ( limit.lms_t_hard > 0 && limit.lms_t_hard < limit.lms_t_soft ) {
229                 limit.lms_t_hard = limit.lms_t_soft;
230         }
231         
232         if ( limit.lms_s_hard > 0 && limit.lms_s_hard < limit.lms_s_soft ) {
233                 limit.lms_s_hard = limit.lms_s_soft;
234         }
235         
236         return( add_limits( be, type, pattern, &limit ) );
237 }
238
239 int
240 parse_limit(
241         const char              *arg,
242         struct slap_limits_set  *limit
243 )
244 {
245         assert( arg );
246         assert( limit );
247
248         if ( strncasecmp( arg, "time", 4 ) == 0 ) {
249                 arg += 4;
250
251                 if ( arg[0] == '.' ) {
252                         arg++;
253                         if ( strncasecmp( arg, "soft", 4 ) == 0 ) {
254                                 arg += 4;
255                                 if ( arg[0] != '=' ) {
256                                         return( 1 );
257                                 }
258                                 arg++;
259                                 limit->lms_t_soft = atoi( arg );
260                                 
261                         } else if ( strncasecmp( arg, "hard", 4 ) == 0 ) {
262                                 arg += 4;
263                                 if ( arg[0] != '=' ) {
264                                         return( 1 );
265                                 }
266                                 arg++;
267                                 if ( strcasecmp( arg, "soft" ) == 0 ) {
268                                         limit->lms_t_hard = 0;
269                                 } else if ( strcasecmp( arg, "none" ) == 0 ) {
270                                         limit->lms_t_hard = -1;
271                                 } else {
272                                         limit->lms_t_hard = atoi( arg );
273                                 }
274                                 
275                         } else {
276                                 return( 1 );
277                         }
278                         
279                 } else if ( arg[0] == '=' ) {
280                         limit->lms_t_soft = atoi( arg );
281                         limit->lms_t_hard = 0;
282                         
283                 } else {
284                         return( 1 );
285                 }
286
287         } else if ( strncasecmp( arg, "size", 4 ) == 0 ) {
288                 arg += 4;
289                 
290                 if ( arg[0] == '.' ) {
291                         arg++;
292                         if ( strncasecmp( arg, "soft", 4 ) == 0 ) {
293                                 arg += 4;
294                                 if ( arg[0] != '=' ) {
295                                         return( 1 );
296                                 }
297                                 arg++;
298                                 limit->lms_s_soft = atoi( arg );
299                                 
300                         } else if ( strncasecmp( arg, "hard", 4 ) == 0 ) {
301                                 arg += 4;
302                                 if ( arg[0] != '=' ) {
303                                         return( 1 );
304                                 }
305                                 arg++;
306                                 if ( strcasecmp( arg, "soft" ) == 0 ) {
307                                         limit->lms_s_hard = 0;
308                                 } else if ( strcasecmp( arg, "none" ) == 0 ) {
309                                         limit->lms_s_hard = -1;
310                                 } else {
311                                         limit->lms_s_hard = atoi( arg );
312                                 }
313                                 
314                         } else if ( strncasecmp( arg, "unchecked", 9 ) == 0 ) {
315                                 arg += 9;
316                                 if ( arg[0] != '=' ) {
317                                         return( 1 );
318                                 }
319                                 arg++;
320                                 if ( strcasecmp( arg, "none" ) == 0 ) {
321                                         limit->lms_s_unchecked = -1;
322                                 } else {
323                                         limit->lms_s_unchecked = atoi( arg );
324                                 }
325                                 
326                         } else {
327                                 return( 1 );
328                         }
329                         
330                 } else if ( arg[0] == '=' ) {
331                         limit->lms_s_soft = atoi( arg );
332                         limit->lms_s_hard = 0;
333                         
334                 } else {
335                         return( 1 );
336                 }
337         }
338
339         return 0;
340 }
341