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