220 lines
8.4 KiB
Diff
220 lines
8.4 KiB
Diff
|
From d0ad557eef9bcdf475b15e40f8f80e3827d3c630 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
||
|
Date: Fri, 4 Mar 2016 12:10:35 +0100
|
||
|
Subject: [PATCH 108/108] SUDO: be able to parse modifyTimestamp correctly
|
||
|
|
||
|
We were unable to parse modifyTimestamp where a non-numeric part
|
||
|
(timezone) was involved. The format is YYYYMMDDHHmmssZ. It may
|
||
|
also contain fraction or different timezone, everytime separated
|
||
|
from the datetime by character. This patch gets the numberic part
|
||
|
and then appends the string part again to get value usable in filter.
|
||
|
|
||
|
Resolves:
|
||
|
https://fedorahosted.org/sssd/ticket/2970
|
||
|
|
||
|
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
||
|
(cherry picked from commit ef5e33f7db1e314226b0077596e38ef16305cba5)
|
||
|
(cherry picked from commit 35c8d4f76c9299105cbc6a6d2c49170e46f2abde)
|
||
|
---
|
||
|
src/providers/ipa/ipa_sudo_refresh.c | 24 ++++++++---------
|
||
|
src/providers/ldap/sdap.h | 2 +-
|
||
|
src/providers/ldap/sdap_sudo_refresh.c | 17 ++++++------
|
||
|
src/providers/ldap/sdap_sudo_shared.c | 48 ++++++++++++++++++++++++++++------
|
||
|
4 files changed, 62 insertions(+), 29 deletions(-)
|
||
|
|
||
|
diff --git a/src/providers/ipa/ipa_sudo_refresh.c b/src/providers/ipa/ipa_sudo_refresh.c
|
||
|
index 7871802ef7462ce98f6ff43bc33da57ff123ff6f..e7219d3147c860a0162bfe8e5004fe6d22de7f25 100644
|
||
|
--- a/src/providers/ipa/ipa_sudo_refresh.c
|
||
|
+++ b/src/providers/ipa/ipa_sudo_refresh.c
|
||
|
@@ -153,7 +153,7 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
struct tevent_req *req;
|
||
|
char *cmdgroups_filter;
|
||
|
char *search_filter;
|
||
|
- unsigned long usn;
|
||
|
+ const char *usn;
|
||
|
errno_t ret;
|
||
|
|
||
|
req = tevent_req_create(mem_ctx, &state,
|
||
|
@@ -166,29 +166,29 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
/* Download all rules from LDAP that are newer than usn */
|
||
|
if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
|
||
|
DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
|
||
|
- usn = 0;
|
||
|
+ usn = "0";
|
||
|
+ search_filter = NULL;
|
||
|
} else {
|
||
|
- usn = srv_opts->max_sudo_value + 1;
|
||
|
+ usn = srv_opts->max_sudo_value;
|
||
|
+ search_filter = talloc_asprintf(state, "(%s>=%s)",
|
||
|
+ sudo_ctx->sudorule_map[IPA_AT_SUDORULE_ENTRYUSN].name, usn);
|
||
|
+ if (search_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
- cmdgroups_filter = talloc_asprintf(state, "(%s>=%lu)",
|
||
|
+ cmdgroups_filter = talloc_asprintf(state, "(%s>=%s)",
|
||
|
sudo_ctx->sudocmdgroup_map[IPA_AT_SUDOCMDGROUP_ENTRYUSN].name, usn);
|
||
|
if (cmdgroups_filter == NULL) {
|
||
|
ret = ENOMEM;
|
||
|
goto immediately;
|
||
|
}
|
||
|
|
||
|
- search_filter = talloc_asprintf(state, "(%s>=%lu)",
|
||
|
- sudo_ctx->sudorule_map[IPA_AT_SUDORULE_ENTRYUSN].name, usn);
|
||
|
- if (search_filter == NULL) {
|
||
|
- ret = ENOMEM;
|
||
|
- goto immediately;
|
||
|
- }
|
||
|
-
|
||
|
/* Do not remove any rules that are already in the sysdb. */
|
||
|
|
||
|
DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
|
||
|
- "(USN > %lu)\n", usn);
|
||
|
+ "(USN >= %s)\n", usn);
|
||
|
|
||
|
subreq = ipa_sudo_refresh_send(state, ev, sudo_ctx, cmdgroups_filter,
|
||
|
search_filter, NULL);
|
||
|
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
|
||
|
index e0e05da0c8270a8f131870bc755da862e43783cb..44b8cfb1c971e059db5d8a12613db9c0e67d13a6 100644
|
||
|
--- a/src/providers/ldap/sdap.h
|
||
|
+++ b/src/providers/ldap/sdap.h
|
||
|
@@ -485,7 +485,7 @@ struct sdap_server_opts {
|
||
|
char *max_user_value;
|
||
|
char *max_group_value;
|
||
|
char *max_service_value;
|
||
|
- unsigned long max_sudo_value;
|
||
|
+ char *max_sudo_value;
|
||
|
bool posix_checked;
|
||
|
};
|
||
|
|
||
|
diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c
|
||
|
index 5ba858019e0bda91a9e0919ed2b0345d9faf085e..62a97dd12cd8b92f719494f173d028cb7c66928c 100644
|
||
|
--- a/src/providers/ldap/sdap_sudo_refresh.c
|
||
|
+++ b/src/providers/ldap/sdap_sudo_refresh.c
|
||
|
@@ -167,7 +167,7 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
struct sdap_server_opts *srv_opts = id_ctx->srv_opts;
|
||
|
struct sdap_sudo_smart_refresh_state *state = NULL;
|
||
|
char *search_filter = NULL;
|
||
|
- unsigned long usn;
|
||
|
+ const char *usn;
|
||
|
int ret;
|
||
|
|
||
|
req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state);
|
||
|
@@ -182,14 +182,15 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
/* Download all rules from LDAP that are newer than usn */
|
||
|
if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
|
||
|
DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
|
||
|
- usn = 0;
|
||
|
+ usn = "0";
|
||
|
+ search_filter = talloc_asprintf(state, "(objectclass=%s)",
|
||
|
+ map[SDAP_OC_SUDORULE].name);
|
||
|
} else {
|
||
|
- usn = srv_opts->max_sudo_value + 1;
|
||
|
+ usn = srv_opts->max_sudo_value;
|
||
|
+ search_filter = talloc_asprintf(state, "(&(objectclass=%s)(%s>=%s))",
|
||
|
+ map[SDAP_OC_SUDORULE].name,
|
||
|
+ map[SDAP_AT_SUDO_USN].name, usn);
|
||
|
}
|
||
|
-
|
||
|
- search_filter = talloc_asprintf(state, "(&(objectclass=%s)(%s>=%lu))",
|
||
|
- map[SDAP_OC_SUDORULE].name,
|
||
|
- map[SDAP_AT_SUDO_USN].name, usn);
|
||
|
if (search_filter == NULL) {
|
||
|
ret = ENOMEM;
|
||
|
goto immediately;
|
||
|
@@ -199,7 +200,7 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
* sysdb_filter = NULL; */
|
||
|
|
||
|
DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
|
||
|
- "(USN > %lu)\n", usn);
|
||
|
+ "(USN >= %s)\n", usn);
|
||
|
|
||
|
subreq = sdap_sudo_refresh_send(state, sudo_ctx, search_filter, NULL);
|
||
|
if (subreq == NULL) {
|
||
|
diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
|
||
|
index 72f55e14baa8f8cf896205fb20f14d5f446cfb0a..b9e5182a2f11d56b5cff0b77fd83282654eae94c 100644
|
||
|
--- a/src/providers/ldap/sdap_sudo_shared.c
|
||
|
+++ b/src/providers/ldap/sdap_sudo_shared.c
|
||
|
@@ -120,11 +120,38 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
|
||
|
return EOK;
|
||
|
}
|
||
|
|
||
|
+static char *
|
||
|
+sdap_sudo_new_usn(TALLOC_CTX *mem_ctx,
|
||
|
+ unsigned long usn,
|
||
|
+ const char *leftover)
|
||
|
+{
|
||
|
+ const char *str = leftover == NULL ? "" : leftover;
|
||
|
+ char *newusn;
|
||
|
+
|
||
|
+ /* We increment USN number so that we can later use simplify filter
|
||
|
+ * (just usn >= last+1 instaed of usn >= last && usn != last).
|
||
|
+ */
|
||
|
+ usn++;
|
||
|
+
|
||
|
+ /* Convert back to string appending non-converted values since it
|
||
|
+ * is an indicator that modifyTimestamp is used instead of entryUSN.
|
||
|
+ * modifyTimestamp contains also timezone specification, usually Z.
|
||
|
+ * We can't really handle any errors here so we just use what we got. */
|
||
|
+ newusn = talloc_asprintf(mem_ctx, "%lu%s", usn, str);
|
||
|
+ if (newusn == NULL) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return newusn;
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
|
||
|
const char *usn)
|
||
|
{
|
||
|
- unsigned int usn_number;
|
||
|
+ unsigned long usn_number;
|
||
|
+ char *newusn;
|
||
|
char *endptr = NULL;
|
||
|
errno_t ret;
|
||
|
|
||
|
@@ -140,24 +167,29 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
|
||
|
|
||
|
errno = 0;
|
||
|
usn_number = strtoul(usn, &endptr, 10);
|
||
|
- if (endptr != NULL && *endptr != '\0') {
|
||
|
- DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert USN %s\n", usn);
|
||
|
- return;
|
||
|
- } else if (errno != 0) {
|
||
|
+ if (errno != 0) {
|
||
|
ret = errno;
|
||
|
DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert USN %s [%d]: %s\n",
|
||
|
usn, ret, sss_strerror(ret));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- if (usn_number > srv_opts->max_sudo_value) {
|
||
|
- srv_opts->max_sudo_value = usn_number;
|
||
|
+ newusn = sdap_sudo_new_usn(srv_opts, usn_number, endptr);
|
||
|
+ if (newusn == NULL) {
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (sysdb_compare_usn(newusn, srv_opts->max_sudo_value) > 0) {
|
||
|
+ talloc_zfree(srv_opts->max_sudo_value);
|
||
|
+ srv_opts->max_sudo_value = newusn;
|
||
|
+ } else {
|
||
|
+ talloc_zfree(newusn);
|
||
|
}
|
||
|
|
||
|
if (usn_number > srv_opts->last_usn) {
|
||
|
srv_opts->last_usn = usn_number;
|
||
|
}
|
||
|
|
||
|
- DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%lu]\n",
|
||
|
+ DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%s]\n",
|
||
|
srv_opts->max_sudo_value);
|
||
|
}
|
||
|
--
|
||
|
2.7.3
|
||
|
|