]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/limits.c
ITS#5379 HAVE_TLS dependency
[openldap] / servers / slapd / limits.c
index 2c4106e79a68319da2b93774f8c5530351be3c7d..17e131e1c8c73eb4ffb2205ecf426071d4dc0f7f 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Copyright 1998-2008 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -72,8 +72,8 @@ limits_get(
 {
        struct slap_limits **lm;
 
-       assert( op );
-       assert( limit );
+       assert( op != NULL );
+       assert( limit != NULL );
 
        Debug( LDAP_DEBUG_TRACE, "==> limits_get: %s dn=\"%s\"\n",
                        op->o_log_prefix,
@@ -93,7 +93,7 @@ limits_get(
 
                switch ( style ) {
                case SLAP_LIMITS_EXACT:
-                       if ( ndn->bv_len == 0 ) {
+                       if ( BER_BVISEMPTY( ndn ) ) {
                                break;
                        }
 
@@ -130,7 +130,7 @@ limits_get(
                case SLAP_LIMITS_CHILDREN: {
                        size_t d;
                        
-                       if ( ndn->bv_len == 0 ) {
+                       if ( BER_BVISEMPTY( ndn ) ) {
                                break;
                        }
 
@@ -147,7 +147,7 @@ limits_get(
                                }
                        } else {
                                /* check for unescaped rdn separator */
-                               if ( !DN_SEPARATOR( ndn->bv_val[d-1] ) ) {
+                               if ( !DN_SEPARATOR( ndn->bv_val[d - 1] ) ) {
                                        break;
                                }
                        }
@@ -180,7 +180,7 @@ limits_get(
                }
 
                case SLAP_LIMITS_REGEX:
-                       if ( ndn->bv_len == 0 ) {
+                       if ( BER_BVISEMPTY( ndn ) ) {
                                break;
                        }
                        if ( regexec( &lm[0]->lm_regex, ndn->bv_val,
@@ -194,7 +194,7 @@ limits_get(
                        break;
 
                case SLAP_LIMITS_ANONYMOUS:
-                       if ( ndn->bv_len == 0 ) {
+                       if ( BER_BVISEMPTY( ndn ) ) {
                                Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=DN match=%s\n",
                                                limits2str( style ), 0, 0 );
                                *limit = &lm[0]->lm_limits;
@@ -203,7 +203,7 @@ limits_get(
                        break;
 
                case SLAP_LIMITS_USERS:
-                       if ( ndn->bv_len != 0 ) {
+                       if ( !BER_BVISEMPTY( ndn ) ) {
                                *limit = &lm[0]->lm_limits;
                                Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=DN match=%s\n",
                                                limits2str( style ), 0, 0 );
@@ -238,8 +238,8 @@ limits_add(
        struct slap_limits      *lm;
        unsigned                type, style;
        
-       assert( be );
-       assert( limit );
+       assert( be != NULL );
+       assert( limit != NULL );
 
        type = flags & SLAP_LIMITS_TYPE_MASK;
        style = flags & SLAP_LIMITS_MASK;
@@ -271,8 +271,8 @@ limits_add(
                {
                        int rc;
                        struct berval bv;
-                       bv.bv_val = (char *) pattern;
-                       bv.bv_len = strlen( pattern );
+
+                       ber_str2bv( pattern, 0, 0, &bv );
 
                        rc = dnNormalize( 0, NULL, NULL, &bv, &lm->lm_pat, NULL );
                        if ( rc != LDAP_SUCCESS ) {
@@ -297,15 +297,14 @@ limits_add(
        case SLAP_LIMITS_USERS:
        case SLAP_LIMITS_ANY:
                lm->lm_flags = style | type;
-               lm->lm_pat.bv_val = NULL;
-               lm->lm_pat.bv_len = 0;
+               BER_BVZERO( &lm->lm_pat );
                break;
        }
 
        switch ( type ) {
        case SLAP_LIMITS_TYPE_GROUP:
-               assert( group_oc );
-               assert( group_ad );
+               assert( group_oc != NULL );
+               assert( group_ad != NULL );
                lm->lm_group_oc = group_oc;
                lm->lm_group_ad = group_ad;
                break;
@@ -342,7 +341,7 @@ limits_parse(
        ObjectClass             *group_oc = NULL;
        AttributeDescription    *group_ad = NULL;
 
-       assert( be );
+       assert( be != NULL );
 
        if ( argc < 3 ) {
                Debug( LDAP_DEBUG_ANY,
@@ -503,7 +502,6 @@ limits_parse(
                        ad.bv_val = strchr( oc.bv_val, '/' );
                        if ( ad.bv_val != NULL ) {
                                const char      *text = NULL;
-                               int             rc;
 
                                oc.bv_len = ad.bv_val - oc.bv_val;
 
@@ -534,7 +532,6 @@ no_oc:;
 
                if ( group_ad == NULL ) {
                        const char      *text = NULL;
-                       int             rc;
                        
                        rc = slap_str2ad( SLAPD_GROUP_ATTR, &group_ad, &text );
 
@@ -637,8 +634,8 @@ limits_parse_one(
        struct slap_limits_set  *limit
 )
 {
-       assert( arg );
-       assert( limit );
+       assert( arg != NULL );
+       assert( limit != NULL );
 
        if ( strncasecmp( arg, "time", STRLENOF( "time" ) ) == 0 ) {
                arg += STRLENOF( "time" );
@@ -651,14 +648,9 @@ limits_parse_one(
                                        limit->lms_t_soft = -1;
 
                                } else {
-                                       char    *next = NULL;
-                                       int     soft = strtol( arg, &next, 10 );
-
-                                       if ( next == arg || next[ 0 ] != '\0' ) {
-                                               return( 1 );
-                                       }
+                                       int     soft;
 
-                                       if ( soft < -1 ) {
+                                       if ( lutil_atoi( &soft, arg ) != 0 || soft < -1 ) {
                                                return( 1 );
                                        }
 
@@ -678,14 +670,9 @@ limits_parse_one(
                                        limit->lms_t_hard = -1;
 
                                } else {
-                                       char    *next = NULL;
-                                       int     hard = strtol( arg, &next, 10 );
+                                       int     hard;
 
-                                       if ( next == arg || next[ 0 ] != '\0' ) {
-                                               return( 1 );
-                                       }
-
-                                       if ( hard < -1 ) {
+                                       if ( lutil_atoi( &hard, arg ) != 0 || hard < -1 ) {
                                                return( 1 );
                                        }
 
@@ -710,10 +697,9 @@ limits_parse_one(
                                limit->lms_t_soft = -1;
 
                        } else {
-                               char    *next = NULL;
-
-                               limit->lms_t_soft = strtol( arg, &next, 10 );
-                               if ( next == arg || limit->lms_t_soft < -1 ) {
+                               if ( lutil_atoi( &limit->lms_t_soft, arg ) != 0 
+                                       || limit->lms_t_soft < -1 )
+                               {
                                        return( 1 );
                                }
                        }
@@ -734,14 +720,9 @@ limits_parse_one(
                                        limit->lms_s_soft = -1;
 
                                } else {
-                                       char    *next = NULL;
-                                       int     soft = strtol( arg, &next, 10 );
-
-                                       if ( next == arg || next[ 0 ] != '\0' ) {
-                                               return( 1 );
-                                       }
+                                       int     soft;
 
-                                       if ( soft < -1 ) {
+                                       if ( lutil_atoi( &soft, arg ) != 0 || soft < -1 ) {
                                                return( 1 );
                                        }
 
@@ -761,14 +742,9 @@ limits_parse_one(
                                        limit->lms_s_hard = -1;
 
                                } else {
-                                       char    *next = NULL;
-                                       int     hard = strtol( arg, &next, 10 );
+                                       int     hard;
 
-                                       if ( next == arg || next[ 0 ] != '\0' ) {
-                                               return( 1 );
-                                       }
-
-                                       if ( hard < -1 ) {
+                                       if ( lutil_atoi( &hard, arg ) != 0 || hard < -1 ) {
                                                return( 1 );
                                        }
 
@@ -792,14 +768,9 @@ limits_parse_one(
                                        limit->lms_s_unchecked = 0;
 
                                } else {
-                                       char    *next = NULL;
-                                       int     unchecked = strtol( arg, &next, 10 );
-
-                                       if ( next == arg || next[ 0 ] != '\0' ) {
-                                               return( 1 );
-                                       }
+                                       int     unchecked;
 
-                                       if ( unchecked < -1 ) {
+                                       if ( lutil_atoi( &unchecked, arg ) != 0 || unchecked < -1 ) {
                                                return( 1 );
                                        }
 
@@ -819,14 +790,9 @@ limits_parse_one(
                                        limit->lms_s_pr = -1;
 
                                } else {
-                                       char    *next = NULL;
-                                       int     pr = strtol( arg, &next, 10 );
+                                       int     pr;
 
-                                       if ( next == arg || next[ 0 ] != '\0' ) {
-                                               return( 1 );
-                                       }
-
-                                       if ( pr < -1 ) {
+                                       if ( lutil_atoi( &pr, arg ) != 0 || pr < -1 ) {
                                                return( 1 );
                                        }
 
@@ -850,15 +816,9 @@ limits_parse_one(
                                        limit->lms_s_pr_total = 0;
 
                                } else {
-                                       char    *next = NULL;
                                        int     total;
 
-                                       total = strtol( arg, &next, 10 );
-                                       if ( next == arg || next[ 0 ] != '\0' ) {
-                                               return( 1 );
-                                       }
-
-                                       if ( total < -1 ) {
+                                       if ( lutil_atoi( &total, arg ) != 0 || total < -1 ) {
                                                return( 1 );
                                        }
 
@@ -883,10 +843,9 @@ limits_parse_one(
                                limit->lms_s_soft = -1;
 
                        } else {
-                               char    *next = NULL;
-
-                               limit->lms_s_soft = strtol( arg, &next, 10 );
-                               if ( next == arg || limit->lms_s_soft < -1 ) {
+                               if ( lutil_atoi( &limit->lms_s_soft, arg ) != 0
+                                       || limit->lms_s_soft < -1 )
+                               {
                                        return( 1 );
                                }
                        }
@@ -912,19 +871,26 @@ static const char *lmpats[] = {
        "*"
 };
 
+#define WHATSLEFT      ( buflen - ( ptr - bv->bv_val ) )
+
 /* Caller must provide an adequately sized buffer in bv */
-void
-limits_unparse( struct slap_limits *lim, struct berval *bv )
+int
+limits_unparse( struct slap_limits *lim, struct berval *bv, ber_len_t buflen )
 {
        struct berval btmp;
        char *ptr;
        int lm;
 
-       if ( !bv || !bv->bv_val ) return;
+       if ( !bv || !bv->bv_val ) return -1;
 
        ptr = bv->bv_val;
 
        if (( lim->lm_flags & SLAP_LIMITS_TYPE_MASK ) == SLAP_LIMITS_TYPE_GROUP ) {
+               if ( WHATSLEFT <= STRLENOF( "group/" "/" "=\"" "\"" )
+                               + lim->lm_group_oc->soc_cname.bv_len
+                               + lim->lm_group_ad->ad_cname.bv_len
+                               + lim->lm_pat.bv_len ) return -1;
+
                ptr = lutil_strcopy( ptr, "group/" );
                ptr = lutil_strcopy( ptr, lim->lm_group_oc->soc_cname.bv_val );
                *ptr++ = '/';
@@ -938,6 +904,7 @@ limits_unparse( struct slap_limits *lim, struct berval *bv )
                case SLAP_LIMITS_ANONYMOUS:
                case SLAP_LIMITS_USERS:
                case SLAP_LIMITS_ANY:
+                       if ( WHATSLEFT <= strlen( lmpats[lm] ) ) return -1;
                        ptr = lutil_strcopy( ptr, lmpats[lm] );
                        break;
                case SLAP_LIMITS_UNDEFINED:
@@ -946,6 +913,8 @@ limits_unparse( struct slap_limits *lim, struct berval *bv )
                case SLAP_LIMITS_SUBTREE:
                case SLAP_LIMITS_CHILDREN:
                case SLAP_LIMITS_REGEX:
+                       if ( WHATSLEFT <= STRLENOF( "dn." "=" "\"" "\"" )
+                                       + strlen( lmpats[lm] ) + lim->lm_pat.bv_len ) return -1;
                        ptr = lutil_strcopy( ptr, "dn." );
                        ptr = lutil_strcopy( ptr, lmpats[lm] );
                        *ptr++ = '=';
@@ -955,21 +924,26 @@ limits_unparse( struct slap_limits *lim, struct berval *bv )
                        break;
                }
        }
-       *ptr++ = ' ';
        bv->bv_len = ptr - bv->bv_val;
        btmp.bv_val = ptr;
        btmp.bv_len = 0;
-       limits_unparse_one( &lim->lm_limits, SLAP_LIMIT_SIZE|SLAP_LIMIT_TIME, &btmp );
+       if ( limits_unparse_one( &lim->lm_limits,
+                       SLAP_LIMIT_SIZE|SLAP_LIMIT_TIME,
+                       &btmp, WHATSLEFT ) )
+       {
+               return -1;
+       }
        bv->bv_len += btmp.bv_len;
+       return 0;
 }
 
 /* Caller must provide an adequately sized buffer in bv */
-void
-limits_unparse_one( struct slap_limits_set *lim, int which, struct berval *bv )
+int
+limits_unparse_one( struct slap_limits_set *lim, int which, struct berval *bv, ber_len_t buflen )
 {
        char *ptr;
 
-       if ( !bv || !bv->bv_val ) return;
+       if ( !bv || !bv->bv_val ) return -1;
 
        ptr = bv->bv_val;
 
@@ -979,89 +953,126 @@ limits_unparse_one( struct slap_limits_set *lim, int which, struct berval *bv )
                        /* If same as global limit, drop it */
                        if ( lim != &frontendDB->be_def_limit &&
                                lim->lms_s_soft == frontendDB->be_def_limit.lms_s_soft )
+                       {
                                goto s_hard;
                        /* If there's also a hard limit, fully qualify this one */
-                       else if ( lim->lms_s_hard )
+                       } else if ( lim->lms_s_hard ) {
+                               if ( WHATSLEFT <= STRLENOF( " size.soft=" ) ) return -1;
                                ptr = lutil_strcopy( ptr, " size.soft=" );
 
                        /* If doing both size & time, qualify this */
-                       else if ( which & SLAP_LIMIT_TIME )
+                       } else if ( which & SLAP_LIMIT_TIME ) {
+                               if ( WHATSLEFT <= STRLENOF( " size=" ) ) return -1;
                                ptr = lutil_strcopy( ptr, " size=" );
+                       }
 
-                       if ( lim->lms_s_soft == -1 )
+                       if ( lim->lms_s_soft == -1 ) {
+                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "unlimited" );
-                       else
-                               ptr += sprintf( ptr, "%d", lim->lms_s_soft );
+                       } else {
+                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_soft );
+                               if ( WHATSLEFT < 0 ) return -1;
+                       }
                        *ptr++ = ' ';
                }
 s_hard:
                if ( lim->lms_s_hard ) {
+                       if ( WHATSLEFT <= STRLENOF( " size.hard=" ) ) return -1;
                        ptr = lutil_strcopy( ptr, " size.hard=" );
-                       if ( lim->lms_s_hard == -1 )
+                       if ( lim->lms_s_hard == -1 ) {
+                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "unlimited" );
-                       else
-                               ptr += sprintf( ptr, "%d", lim->lms_s_hard );
+                       } else {
+                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_hard );
+                               if ( WHATSLEFT < 0 ) return -1;
+                       }
                        *ptr++ = ' ';
                }
                if ( lim->lms_s_unchecked != -1 ) {
+                       if ( WHATSLEFT <= STRLENOF( " size.unchecked=" ) ) return -1;
                        ptr = lutil_strcopy( ptr, " size.unchecked=" );
-                       if ( lim->lms_s_unchecked == 0 )
+                       if ( lim->lms_s_unchecked == 0 ) {
+                               if ( WHATSLEFT <= STRLENOF( "disabled" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "disabled" );
-                       else
-                               ptr += sprintf( ptr, "%d", lim->lms_s_unchecked );
+                       } else {
+                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_unchecked );
+                               if ( WHATSLEFT < 0 ) return -1;
+                       }
                        *ptr++ = ' ';
                }
                if ( lim->lms_s_pr_hide ) {
+                       if ( WHATSLEFT <= STRLENOF( " size.pr=noEstimate " ) ) return -1;
                        ptr = lutil_strcopy( ptr, " size.pr=noEstimate " );
                }
                if ( lim->lms_s_pr ) {
+                       if ( WHATSLEFT <= STRLENOF( " size.pr=" ) ) return -1;
                        ptr = lutil_strcopy( ptr, " size.pr=" );
-                       if ( lim->lms_s_pr == -1 )
+                       if ( lim->lms_s_pr == -1 ) {
+                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "unlimited" );
-                       else
-                               ptr += sprintf( ptr, "%d", lim->lms_s_pr );
+                       } else {
+                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_pr );
+                               if ( WHATSLEFT < 0 ) return -1;
+                       }
                        *ptr++ = ' ';
                }
                if ( lim->lms_s_pr_total ) {
+                       if ( WHATSLEFT <= STRLENOF( " size.prtotal=" ) ) return -1;
                        ptr = lutil_strcopy( ptr, " size.prtotal=" );
-                       if ( lim->lms_s_pr_total == -1 )
+                       if ( lim->lms_s_pr_total == -1 ) {
+                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "unlimited" );
-                       else if ( lim->lms_s_pr_total == -2 )
+                       } else if ( lim->lms_s_pr_total == -2 ) {
+                               if ( WHATSLEFT <= STRLENOF( "disabled" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "disabled" );
-                       else 
-                               ptr += sprintf( ptr, "%d", lim->lms_s_pr_total );
+                       } else {
+                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_pr_total );
+                               if ( WHATSLEFT < 0 ) return -1;
+                       }
                        *ptr++ = ' ';
                }
        }
+
        if ( which & SLAP_LIMIT_TIME ) {
                if ( lim->lms_t_soft != SLAPD_DEFAULT_TIMELIMIT ) {
 
                        /* If same as global limit, drop it */
                        if ( lim != &frontendDB->be_def_limit &&
                                lim->lms_t_soft == frontendDB->be_def_limit.lms_t_soft )
+                       {
                                goto t_hard;
 
                        /* If there's also a hard limit, fully qualify this one */
-                       else if ( lim->lms_t_hard ) 
+                       } else if ( lim->lms_t_hard ) {
+                               if ( WHATSLEFT <= STRLENOF( " time.soft=" ) ) return -1;
                                ptr = lutil_strcopy( ptr, " time.soft=" );
 
                        /* If doing both size & time, qualify this */
-                       else if ( which & SLAP_LIMIT_SIZE )
+                       } else if ( which & SLAP_LIMIT_SIZE ) {
+                               if ( WHATSLEFT <= STRLENOF( " time=" ) ) return -1;
                                ptr = lutil_strcopy( ptr, " time=" );
+                       }
 
-                       if ( lim->lms_t_soft == -1 )
+                       if ( lim->lms_t_soft == -1 ) {
+                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "unlimited" );
-                       else
-                               ptr += sprintf( ptr, "%d", lim->lms_t_soft );
+                       } else {
+                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_t_soft );
+                               if ( WHATSLEFT < 0 ) return -1;
+                       }
                        *ptr++ = ' ';
                }
 t_hard:
                if ( lim->lms_t_hard ) {
+                       if ( WHATSLEFT <= STRLENOF( " time.hard=" ) ) return -1;
                        ptr = lutil_strcopy( ptr, " time.hard=" );
-                       if ( lim->lms_t_hard == -1 )
+                       if ( lim->lms_t_hard == -1 ) {
+                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
                                ptr = lutil_strcopy( ptr, "unlimited" );
-                       else
-                               ptr += sprintf( ptr, "%d", lim->lms_t_hard );
+                       } else {
+                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_t_hard );
+                               if ( WHATSLEFT < 0 ) return -1;
+                       }
                        *ptr++ = ' ';
                }
        }
@@ -1070,13 +1081,15 @@ t_hard:
                *ptr = '\0';
                bv->bv_len = ptr - bv->bv_val;
        }
+
+       return 0;
 }
 
 int
 limits_check( Operation *op, SlapReply *rs )
 {
-       assert( op );
-       assert( rs );
+       assert( op != NULL );
+       assert( rs != NULL );
        /* FIXME: should this be always true? */
        assert( op->o_tag == LDAP_REQ_SEARCH);
 
@@ -1105,6 +1118,18 @@ limits_check( Operation *op, SlapReply *rs )
                        op->ors_slimit = SLAP_NO_LIMIT;
                }
 
+               /* if paged results and slimit are requested */ 
+               if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED &&
+                       op->ors_slimit != SLAP_NO_LIMIT ) {
+                       PagedResultsState *ps = op->o_pagedresults_state;
+                       int total = op->ors_slimit - ps->ps_count;
+                       if ( total > 0 ) {
+                               op->ors_slimit = total;
+                       } else {
+                               op->ors_slimit = 0;
+                       }
+               }
+
        /* if not root, get appropriate limits */
        } else {
                ( void ) limits_get( op, &op->o_ndn, &op->ors_limit );
@@ -1272,6 +1297,9 @@ limits_check( Operation *op, SlapReply *rs )
                                                return -1;
                                        }
                                        op->ors_slimit = slimit;
+
+                               } else if ( slimit == 0 ) {
+                                       op->ors_slimit = 0;
                                }
 
                        } else {
@@ -1319,3 +1347,37 @@ limits_check( Operation *op, SlapReply *rs )
        return 0;
 }
 
+void
+limits_destroy( 
+       struct slap_limits      **lm )
+{
+       int             i;
+
+       if ( lm == NULL ) {
+               return;
+       }
+
+       for ( i = 0; lm[ i ]; i++ ) {
+               switch ( lm[ i ]->lm_flags & SLAP_LIMITS_MASK ) {
+               case SLAP_LIMITS_REGEX:
+                       regfree( &lm[ i ]->lm_regex );
+                       break;
+
+               case SLAP_LIMITS_EXACT:
+               case SLAP_LIMITS_ONE:
+               case SLAP_LIMITS_SUBTREE:
+               case SLAP_LIMITS_CHILDREN:
+                       if ( !BER_BVISNULL( &lm[ i ]->lm_pat ) ) {
+                               ch_free( lm[ i ]->lm_pat.bv_val );
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+
+               ch_free( lm[ i ] );
+       }
+
+       ch_free( lm );
+}