source4: Use wrapper for string to integer conversion
authorSwen Schillig <swen@linux.ibm.com>
Wed, 30 Jan 2019 08:31:34 +0000 (09:31 +0100)
committerJeremy Allison <jra@samba.org>
Fri, 1 Mar 2019 00:32:11 +0000 (00:32 +0000)
In order to detect an value overflow error during
the string to integer conversion with strtoul/strtoull,
the errno variable must be set to zero before the execution and
checked after the conversion is performed. This is achieved by
using the wrapper function strtoul_err and strtoull_err.

Signed-off-by: Swen Schillig <swen@linux.ibm.com>
Reviewed-by: Ralph Böhme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
16 files changed:
source4/dns_server/dlz_bind9.c
source4/dsdb/common/dsdb_dn.c
source4/dsdb/common/util.c
source4/dsdb/samdb/ldb_modules/dirsync.c
source4/dsdb/samdb/ldb_modules/partition_metadata.c
source4/dsdb/samdb/ldb_modules/samldb.c
source4/dsdb/samdb/ldb_modules/schema_load.c
source4/dsdb/schema/schema_prefixmap.c
source4/lib/registry/ldb.c
source4/lib/socket/interface.c
source4/libcli/resolve/dns_ex.c
source4/nbt_server/wins/winsdb.c
source4/rpc_server/lsa/dcesrv_lsa.c
source4/torture/nbench/nbench.c
source4/torture/smb2/sharemode.c
source4/web_server/web_server.c

index 82c72111a007b59f9ad8e2855fca72ec07fd0d22..070990db3cff6d3951dc40b000d4e6cc730c966d 100644 (file)
@@ -307,8 +307,12 @@ static bool b9_dns_type(const char *type, enum dns_record_type *dtype)
 
 #define DNS_PARSE_UINT(ret, str, sep, saveptr) do {  \
        char *istr = strtok_r(str, sep, &saveptr); \
+       int error = 0;\
        if ((istr) == NULL) return false; \
-       (ret) = strtoul(istr, NULL, 10); \
+       (ret) = strtoul_err(istr, NULL, 10, &error); \
+       if (error != 0) {\
+               return false;\
+       }\
        } while (0)
 
 /*
index 900c6e2df63b6de89ba398dc71075f53f2a5b7a7..2119a4faaf33602ceeaff57523f525952304a762 100644 (file)
@@ -84,6 +84,7 @@ struct dsdb_dn *dsdb_dn_parse_trusted(TALLOC_CTX *mem_ctx, struct ldb_context *l
        struct ldb_val bval;
        struct ldb_val dval;
        char *dn_str;
+       int error = 0;
 
        enum dsdb_dn_format dn_format = dsdb_dn_oid_to_format(dn_oid);
 
@@ -134,8 +135,8 @@ struct dsdb_dn *dsdb_dn_parse_trusted(TALLOC_CTX *mem_ctx, struct ldb_context *l
        }
 
        errno = 0;
-       blen = strtoul(p1, &p2, 10);
-       if (errno != 0) {
+       blen = strtoul_err(p1, &p2, 10, &error);
+       if (error != 0) {
                DEBUG(10, (__location__ ": failed\n"));
                goto failed;
        }
index fc7055d800a3f767ffc5cae10e29d8064a331bd3..d466e6ff0a931ac56a5259b9a266a9a84d4db6cd 100644 (file)
@@ -3873,6 +3873,7 @@ NTSTATUS dsdb_get_extended_dn_guid(struct ldb_dn *dn, struct GUID *guid, const c
 NTSTATUS dsdb_get_extended_dn_uint64(struct ldb_dn *dn, uint64_t *val, const char *component_name)
 {
        const struct ldb_val *v;
+       int error = 0;
 
        v = ldb_dn_get_extended_component(dn, component_name);
        if (v == NULL) {
@@ -3887,7 +3888,10 @@ NTSTATUS dsdb_get_extended_dn_uint64(struct ldb_dn *dn, uint64_t *val, const cha
                memcpy(s, v->data, v->length);
                s[v->length] = 0;
 
-               *val = strtoull(s, NULL, 0);
+               *val = strtoull_err(s, NULL, 0, &error);
+               if (error != 0) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
        }
        return NT_STATUS_OK;
 }
@@ -3906,6 +3910,7 @@ NTSTATUS dsdb_get_extended_dn_nttime(struct ldb_dn *dn, NTTIME *nttime, const ch
 NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const char *component_name)
 {
        const struct ldb_val *v;
+       int error = 0;
 
        v = ldb_dn_get_extended_component(dn, component_name);
        if (v == NULL) {
@@ -3919,7 +3924,10 @@ NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const cha
                char s[v->length + 1];
                memcpy(s, v->data, v->length);
                s[v->length] = 0;
-               *val = strtoul(s, NULL, 0);
+               *val = strtoul_err(s, NULL, 0, &error);
+               if (error != 0) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
        }
 
        return NT_STATUS_OK;
@@ -3973,6 +3981,7 @@ uint32_t dsdb_dn_val_rmd_flags(const struct ldb_val *val)
        const char *p;
        uint32_t flags;
        char *end;
+       int error = 0;
 
        if (val->length < 13) {
                return 0;
@@ -3981,8 +3990,8 @@ uint32_t dsdb_dn_val_rmd_flags(const struct ldb_val *val)
        if (!p) {
                return 0;
        }
-       flags = strtoul(p+11, &end, 10);
-       if (!end || *end != '>') {
+       flags = strtoul_err(p+11, &end, 10, &error);
+       if (!end || *end != '>' || error != 0) {
                /* it must end in a > */
                return 0;
        }
