idmap_autorid: improve implementation of idmap_autorid_parse_configstr()
authorAtul Kulkarni <atul.kulkarni@in.ibm.com>
Wed, 28 Aug 2013 14:12:58 +0000 (16:12 +0200)
committerMichael Adam <obnox@samba.org>
Tue, 1 Oct 2013 08:49:11 +0000 (10:49 +0200)
This new implementation is more generous. It can cope with multiple spaces.
It can also print more precise error messages, when the input string is not
valid.

Pair-Programmed-With: Michael Adam <obnox@samba.org>

Signed-off-by: Atul Kulkarni <atul.kulkarni@in.ibm.com>
Signed-off-by: Michael Adam <obnox@samba.org>
source3/winbindd/idmap_autorid_tdb.c

index 1f2d33ec4c38e9d70ff87c7b3c40ec5a710fc815..62b6d32f3bbfb46c59ca7d736b13f9e371a24e35 100644 (file)
@@ -275,22 +275,101 @@ NTSTATUS idmap_autorid_getconfigstr(struct db_context *db, TALLOC_CTX *mem_ctx,
 bool idmap_autorid_parse_configstr(const char *configstr,
                                   struct autorid_global_config *cfg)
 {
-       unsigned long minvalue, rangesize, maxranges;
-
-       if (sscanf(configstr,
-                  "minvalue:%lu rangesize:%lu maxranges:%lu",
-                  &minvalue, &rangesize, &maxranges) != 3) {
-               DEBUG(1,
-                     ("Found invalid configuration data"
-                      "creating new config\n"));
-               return false;
+       const char *confnames[] = { [0] = "minvalue",
+                                   [1] = "rangesize",
+                                   [2] = "maxranges" };
+       char *str1, *saveptr1;
+       const char *delim = " ";
+       const char *subdelim = ":";
+       int j;
+       bool ret = false;
+
+       if (cfg == NULL || configstr == NULL) {
+               goto done;
        }
 
-       cfg->minvalue = minvalue;
-       cfg->rangesize = rangesize;
-       cfg->maxranges = maxranges;
+       if (strlen(configstr) < 34) {
+               DEBUG(0, ("less than expected length for config: '%s'\n",
+                          configstr));
+               goto done;
+       }
+
+       DEBUG(5, ("config for parsing: %s\n", configstr));
+
+       for (j = 0, str1 = discard_const_p(char, configstr); ; j++, str1 = NULL)
+       {
+               int k;
+               char *token, *str2, *saveptr2;
+
+               token = strtok_r(str1, delim, &saveptr1);
+               if (token == NULL) {
+                       break;
+               }
+
+               if (strncmp(token, confnames[j], strlen(confnames[j]))) {
+                       DEBUG(0, ("expected %s but received '%s'\n",
+                                 confnames[j], token));
+                       goto done;
+               }
 
-       return true;
+               for (k=0, str2 = token; ; k++, str2 = NULL) {
+                       char *e = NULL;
+                       char *pp, *vp;
+
+                       pp = strtok_r(str2, subdelim, &saveptr2);
+                       if (pp == NULL) {
+                               break;
+                       }
+
+                       if (k > 0 ) {
+                               DEBUG(0, ("more than expected tokens in %s\n",
+                                         confnames[j]));
+                               goto done;
+                       }
+
+                       vp = strtok_r(NULL, subdelim, &saveptr2);
+                       if (vp == NULL) {
+                               DEBUG(0, ("error while looking"
+                                         " for a value of %s\n", pp));
+                               goto done;
+                       }
+
+                       if (*vp == '-') {
+                               DEBUG(0, ("value specified for '%s' "
+                                         "can't be negative\n", confnames[j]));
+                               goto done;
+                       }
+
+                       switch(j) {
+                               case 0:
+                                       cfg->minvalue = strtoul(vp, &e, 10);
+                                       break;
+                               case 1:
+                                       cfg->rangesize = strtoul(vp, &e, 10);
+                                       break;
+                               case 2:
+                                       cfg->maxranges = strtoul(vp, &e, 10);
+                                       break;
+                       }
+
+                       if (errno == ERANGE || vp == e || (e && *e != '\0')) {
+                               DEBUG(0, ("invalid value specified for '%s'\n",
+                                         confnames[j]));
+                               goto done;
+                       }
+               }
+       }
+
+       if (cfg->rangesize == 0 || cfg->maxranges == 0) {
+               DEBUG(0, ("%s and %s both must be greater than 0\n",
+                         confnames[1], confnames[2]));
+               goto done;
+       }
+
+       ret = true;
+
+done:
+       return ret;
 }
 
 NTSTATUS idmap_autorid_loadconfig(struct db_context *db,