URL: https://github.com/SSSD/sssd/pull/5827
Author: alexey-tikhonov
 Title: #5827: A number of fixes around `strto*()` usage
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5827/head:pr5827
git checkout pr5827
From aafba2f98e61789570a821f7fc7f3653f0fb13f3 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Fri, 15 Oct 2021 18:23:55 +0200
Subject: [PATCH 1/4] Removed excessive includes around 'strtonum'

---
 src/providers/ad/ad_gpo.c  | 1 +
 src/util/strtonum.c        | 6 ------
 src/util/strtonum.h        | 2 --
 src/util/usertools.c       | 1 +
 src/util/well_known_sids.c | 1 +
 5 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index f3452176af..8f2fe277e1 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -31,6 +31,7 @@
  *   ad_gpo_process_cse_send/recv: retrieve policy file data
  */
 
+#include <ctype.h>
 #include <security/pam_modules.h>
 #include <syslog.h>
 #include <fcntl.h>
diff --git a/src/util/strtonum.c b/src/util/strtonum.c
index 22e682b4b2..8eda8ea25e 100644
--- a/src/util/strtonum.c
+++ b/src/util/strtonum.c
@@ -19,14 +19,10 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <ctype.h>
 #include <stdlib.h>
 #include <errno.h>
-#include "config.h"
-#include "util/util.h"
 #include "util/strtonum.h"
 
-/* strtoint32 */
 int32_t strtoint32(const char *nptr, char **endptr, int base)
 {
     long long ret = 0;
@@ -48,7 +44,6 @@ int32_t strtoint32(const char *nptr, char **endptr, int base)
 }
 
 
-/* strtouint32 */
 uint32_t strtouint32(const char *nptr, char **endptr, int base)
 {
     unsigned long long ret = 0;
@@ -65,7 +60,6 @@ uint32_t strtouint32(const char *nptr, char **endptr, int base)
 }
 
 
-/* strtouint16 */
 uint16_t strtouint16(const char *nptr, char **endptr, int base)
 {
     unsigned long long ret = 0;
diff --git a/src/util/strtonum.h b/src/util/strtonum.h
index d9c31e9cde..ae493b5f51 100644
--- a/src/util/strtonum.h
+++ b/src/util/strtonum.h
@@ -22,8 +22,6 @@
 #ifndef _STRTONUM_H_
 #define _STRTONUM_H_
 
-#include <ctype.h>
-#include <stdlib.h>
 #include <stdint.h>
 
 int32_t strtoint32(const char *nptr, char **endptr, int base);
diff --git a/src/util/usertools.c b/src/util/usertools.c
index 6f93a4cef2..1fbde2eb43 100644
--- a/src/util/usertools.c
+++ b/src/util/usertools.c
@@ -21,6 +21,7 @@
 
 #include <pwd.h>
 #include <errno.h>
+#include <ctype.h>
 #include <talloc.h>
 #include <grp.h>
 
diff --git a/src/util/well_known_sids.c b/src/util/well_known_sids.c
index 38fe2646fa..1f9a7beea8 100644
--- a/src/util/well_known_sids.c
+++ b/src/util/well_known_sids.c
@@ -20,6 +20,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <ctype.h>
 #include "util/util.h"
 #include "util/strtonum.h"
 

From 52cdf419f774f7e26636527ceda3ee6c6d69b7cb Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Fri, 15 Oct 2021 21:12:32 +0200
Subject: [PATCH 2/4] 'strtonum' helpers: usage sanitization

To properly check for an error during string to number conversion
one needs to:
 - check `errno`
 - check that something was really converted (i.e. start != end)
 - (if this is expected) check that entire string was consumed

Some of those error conditions weren't checked in various locations
over the code.
---
 src/db/sysdb.c                           | 3 ---
 src/providers/ad/ad_id.c                 | 8 ++++----
 src/providers/ad/ad_machine_pw_renewal.c | 2 --
 src/providers/ipa/ipa_s2n_exop.c         | 1 -
 src/providers/ipa/ipa_subdomains_id.c    | 8 ++++----
 src/providers/ipa/ipa_views.c            | 1 -
 src/providers/ldap/ldap_id.c             | 4 ++--
 src/providers/ldap/ldap_id_services.c    | 7 ++++---
 src/providers/ldap/sdap_access.c         | 8 ++++----
 src/providers/ldap/sdap_range.c          | 2 +-
 src/providers/proxy/proxy_services.c     | 1 -
 src/responder/common/responder_common.c  | 3 +--
 src/responder/ifp/ifp_groups.c           | 9 +++++----
 src/responder/ifp/ifp_users.c            | 7 ++++---
 src/responder/ifp/ifpsrv.c               | 7 ++++---
 src/tools/common/sss_colondb.c           | 7 ++++---
 src/util/usertools.c                     | 3 +--
 src/util/well_known_sids.c               | 1 -
 18 files changed, 38 insertions(+), 44 deletions(-)

diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 3fe0ebf6c2..3ba79ab360 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -359,7 +359,6 @@ int sysdb_attrs_get_int32_t(struct sysdb_attrs *attrs, const char *name,
         return ERANGE;
     }
 
-    errno = 0;
     val = strtoint32((const char *) el->values[0].data, &endptr, 10);
     if (errno != 0) return errno;
     if (*endptr) return EINVAL;
@@ -385,7 +384,6 @@ int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name,
         return ERANGE;
     }
 