index 2a9895ae641f4a7aa5bc83c69fdc7408930d9fb4..291876e162b25daea640ce9e09d077267f91941d 100644 (file)
@@ -157,11 +157,24 @@ static int dirsync_filter_entry(struct ldb_request *req,
        for (i = msg->num_elements - 1; i >= 0; i--) {
                attr = dsdb_attribute_by_lDAPDisplayName(dsc->schema, msg->elements[i].name);
                if (ldb_attr_cmp(msg->elements[i].name, "uSNChanged") == 0) {
+                       int error = 0;
                        /* Read the USN it will used at the end of the filtering
                         * to update the max USN in the cookie if we
                         * decide to keep this entry
                         */
-                       val = strtoull((const char*)msg->elements[i].values[0].data, NULL, 0);
+                       val = strtoull_err(
+                               (const char*)msg->elements[i].values[0].data,
+                               NULL,
+                               0,
+                               &error);
+                       if (error != 0) {
+                               ldb_set_errstring(ldb,
+                                                 "Failed to convert USN");
+                               return ldb_module_done(dsc->req,
+                                                      NULL,
+                                                      NULL,
+                                                      LDB_ERR_OPERATIONS_ERROR);
+                       }
                        continue;
                }
 
index 197e7b092e0a0f92059e7292c252cccfab3b57eb..250fecbd9e6f1a14422df9f4af8e2ad2ef4a4147 100644 (file)
@@ -36,6 +36,7 @@ static int partition_metadata_get_uint64(struct ldb_module *module,
        TDB_DATA tdb_key, tdb_data;
        char *value_str;
        TALLOC_CTX *tmp_ctx;
+       int error = 0;
 
        data = talloc_get_type_abort(ldb_module_get_private(module),
                                     struct partition_private_data);
@@ -73,7 +74,11 @@ static int partition_metadata_get_uint64(struct ldb_module *module,
                return ldb_module_oom(module);
        }
 
-       *value = strtoull(value_str, NULL, 10);
+       *value = strtoull_err(value_str, NULL, 10, &error);
+       if (error != 0) {
+               return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
+                                       "partition_metadata: converision failed");
+       }
 
        SAFE_FREE(tdb_data.dptr);
        talloc_free(tmp_ctx);
index e69228c32c75da1d8c644cabf78fe09cc59070eb..ae99ebbe9edb8dcf55cb6da703ad2fa998279f12 100644 (file)
@@ -3313,6 +3313,7 @@ static int verify_cidr(const char *cidr)
        char *address_redux = NULL;
        unsigned int address_len;
        TALLOC_CTX *frame = NULL;
+       int error = 0;
 
        DBG_DEBUG("CIDR is %s\n", cidr);
        frame = talloc_stackframe();
@@ -3329,14 +3330,14 @@ static int verify_cidr(const char *cidr)
        /* terminate the address for strchr, inet_pton */
        *slash = '\0';
 
-       mask = strtoul(slash + 1, &endptr, 10);
+       mask = strtoul_err(slash + 1, &endptr, 10, &error);
        if (mask == 0){
                DBG_INFO("Windows does not like the zero mask, "
                         "so nor do we: %s\n", cidr);
                goto error;
        }
 
-       if (*endptr != '\0' || endptr == slash + 1){
+       if (*endptr != '\0' || endptr == slash + 1 || error != 0){
                DBG_INFO("CIDR mask is not a proper integer: %s\n", cidr);
                goto error;
        }
index 473a2e0a1f79b53e91407ed7151cd88eac076f8e..3b0781685cf95c327c86d1f47d4a539109373d2f 100644 (file)
@@ -117,6 +117,7 @@ static int schema_metadata_get_uint64(struct schema_load_private_data *data,
        char *value_str;
        TALLOC_CTX *tmp_ctx;
        int tdb_seqnum;
+       int error = 0;
 
        if (!data) {
                *value = default_value;
@@ -169,7 +170,12 @@ static int schema_metadata_get_uint64(struct schema_load_private_data *data,
         * next time
         */
        data->tdb_seqnum = tdb_seqnum;
-       data->schema_seq_num_cache = strtoull(value_str, NULL, 10);
+       data->schema_seq_num_cache = strtoull_err(value_str, NULL, 10, &error);
+       if (error != 0) {
+               talloc_free(tmp_ctx);
+               return ldb_module_error(data->module, LDB_ERR_OPERATIONS_ERROR,
+                                       "Failed to convert value");
+       }
 
        *value = data->schema_seq_num_cache;
 
index c30aecc0ec265eec5e5cf76a956badc4be6e4340..482a35f21658b9458080c9dc68d942ba8a7bc6ad 100644 (file)
@@ -216,6 +216,7 @@ static WERROR _dsdb_pfm_make_binary_oid(const char *full_oid, TALLOC_CTX *mem_ct
 {
        uint32_t last_subid;
        const char *oid_subid;
+       int error = 0;
 
        /* make last sub-identifier value */
        oid_subid = strrchr(full_oid, '.');
@@ -223,7 +224,10 @@ static WERROR _dsdb_pfm_make_binary_oid(const char *full_oid, TALLOC_CTX *mem_ct
                return WERR_INVALID_PARAMETER;
        }
        oid_subid++;
-       last_subid = strtoul(oid_subid, NULL, 10);
+       last_subid = strtoul_err(oid_subid, NULL, 10, &error);
+       if (error != 0) {
+               return WERR_INVALID_PARAMETER;
+       }
 
        /* encode oid in BER format */
        if (!ber_write_OID_String(mem_ctx, _bin_oid, full_oid)) {
index 8bb6fd5c10f2006352e846552026d6d1745311b1..ec293c46149b6c2bea8688d3e532c4e9e1a3b606 100644 (file)
@@ -75,8 +75,16 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx,
        case REG_DWORD:
        case REG_DWORD_BIG_ENDIAN:
                if (val != NULL) {
+                       int error = 0;
                        /* The data is a plain DWORD */
-                       uint32_t tmp = strtoul((char *)val->data, NULL, 0);
+                       uint32_t tmp;
+
+                       tmp = strtoul_err((char *)val->data, NULL, 0, &error);
+                       if (error != 0) {
+                               data->data = NULL;
+                               data->length = 0;
+                               break;
+                       }
                        data->data = talloc_size(mem_ctx, sizeof(uint32_t));
                        if (data->data != NULL) {
                                SIVAL(data->data, 0, tmp);
@@ -90,8 +98,16 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx,
 
        case REG_QWORD:
                if (val != NULL) {
+                       int error = 0;
                        /* The data is a plain QWORD */
-                       uint64_t tmp = strtoull((char *)val->data, NULL, 0);
+                       uint64_t tmp;
+
+                       tmp = strtoull_err((char *)val->data, NULL, 0, &error);
+                       if (error != 0) {
+                               data->data = NULL;
+                               data->length = 0;
+                               break;
+                       }
                        data->data = talloc_size(mem_ctx, sizeof(uint64_t));
                        if (data->data != NULL) {
                                SBVAL(data->data, 0, tmp);
index 594df1a0526cc9d75994b05adbc451bbac4b53ff..494cbd4fdd294baf7a4c96f6b917bc925e5cb963 100644 (file)
@@ -225,8 +225,10 @@ static void interpret_interface(TALLOC_CTX *mem_ctx,
                }
        } else {
                char *endp = NULL;
-               unsigned long val = strtoul(p, &endp, 0);
-               if (p == endp || (endp && *endp != '\0')) {
+               int error = 0;
+
+               unsigned long val = strtoul_err(p, &endp, 0, &error);
+               if (p == endp || (endp && *endp != '\0') || error != 0) {
                        DEBUG(2,("interpret_interface: "
                                "can't determine netmask value from %s\n",
                                p));
index 6174b617cb37137a9f89fcd1fe48b697b6dcdc6f..a6863aed59e99bc9cb2cd6a717757e019a3e689c 100644 (file)
@@ -514,6 +514,7 @@ static void pipe_handler(struct tevent_context *ev, struct tevent_fd *fde,
                uint32_t port = 0;
                char *p = strrchr(addrs[i], '@');
                char *n;
+               int error = 0;
 
                if (!p) {
                        composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
@@ -536,8 +537,8 @@ static void pipe_handler(struct tevent_context *ev, struct tevent_fd *fde,
                        composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
                        return;
                }
-               port = strtoul(p, NULL, 10);
-               if (port > UINT16_MAX) {
+               port = strtoul_err(p, NULL, 10, &error);
+               if (port > UINT16_MAX || error != 0) {
                        composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
                        return;
                }
index fa9a6154b9a80f0471914d65c4a1238d5586bf9b..5184d7de7b0cfc26efda283f84fc778b561dcfeb 100644 (file)
@@ -148,6 +148,7 @@ static NTSTATUS winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct n
        struct nbt_name *name;
        unsigned int comp_num;
        uint32_t cur = 0;
+       int error = 0;
 
        name = talloc(mem_ctx, struct nbt_name);
        if (!name) {
@@ -181,7 +182,16 @@ static NTSTATUS winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct n
        }
 
        if (comp_num > cur && strcasecmp("type", ldb_dn_get_component_name(dn, cur)) == 0) {
-               name->type      = strtoul((char *)ldb_dn_get_component_val(dn, cur)->data, NULL, 0);
+               name->type =
+                       strtoul_err(
+                               (char *)ldb_dn_get_component_val(dn, cur)->data,
+                               NULL,
+                               0,
+                               &error);
+               if (error != 0) {
+                       status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+                       goto failed;
+               }
                cur++;
        } else {
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
index cbbd9f482f2c28c76472e579332cddfab47cf50f..64d2ec9991a58b7b33dd59e0fee50645589e43b2 100644 (file)
@@ -1698,6 +1698,7 @@ static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
        uint32_t orig_uint = 0;
        unsigned int flags = 0;
        int ret;
+       int error = 0;
 
        orig_val = ldb_msg_find_ldb_val(orig, attribute);
        if (!orig_val || !orig_val->data) {
@@ -1705,9 +1706,11 @@ static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
                flags = LDB_FLAG_MOD_ADD;
 
        } else {
-               errno = 0;
-               orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
-               if (errno != 0 || orig_uint != value) {
+               orig_uint = strtoul_err((const char *)orig_val->data,
+                                       NULL,
+                                       0,
+                                       &error);
+               if (error != 0 || orig_uint != value) {
                        /* replace also if can't get value */
                        flags = LDB_FLAG_MOD_REPLACE;
                }
index 8e4a984c9b5fa01413e327343ccec144702aa830..83395123c3300ab2760d7eea4c5895b71705f2c9 100644 (file)
@@ -96,6 +96,8 @@ again:
        while (fgets(line, sizeof(line)-1, f)) {
                NTSTATUS status;
                const char **params0, **params;
+               unsigned long int tmp;
+               int error = 0;
 
                nbench_line_count++;
 
@@ -138,7 +140,11 @@ again:
 
                /* accept numeric or string status codes */
                if (strncmp(params[i-1], "0x", 2) == 0) {
-                       status = NT_STATUS(strtoul(params[i-1], NULL, 16));
+                       tmp = strtoul_err(params[i-1], NULL, 16, &error);
+                       if (error != 0) {
+                               tmp = error;
+                       }
+                       status = NT_STATUS(tmp);
                } else {
                        status = nt_status_string_to_code(params[i-1]);
                }
index 8c7403c830243d895dae4493190b523be3690183..b76aa4ccd7da4080ca8f96bf5fdb5d135435c7df 100644 (file)
@@ -186,12 +186,17 @@ bool torture_smb2_check_sharemode(struct torture_context *tctx)
        struct smb2_create create = { };
        NTSTATUS status;
        bool ret = true;
+       int error = 0;
 
        sharemode_string = torture_setting_string(tctx, "sharemode", "RWD");
        sharemode = smb2_util_share_access(sharemode_string);
 
        access_string = torture_setting_string(tctx, "access", "0xf01ff");
-       access = strtoul(access_string, NULL, 0);
+       access = strtoul_err(access_string, NULL, 0, &error);
+       if (error != 0) {
+               torture_comment(tctx, "Initializing access failed.\n");
+               return false;
+       }
 
        filename = torture_setting_string(tctx, "filename", "testfile");
        operation = torture_setting_string(tctx, "operation", "WD");
index 7c2717368e3120bc38215e33daf981e05930a551..a1db34be21a83b7c7f42bb3d2eff8d6b550e17bb 100644 (file)
@@ -107,6 +107,8 @@ void websrv_output(struct websrv_context *web, const void *data, size_t length)
 */
 NTSTATUS http_parse_header(struct websrv_context *web, const char *line)
 {
+       int error = 0;
+
        if (line[0] == 0) {
                web->input.end_of_headers = true;
        } else if (strncasecmp(line,"GET ", 4)==0) {
@@ -118,7 +120,10 @@ NTSTATUS http_parse_header(struct websrv_context *web, const char *line)
                http_error(web, "400 Bad request", "This server only accepts GET and POST requests");
                return NT_STATUS_INVALID_PARAMETER;
        } else if (strncasecmp(line, "Content-Length: ", 16)==0) {
-               web->input.content_length = strtoul(&line[16], NULL, 10);
+               web->input.content_length = strtoul_err(&line[16], NULL, 10, &error);
+               if (error != 0) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
        } else {
                struct http_header *hdr = talloc_zero(web, struct http_header);
                char *colon = strchr(line, ':');