sssd/0009-strtonum-helpers-usage-sanitization.patch

404 lines
16 KiB
Diff
Raw Normal View History

From a2cc7daef2a1378aa12a21cd37a6369946e27bfc Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
Date: Fri, 15 Oct 2021 21:12:32 +0200
Subject: [PATCH 10/17] '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.
Reviewed-by: Pawel Polawski <ppolawsk@redhat.com>
---
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 3fe0ebf6c21a408228b572b2268d159eed6cfafc..3ba79ab3603d802c71dad24e994779019a0ced2f 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 8e4a0a50946296bf8281b5d80913a3a9fd7855d7..3d12472432708de8df0a872decbcea3dea6cbd99 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 6e7137a86a2edcebdc2d1f105cabdf9410a42db7..b5c6cfec9454ad4472f79ed8918b2d4d85640fb7 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 b0baf0e67ce5499aab8a2d87964d7ab1d45d3a55..56105ac2bdad22f20e8885dbc881d43e568530a9 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 46d4962585caca7d30df41d1dcf728360ca0a176..445b9ba2ff2ee2116409316a97f9783700af505b 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 e1090d03b32747ded0cfafa64571646db83103b1..50243098ae591f55e98c70cd7aa9248b973d6477 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 9b67773a8d2dd96e084eca8e091e36eba56bfa2f..51cebc8c9b176d37d08908ad3d53b22b373f55d6 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 638cb619b39f135307090dcf0f2c6ab2cc4119d0..52a15631842cb4f93c2d73cf6b72aca9c097a26b 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 8add97ba88c09f16e833aa145c57d9fbbff54f95..1b898d24488fb1d7decdf5c2488009a02116b0fd 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 d88def6fa91789fb023909535c3f81e32adf6144..44c3350db1e19f6bcaece3e91652c2d0dd6e843e 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 2f7bbeb06d8f063466db55121c7005b04116d4f7..856da09be970741b015ebfabf06cff3f15ab5ce4 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 7e145aa9b26a3298e572484a6998b579f50dd4f2..913dbcd8002e77ba48157c44671218a5042289d8 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 353f3a79f31517fe6daa1c2158ed463d2d4d9a81..14c58c74c34ff31e792b5c0d85644956e082cd42 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 ac9330858f0247ce0236d029b5d8678921c9061b..714f7ef78d4e3215b5dd80becaecb063caed860c 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 6de2e00a0194a3d62807a7754d6b7a55ae491acf..d27c2dfccde04401501fa4b37f22a3c96e6f6578 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 e8aeb315c9ed0efde15553e2d741d04c5d895b1a..41e6c3a51d0ff84ca9322d443eeccad1aa764ac0 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 1fbde2eb43b1cc4c6dead346a1dafc632a6ec78b..370a98b41740bb5494a10f93752daa40c6e445ff 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 1f9a7beea8086c6aa34a132e4df85edbf37aca55..0b51667a2a62702105c44ab2ba7594c7dbb18c91 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;
--
2.31.1