-    errno = 0;
     val = strtouint32((const char *) el->values[0].data, &endptr, 10);
     if (errno != 0) return errno;
     if (*endptr) return EINVAL;
@@ -411,7 +409,6 @@ int sysdb_attrs_get_uint16_t(struct sysdb_attrs *attrs, const char *name,
         return ERANGE;
     }
 
-    errno = 0;
     val = strtouint16((const char *) el->values[0].data, &endptr, 10);
     if (errno != 0) return errno;
     if (*endptr) return EINVAL;
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 8e4a0a5094..3d12472432 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -42,6 +42,7 @@ static bool ad_account_can_shortcut(struct sdap_idmap_ctx *idmap_ctx,
     uint32_t id;
     bool shortcut = false;
     errno_t ret;
+    char *endptr;
 
     if (!sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx, domain->name,
                                                    domain->domain_id)) {
@@ -51,10 +52,9 @@ static bool ad_account_can_shortcut(struct sdap_idmap_ctx *idmap_ctx,
     switch (filter_type) {
     case BE_FILTER_IDNUM:
         /* convert value to ID */
-        errno = 0;
-        id = strtouint32(filter_value, NULL, 10);
-        if (errno != 0) {
-            ret = errno;
+        id = strtouint32(filter_value, &endptr, 10);
+        if ((errno != 0) || *endptr || (filter_value == endptr)) {
+            ret = errno ? errno : EINVAL;
             DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert filter value to "
                   "number [%d]: %s\n", ret, strerror(ret));
             goto done;
diff --git a/src/providers/ad/ad_machine_pw_renewal.c b/src/providers/ad/ad_machine_pw_renewal.c
index 6e7137a86a..b5c6cfec94 100644
--- a/src/providers/ad/ad_machine_pw_renewal.c
+++ b/src/providers/ad/ad_machine_pw_renewal.c
@@ -360,7 +360,6 @@ errno_t ad_machine_account_password_renewal_init(struct be_ctx *be_ctx,
         goto done;
     }
 
-    errno = 0;
     period = strtouint32(opt_list[0], &endptr, 10);
     if (errno != 0 || *endptr != '\0' || opt_list[0] == endptr) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse first renewal option.\n");
@@ -368,7 +367,6 @@ errno_t ad_machine_account_password_renewal_init(struct be_ctx *be_ctx,
         goto done;
     }
 
-    errno = 0;
     initial_delay = strtouint32(opt_list[1], &endptr, 10);
     if (errno != 0 || *endptr != '\0' || opt_list[0] == endptr) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse second renewal option.\n");
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index b0baf0e67c..56105ac2bd 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -1340,7 +1340,6 @@ static errno_t ipa_s2n_get_list_step(struct tevent_req *req)
 
         break;
     case REQ_INP_ID:
-        errno = 0;
         id = strtouint32(state->list[state->list_idx], &endptr, 10);
         if (errno != 0 || *endptr != '\0'
                 || (state->list[state->list_idx] == endptr)) {
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 46d4962585..445b9ba2ff 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -1125,6 +1125,7 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
     uint32_t id;
     struct ldb_message *msg = NULL;
     struct ldb_result *res = NULL;
+    char *endptr;
     const char *attrs[] = { SYSDB_NAME,
                             SYSDB_UIDNUM,
                             SYSDB_SID_STR,
@@ -1183,10 +1184,9 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
         ret = EOK;
         goto done;
     } else if (ar->filter_type == BE_FILTER_IDNUM) {
-        errno = 0;
-        id = strtouint32(ar->filter_value, NULL, 10);
-        if (errno != 0) {
-            ret = errno;
+        id = strtouint32(ar->filter_value, &endptr, 10);
+        if ((errno != 0) || *endptr || (ar->filter_value == endptr)) {
+            ret = errno ? errno : EINVAL;
             DEBUG(SSSDBG_OP_FAILURE, "strtouint32 failed.\n");
             goto done;
         }
diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
index e1090d03b3..50243098ae 100644
--- a/src/providers/ipa/ipa_views.c
+++ b/src/providers/ipa/ipa_views.c
@@ -90,7 +90,6 @@ static errno_t dp_id_data_to_override_filter(TALLOC_CTX *mem_ctx,
         break;
 
     case BE_FILTER_IDNUM:
-        errno = 0;
         id = strtouint32(ar->filter_value, &endptr, 10);
         if (errno != 0|| *endptr != '\0' || (ar->filter_value == endptr)) {
             DEBUG(SSSDBG_CRIT_FAILURE, "Invalid id value [%s].\n",
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 9b67773a8d..51cebc8c9b 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -264,7 +264,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
              * in the search filter.
              */
             uid = strtouint32(filter_value, &endptr, 10);
-            if (errno != EOK) {
+            if ((errno != EOK) || *endptr || (filter_value == endptr)) {
                 ret = EINVAL;
                 goto done;
             }
@@ -742,7 +742,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
              * in the search filter.
              */
             gid = strtouint32(filter_value, &endptr, 10);
-            if (errno != EOK) {
+            if ((errno != EOK) || *endptr || (filter_value == endptr)) {
                 ret = EINVAL;
                 goto done;
             }
diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c
index 638cb619b3..52a1563184 100644
--- a/src/providers/ldap/ldap_id_services.c
+++ b/src/providers/ldap/ldap_id_services.c
@@ -217,6 +217,7 @@ services_get_done(struct tevent_req *subreq)
 {
     errno_t ret;
     uint16_t port;
+    char *endptr;
     struct tevent_req *req =
             tevent_req_callback_data(subreq, struct tevent_req);
     struct sdap_services_get_state *state =
@@ -263,9 +264,9 @@ services_get_done(struct tevent_req *subreq)
             break;
 
         case BE_FILTER_IDNUM:
-            port = strtouint16(state->name, NULL, 10);
-            if (errno) {
-                tevent_req_error(req, errno);
+            port = strtouint16(state->name, &endptr, 10);
+            if (errno || *endptr || (state->name == endptr)) {
+                tevent_req_error(req, (errno ? errno : EINVAL));
                 return;
             }
 
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index 8add97ba88..1b898d2448 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -1812,6 +1812,7 @@ is_account_locked(const char *pwdAccountLockedTime,
     time_t duration;
     time_t now;
     bool locked;
+    char *endptr;
 
     /* Default action is to consider account to be locked. */
     locked = true;
@@ -1855,10 +1856,9 @@ is_account_locked(const char *pwdAccountLockedTime,
         if (difftime(lock_time, now) > 0.0) {
             locked = false;
         } else if (pwdAccountLockedDurationTime != NULL) {
-            errno = 0;
-            duration = strtouint32(pwdAccountLockedDurationTime, NULL, 0);
-            if (errno) {
-                ret = errno;
+            duration = strtouint32(pwdAccountLockedDurationTime, &endptr, 0);
+            if (errno || *endptr) {
+                ret = errno ? errno : EINVAL;
                 goto done;
             }
             /* Lockout has expired */
diff --git a/src/providers/ldap/sdap_range.c b/src/providers/ldap/sdap_range.c
index d88def6fa9..44c3350db1 100644
--- a/src/providers/ldap/sdap_range.c
+++ b/src/providers/ldap/sdap_range.c
@@ -120,7 +120,7 @@ errno_t sdap_parse_range(TALLOC_CTX *mem_ctx,
     }
 
     *range_offset = strtouint32(end_range, &endptr, 10);
-    if (*endptr != '\0') {
+    if ((errno != 0) || (*endptr != '\0') || (end_range == endptr)) {
         *range_offset = 0;
         ret = errno;
         DEBUG(SSSDBG_MINOR_FAILURE,
diff --git a/src/providers/proxy/proxy_services.c b/src/providers/proxy/proxy_services.c
index 2f7bbeb06d..856da09be9 100644
--- a/src/providers/proxy/proxy_services.c
+++ b/src/providers/proxy/proxy_services.c
@@ -171,7 +171,6 @@ get_serv_byport(struct proxy_id_ctx *ctx,
         goto done;
     }
 
-    errno = 0;
     port = htons(strtouint16(be_filter, NULL, 0));
     if (errno) {
         ret = errno;
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 7e145aa9b2..913dbcd800 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -224,7 +224,6 @@ errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
     }
 
     for (c = 0; c < list_size; c++) {
-        errno = 0;
         if (*list[c] == '\0') {
             DEBUG(SSSDBG_OP_FAILURE, "Empty list item.\n");
             ret = EINVAL;
@@ -232,7 +231,7 @@ errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
         }
 
         uids[c] = strtouint32(list[c], &endptr, 10);
-        if (errno != 0 || *endptr != '\0') {
+        if ((errno != 0) || (*endptr != '\0') || (list[c] == endptr)) {
             ret = errno;
             if (ret == ERANGE) {
                 DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is out of range.\n",
diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c
index 353f3a79f3..14c58c74c3 100644
--- a/src/responder/ifp/ifp_groups.c
+++ b/src/responder/ifp/ifp_groups.c
@@ -530,13 +530,14 @@ ifp_groups_get_from_cache(TALLOC_CTX *mem_ctx,
     struct ldb_result *group_res = NULL;
     errno_t ret;
     gid_t gid;
+    char *endptr;
 
     switch (domain->type) {
     case DOM_TYPE_POSIX:
-        gid = strtouint32(key, NULL, 10);
-        ret = errno;
-        if (ret != EOK) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Invalid UID value\n");
+        gid = strtouint32(key, &endptr, 10);
+        if ((errno != 0) || *endptr || (key == endptr)) {
+            ret = errno ? errno : EINVAL;
+            DEBUG(SSSDBG_CRIT_FAILURE, "Invalid GID value\n");
             return ret;
         }
 
diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c
index ac9330858f..714f7ef78d 100644
--- a/src/responder/ifp/ifp_users.c
+++ b/src/responder/ifp/ifp_users.c
@@ -1038,12 +1038,13 @@ ifp_users_get_from_cache(TALLOC_CTX *mem_ctx,
     struct ldb_result *user_res = NULL;
     errno_t ret;
     uid_t uid;
+    char *endptr;
 
     switch (domain->type) {
     case DOM_TYPE_POSIX:
-        uid = strtouint32(key, NULL, 10);
-        ret = errno;
-        if (ret != EOK) {
+        uid = strtouint32(key, &endptr, 10);
+        if ((errno != 0) || *endptr || (key == endptr)) {
+            ret = errno ? errno : EINVAL;
             DEBUG(SSSDBG_CRIT_FAILURE, "Invalid UID value\n");
             goto done;
         }
diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
index 6de2e00a01..d27c2dfccd 100644
--- a/src/responder/ifp/ifpsrv.c
+++ b/src/responder/ifp/ifpsrv.c
@@ -166,6 +166,7 @@ int ifp_process_init(TALLOC_CTX *mem_ctx,
     char *uid_str;
     char *attr_list_str;
     char *wildcard_limit_str;
+    char *endptr;
 
     ifp_cmds = get_ifp_cmds();
     ret = sss_process_init(mem_ctx, ev, cdb,
@@ -245,9 +246,9 @@ int ifp_process_init(TALLOC_CTX *mem_ctx,
     }
 
     if (wildcard_limit_str) {
-        ifp_ctx->wildcard_limit = strtouint32(wildcard_limit_str, NULL, 10);
-        ret = errno;
-        if (ret != EOK) {
+        ifp_ctx->wildcard_limit = strtouint32(wildcard_limit_str, &endptr, 10);
+        if ((errno != 0) || *endptr || (wildcard_limit_str == endptr)) {
+            ret = errno ? errno : EINVAL;
             goto fail;
         }
     }
diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c
index e8aeb315c9..41e6c3a51d 100644
--- a/src/tools/common/sss_colondb.c
+++ b/src/tools/common/sss_colondb.c
@@ -78,6 +78,7 @@ static char *read_field_as_uint32(char *line,
     const char *str;
     char *rest;
     errno_t ret;
+    char *endptr;
 
     rest = read_field_as_string(line, &str);
     if (str == NULL) {
@@ -85,9 +86,9 @@ static char *read_field_as_uint32(char *line,
         return rest;
     }
 
-    *_value = strtouint32(str, NULL, 10);
-    if (errno != 0) {
-        ret = errno;
+    *_value = strtouint32(str, &endptr, 10);
+    if ((errno != 0) || *endptr || (str == endptr)) {
+        ret = errno ? errno : EINVAL;
         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse number [%d]: %s\n",
               ret, sss_strerror(ret));
 
diff --git a/src/util/usertools.c b/src/util/usertools.c
index 1fbde2eb43..370a98b417 100644
--- a/src/util/usertools.c
+++ b/src/util/usertools.c
@@ -578,9 +578,8 @@ errno_t sss_user_by_name_or_uid(const char *input, uid_t *_uid, gid_t *_gid)
     struct passwd *pwd;
 
     /* Try if it's an ID first */
-    errno = 0;
     uid = strtouint32(input, &endptr, 10);
-    if (errno != 0 || *endptr != '\0') {
+    if ((errno != 0) || (*endptr != '\0') || (input == endptr)) {
         ret = errno;
         if (ret == ERANGE) {
             DEBUG(SSSDBG_OP_FAILURE,
diff --git a/src/util/well_known_sids.c b/src/util/well_known_sids.c
index 1f9a7beea8..0b51667a2a 100644
--- a/src/util/well_known_sids.c
+++ b/src/util/well_known_sids.c
@@ -189,7 +189,6 @@ static errno_t handle_rid_to_name_map(const char *sid, size_t prefix_len,
     char *endptr;
     size_t c;
 
-    errno = 0;
     rid = (uint32_t) strtouint32(sid + prefix_len, &endptr, 10);
     if (errno != 0 || *endptr != '\0') {
         return EINVAL;

From 5b8e1995fb23aa0dcdb3cfe85da3e33fc7fbe3b0 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Fri, 15 Oct 2021 22:29:12 +0200
Subject: [PATCH 3/4] 'strto*()': usage sanitization

To properly check for an error during string to number conversion
one needs to:
 - check `errno`
 - check that something was really converted (i.e. start != end)
 - (if this is expected) check that entire string was consumed

Some of those error conditions weren't checked in various locations
over the code.
---
 src/confdb/confdb.c                            | 16 ++++++++++++----
 src/providers/ldap/sdap.c                      |  6 ++++--
 src/providers/ldap/sdap_async_enum.c           |  7 ++++---
 src/providers/ldap/sdap_async_iphost.c         |  4 ++--
 src/providers/ldap/sdap_async_ipnetwork.c      |  4 ++--
 src/providers/ldap/sdap_async_services.c       |  4 ++--
 src/util/crypto/libcrypto/crypto_sha512crypt.c |  3 ++-
 7 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index 80203c0f64..6a6fac916e 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -439,6 +439,7 @@ int confdb_get_int(struct confdb_ctx *cdb,
     char **values = NULL;
     long val;
     int ret;
+    char *endptr;
     TALLOC_CTX *tmp_ctx;
 
     tmp_ctx = talloc_new(NULL);
@@ -460,12 +461,15 @@ int confdb_get_int(struct confdb_ctx *cdb,
         }
 
         errno = 0;
-        val = strtol(values[0], NULL, 0);
+        val = strtol(values[0], &endptr, 0);
         ret = errno;
         if (ret != 0) {
             goto failed;
         }
-
+        if (*endptr || (values[0] == endptr)) {
+            ret = EINVAL;
+            goto failed;
+        }
         if (val < INT_MIN || val > INT_MAX) {
             ret = ERANGE;
             goto failed;
@@ -495,6 +499,7 @@ long confdb_get_long(struct confdb_ctx *cdb,
     char **values = NULL;
     long val;
     int ret;
+    char *endptr;
     TALLOC_CTX *tmp_ctx;
 
     tmp_ctx = talloc_new(NULL);
@@ -516,12 +521,15 @@ long confdb_get_long(struct confdb_ctx *cdb,
         }
 
         errno = 0;
-        val = strtol(values[0], NULL, 0);
+        val = strtol(values[0], &endptr, 0);
         ret = errno;
         if (ret != 0) {
             goto failed;
         }
-
+        if (*endptr || (values[0] == endptr)) {
+            ret = EINVAL;
+            goto failed;
+        }
     } else {
         val = defval;
     }
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 32c0144b92..72d6a72812 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -1418,8 +1418,9 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
                               opts->gen_map[SDAP_AT_ENTRY_USN].opt_name);
                 } else {
                     so->supports_usn = true;
+                    errno = 0;
                     so->last_usn = strtoul(last_usn_value, &endptr, 10);
-                    if (endptr != NULL && (*endptr != '\0' || endptr == last_usn_value)) {
+                    if (errno || !endptr || *endptr || (endptr == last_usn_value)) {
                         DEBUG(SSSDBG_MINOR_FAILURE,
                               "USN is not valid (value: %s)\n", last_usn_value);
                         so->last_usn = 0;
@@ -1442,8 +1443,9 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
                     opts->gen_map[SDAP_AT_ENTRY_USN].name =
                         talloc_strdup(opts->gen_map, usn_attrs[i].entry_name);
                     so->supports_usn = true;
+                    errno = 0;
                     so->last_usn = strtoul(last_usn_value, &endptr, 10);
-                    if (endptr != NULL && (*endptr != '\0' || endptr == last_usn_value)) {
+                    if (errno || !endptr || *endptr || (endptr == last_usn_value)) {
                         DEBUG(SSSDBG_MINOR_FAILURE,
                               "USN is not valid (value: %s)\n", last_usn_value);
                         so->last_usn = 0;
diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c
index 2a12e59b74..44cec84adb 100644
--- a/src/providers/ldap/sdap_async_enum.c
+++ b/src/providers/ldap/sdap_async_enum.c
@@ -571,9 +571,9 @@ static void enum_users_done(struct tevent_req *subreq)
         talloc_zfree(state->ctx->srv_opts->max_user_value);
         state->ctx->srv_opts->max_user_value =
                                         talloc_steal(state->ctx, usn_value);
-
+        errno = 0;
         usn_number = strtoul(usn_value, &endptr, 10);
-        if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
+        if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
             && (usn_number > state->ctx->srv_opts->last_usn)) {
             state->ctx->srv_opts->last_usn = usn_number;
         }
@@ -751,8 +751,9 @@ static void enum_groups_done(struct tevent_req *subreq)
         talloc_zfree(state->ctx->srv_opts->max_group_value);
         state->ctx->srv_opts->max_group_value =
                                         talloc_steal(state->ctx, usn_value);
+        errno = 0;
         usn_number = strtoul(usn_value, &endptr, 10);
-        if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
+        if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
             && (usn_number > state->ctx->srv_opts->last_usn)) {
             state->ctx->srv_opts->last_usn = usn_number;
         }
diff --git a/src/providers/ldap/sdap_async_iphost.c b/src/providers/ldap/sdap_async_iphost.c
index e798a32c26..33b8e21672 100644
--- a/src/providers/ldap/sdap_async_iphost.c
+++ b/src/providers/ldap/sdap_async_iphost.c
@@ -618,9 +618,9 @@ enum_iphosts_op_done(struct tevent_req *subreq)
         talloc_zfree(state->id_ctx->srv_opts->max_iphost_value);
         state->id_ctx->srv_opts->max_iphost_value =
                 talloc_steal(state->id_ctx, usn_value);
-
+        errno = 0;
         usn_number = strtoul(usn_value, &endptr, 10);
-        if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
+        if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
             && (usn_number > state->id_ctx->srv_opts->last_usn)) {
             state->id_ctx->srv_opts->last_usn = usn_number;
         }
diff --git a/src/providers/ldap/sdap_async_ipnetwork.c b/src/providers/ldap/sdap_async_ipnetwork.c
index e34bf58d4a..e057566c16 100644
--- a/src/providers/ldap/sdap_async_ipnetwork.c
+++ b/src/providers/ldap/sdap_async_ipnetwork.c
@@ -603,9 +603,9 @@ enum_ipnetworks_op_done(struct tevent_req *subreq)
         talloc_zfree(state->id_ctx->srv_opts->max_ipnetwork_value);
         state->id_ctx->srv_opts->max_ipnetwork_value =
                 talloc_steal(state->id_ctx, usn_value);
-
+        errno = 0;
         usn_number = strtoul(usn_value, &endptr, 10);
-        if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
+        if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
             && (usn_number > state->id_ctx->srv_opts->last_usn)) {
             state->id_ctx->srv_opts->last_usn = usn_number;
         }
diff --git a/src/providers/ldap/sdap_async_services.c b/src/providers/ldap/sdap_async_services.c
index eebe239133..cccc4f94c2 100644
--- a/src/providers/ldap/sdap_async_services.c
+++ b/src/providers/ldap/sdap_async_services.c
@@ -623,9 +623,9 @@ enum_services_op_done(struct tevent_req *subreq)
         talloc_zfree(state->id_ctx->srv_opts->max_service_value);
         state->id_ctx->srv_opts->max_service_value =
                 talloc_steal(state->id_ctx, usn_value);
-
+        errno = 0;
         usn_number = strtoul(usn_value, &endptr, 10);
-        if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
+        if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
             && (usn_number > state->id_ctx->srv_opts->last_usn)) {
             state->id_ctx->srv_opts->last_usn = usn_number;
         }
diff --git a/src/util/crypto/libcrypto/crypto_sha512crypt.c b/src/util/crypto/libcrypto/crypto_sha512crypt.c
index 1e57b04d13..c816d26f18 100644
--- a/src/util/crypto/libcrypto/crypto_sha512crypt.c
+++ b/src/util/crypto/libcrypto/crypto_sha512crypt.c
@@ -101,8 +101,9 @@ static int sha512_crypt_r(const char *key,
         char *endp;
 
         num = salt + ROUNDS_SIZE;
+        errno = 0;
         srounds = strtoul(num, &endp, 10);
-        if (*endp == '$') {
+        if (!errno && (*endp == '$')) {
             salt = endp + 1;
             if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
             if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;

From b9757be3a3d1a94f607bda5f94581cba47cd1b22 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Fri, 15 Oct 2021 22:30:21 +0200
Subject: [PATCH 4/4] TESTS: fixed a bug in define->string conversion

Previously result of `AS_STR(OFFLINE_TIMEOUT)` was "OFFLINE_TIMEOUT"
instead of expected integer value.
---
 src/tests/cmocka/test_data_provider_be.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/tests/cmocka/test_data_provider_be.c b/src/tests/cmocka/test_data_provider_be.c
index a6d6ec8802..49f04ddfb0 100644
--- a/src/tests/cmocka/test_data_provider_be.c
+++ b/src/tests/cmocka/test_data_provider_be.c
@@ -32,7 +32,8 @@
 #define TEST_ID_PROVIDER "ldap"
 
 #define OFFLINE_TIMEOUT 2
-#define AS_STR(param) (#param)
+#define STR_HELPER(x) #x
+#define AS_STR(param) STR_HELPER(param)
 
 static TALLOC_CTX *global_mock_context = NULL;
 static bool global_timer_added;
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to