Blame SOURCES/0009-extdom-unify-error-code-handling-especially-LDAP_NO_SUCH_OBJECT_rhbz#1741530.patch

e8574e
From 3bb72545fc337564e0843b0c72906a9a1e3f6a06 Mon Sep 17 00:00:00 2001
e8574e
From: Sumit Bose <sbose@redhat.com>
e8574e
Date: Fri, 14 Jun 2019 11:13:54 +0200
e8574e
Subject: [PATCH] extdom: unify error code handling especially
e8574e
 LDAP_NO_SUCH_OBJECT
e8574e
e8574e
A return code LDAP_NO_SUCH_OBJECT will tell SSSD on the IPA client to
e8574e
remove the searched object from the cache. As a consequence
e8574e
LDAP_NO_SUCH_OBJECT should only be returned if the object really does
e8574e
not exists otherwise the data of existing objects might be removed form
e8574e
the cache of the clients causing unexpected behaviour like
e8574e
authentication errors.
e8574e
e8574e
Currently some code-paths use LDAP_NO_SUCH_OBJECT as default error code.
e8574e
With this patch LDAP_NO_SUCH_OBJECT is only returned if the related
e8574e
lookup functions return ENOENT. Timeout related error code will lead to
e8574e
LDAP_TIMELIMIT_EXCEEDED and LDAP_OPERATIONS_ERROR is used as default
e8574e
error code.
e8574e
e8574e
Fixes: https://pagure.io/freeipa/issue/8044
e8574e
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
e8574e
---
e8574e
 .../ipa-extdom-extop/back_extdom_sss_idmap.c  |  4 +-
e8574e
 .../ipa-extdom-extop/ipa_extdom_common.c      | 77 ++++++++++++++-----
e8574e
 .../ipa-extdom-extop/ipa_extdom_extop.c       |  2 +
e8574e
 3 files changed, 61 insertions(+), 22 deletions(-)
e8574e
e8574e
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c
e8574e
index ef552a9a37..163e8e1371 100644
e8574e
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c
e8574e
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c
e8574e
@@ -62,10 +62,10 @@ static enum nss_status __convert_sss_nss2nss_status(int errcode) {
e8574e
         return NSS_STATUS_SUCCESS;
e8574e
     case ENOENT:
e8574e
         return NSS_STATUS_NOTFOUND;
e8574e
-    case ETIME:
e8574e
-        /* fall-through */
e8574e
     case ERANGE:
e8574e
         return NSS_STATUS_TRYAGAIN;
e8574e
+    case ETIME:
e8574e
+        /* fall-through */
e8574e
     case ETIMEDOUT:
e8574e
         /* fall-through */
e8574e
     default:
e8574e
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
e8574e
index 525487c9e4..65c723ce65 100644
e8574e
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
e8574e
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
e8574e
@@ -523,7 +523,7 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
e8574e
         if (strcasecmp(locat+1, domain_name) == 0  ) {
e8574e
             locat[0] = '\0';
e8574e
         } else {
e8574e
-            ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            ret = LDAP_INVALID_SYNTAX;
e8574e
             goto done;
e8574e
         }
e8574e
     }
e8574e
@@ -568,10 +568,12 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
e8574e
             ret = getgrgid_r_wrapper(ctx,
e8574e
                                      groups[c], &grp, &buf, &buf_len);
e8574e
             if (ret != 0) {
e8574e
-                if (ret == ENOMEM || ret == ERANGE) {
e8574e
-                    ret = LDAP_OPERATIONS_ERROR;
e8574e
-                } else {
e8574e
+                if (ret == ENOENT) {
e8574e
                     ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                } else if (ret == ETIMEDOUT) {
e8574e
+                    ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
+                } else {
e8574e
+                    ret = LDAP_OPERATIONS_ERROR;
e8574e
                 }
e8574e
                 goto done;
e8574e
             }
e8574e
@@ -634,7 +636,7 @@ int pack_ber_group(enum response_types response_type,
e8574e
         if (strcasecmp(locat+1, domain_name) == 0  ) {
e8574e
             locat[0] = '\0';
e8574e
         } else {
e8574e
-            ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            ret = LDAP_INVALID_SYNTAX;
e8574e
             goto done;
e8574e
         }
e8574e
     }
e8574e
@@ -836,6 +838,8 @@ static int handle_uid_request(struct ipa_extdom_ctx *ctx,
e8574e
                             || id_type == SSS_ID_TYPE_BOTH)) {
e8574e
             if (ret == ENOENT) {
e8574e
                 ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
             } else {
e8574e
                 set_err_msg(req, "Failed to lookup SID by UID");
e8574e
                 ret = LDAP_OPERATIONS_ERROR;
e8574e
@@ -847,10 +851,12 @@ static int handle_uid_request(struct ipa_extdom_ctx *ctx,
e8574e
     } else {
e8574e
         ret = getpwuid_r_wrapper(ctx, uid, &pwd, &buf, &buf_len);
e8574e
         if (ret != 0) {
e8574e
-            if (ret == ENOMEM || ret == ERANGE) {
e8574e
-                ret = LDAP_OPERATIONS_ERROR;
e8574e
-            } else {
e8574e
+            if (ret == ENOENT) {
e8574e
                 ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            } else if (ret == ETIMEDOUT) {
e8574e
+                ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
+            } else {
e8574e
+                ret = LDAP_OPERATIONS_ERROR;
e8574e
             }
e8574e
             goto done;
e8574e
         }
e8574e
@@ -862,6 +868,8 @@ static int handle_uid_request(struct ipa_extdom_ctx *ctx,
e8574e
                 set_err_msg(req, "Failed to read original data");
e8574e
                 if (ret == ENOENT) {
e8574e
                     ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                    ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
                 } else {
e8574e
                     ret = LDAP_OPERATIONS_ERROR;
e8574e
                 }
e8574e
@@ -907,6 +915,8 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
e8574e
         if (ret != 0 || id_type != SSS_ID_TYPE_GID) {
e8574e
             if (ret == ENOENT) {
e8574e
                 ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
             } else {
e8574e
                 set_err_msg(req, "Failed to lookup SID by GID");
e8574e
                 ret = LDAP_OPERATIONS_ERROR;
e8574e
@@ -918,10 +928,12 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
e8574e
     } else {
e8574e
         ret = getgrgid_r_wrapper(ctx, gid, &grp, &buf, &buf_len);
e8574e
         if (ret != 0) {
e8574e
-            if (ret == ENOMEM || ret == ERANGE) {
e8574e
-                ret = LDAP_OPERATIONS_ERROR;
e8574e
-            } else {
e8574e
+            if (ret == ENOENT) {
e8574e
                 ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            } else if (ret == ETIMEDOUT) {
e8574e
+                ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
+            } else {
e8574e
+                ret = LDAP_OPERATIONS_ERROR;
e8574e
             }
e8574e
             goto done;
e8574e
         }
e8574e
@@ -933,6 +945,8 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
e8574e
                 set_err_msg(req, "Failed to read original data");
e8574e
                 if (ret == ENOENT) {
e8574e
                     ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                    ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
                 } else {
e8574e
                     ret = LDAP_OPERATIONS_ERROR;
e8574e
                 }
e8574e
@@ -976,6 +990,8 @@ static int handle_cert_request(struct ipa_extdom_ctx *ctx,
e8574e
     if (ret != 0) {
e8574e
         if (ret == ENOENT) {
e8574e
             ret = LDAP_NO_SUCH_OBJECT;
e8574e
+        } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+            ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
         } else {
e8574e
             set_err_msg(req, "Failed to lookup name by certificate");
e8574e
             ret = LDAP_OPERATIONS_ERROR;
e8574e
@@ -1020,6 +1036,8 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
e8574e
     if (ret != 0) {
e8574e
         if (ret == ENOENT) {
e8574e
             ret = LDAP_NO_SUCH_OBJECT;
e8574e
+        } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+            ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
         } else {
e8574e
             set_err_msg(req, "Failed to lookup name by SID");
e8574e
             ret = LDAP_OPERATIONS_ERROR;
e8574e
@@ -1057,10 +1075,12 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
e8574e
     case SSS_ID_TYPE_BOTH:
e8574e
         ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len);
e8574e
         if (ret != 0) {
e8574e
-            if (ret == ENOMEM || ret == ERANGE) {
e8574e
-                ret = LDAP_OPERATIONS_ERROR;
e8574e
-            } else {
e8574e
+            if (ret == ENOENT) {
e8574e
                 ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            } else if (ret == ETIMEDOUT) {
e8574e
+                ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
+            } else {
e8574e
+                ret = LDAP_OPERATIONS_ERROR;
e8574e
             }
e8574e
             goto done;
e8574e
         }
e8574e
@@ -1072,6 +1092,8 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
e8574e
                 set_err_msg(req, "Failed to read original data");
e8574e
                 if (ret == ENOENT) {
e8574e
                     ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                    ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
                 } else {
e8574e
                     ret = LDAP_OPERATIONS_ERROR;
e8574e
                 }
e8574e
@@ -1089,10 +1111,12 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
e8574e
     case SSS_ID_TYPE_GID:
e8574e
         ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len);
e8574e
         if (ret != 0) {
e8574e
-            if (ret == ENOMEM || ret == ERANGE) {
e8574e
-                ret = LDAP_OPERATIONS_ERROR;
e8574e
-            } else {
e8574e
+            if (ret == ENOENT) {
e8574e
                 ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            } else if (ret == ETIMEDOUT) {
e8574e
+                ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
+            } else {
e8574e
+                ret = LDAP_OPERATIONS_ERROR;
e8574e
             }
e8574e
             goto done;
e8574e
         }
e8574e
@@ -1104,6 +1128,8 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
e8574e
                 set_err_msg(req, "Failed to read original data");
e8574e
                 if (ret == ENOENT) {
e8574e
                     ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                    ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
                 } else {
e8574e
                     ret = LDAP_OPERATIONS_ERROR;
e8574e
                 }
e8574e
@@ -1167,6 +1193,8 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
e8574e
         if (ret != 0) {
e8574e
             if (ret == ENOENT) {
e8574e
                 ret = LDAP_NO_SUCH_OBJECT;
e8574e
+            } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
             } else {
e8574e
                 set_err_msg(req, "Failed to lookup SID by name");
e8574e
                 ret = LDAP_OPERATIONS_ERROR;
e8574e
@@ -1190,6 +1218,8 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
e8574e
                     set_err_msg(req, "Failed to read original data");
e8574e
                     if (ret == ENOENT) {
e8574e
                         ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                    } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                        ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
                     } else {
e8574e
                         ret = LDAP_OPERATIONS_ERROR;
e8574e
                     }
e8574e
@@ -1205,6 +1235,9 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
e8574e
         } else if (ret == ENOMEM || ret == ERANGE) {
e8574e
             ret = LDAP_OPERATIONS_ERROR;
e8574e
             goto done;
e8574e
+        } else if (ret == ETIMEDOUT) {
e8574e
+            ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
+            goto done;
e8574e
         } else { /* no user entry found */
e8574e
             /* according to the getpwnam() man page there are a couple of
e8574e
              * error codes which can indicate that the user was not found. To
e8574e
@@ -1212,10 +1245,12 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
e8574e
              * errors. */
e8574e
             ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len);
e8574e
             if (ret != 0) {
e8574e
-                if (ret == ENOMEM || ret == ERANGE) {
e8574e
-                    ret = LDAP_OPERATIONS_ERROR;
e8574e
-                } else {
e8574e
+                if (ret == ENOENT) {
e8574e
                     ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                } else if (ret == ETIMEDOUT) {
e8574e
+                    ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
+                } else {
e8574e
+                    ret = LDAP_OPERATIONS_ERROR;
e8574e
                 }
e8574e
                 goto done;
e8574e
             }
e8574e
@@ -1226,6 +1261,8 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
e8574e
                                     || id_type == SSS_ID_TYPE_BOTH)) {
e8574e
                     if (ret == ENOENT) {
e8574e
                         ret = LDAP_NO_SUCH_OBJECT;
e8574e
+                    } else if (ret == ETIMEDOUT || ret == ETIME) {
e8574e
+                        ret = LDAP_TIMELIMIT_EXCEEDED;
e8574e
                     } else {
e8574e
                         set_err_msg(req, "Failed to read original data");
e8574e
                         ret = LDAP_OPERATIONS_ERROR;
e8574e
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
e8574e
index 10d3f86eba..48fcecc1ee 100644
e8574e
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
e8574e
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
e8574e
@@ -242,6 +242,8 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
e8574e
     if (ret != LDAP_SUCCESS) {
e8574e
         if (ret == LDAP_NO_SUCH_OBJECT) {
e8574e
             rc = LDAP_NO_SUCH_OBJECT;
e8574e
+        } else if (ret == LDAP_TIMELIMIT_EXCEEDED) {
e8574e
+            rc = LDAP_TIMELIMIT_EXCEEDED;
e8574e
         } else {
e8574e
             rc = LDAP_OPERATIONS_ERROR;
e8574e
             err_msg = "Failed to handle the request.\n";
e8574e
From 0ead6f59732e8b3370c5d8d05acd29f2d56c52bb Mon Sep 17 00:00:00 2001
e8574e
From: Alexander Bokovoy <abokovoy@redhat.com>
e8574e
Date: Mon, 19 Aug 2019 10:15:50 +0300
e8574e
Subject: [PATCH] ipa-extdom-extop: test timed out getgrgid_r
e8574e
e8574e
Simulate getgrgid_r() timeout when packing list of groups user is a
e8574e
member of in pack_ber_user().
e8574e
e8574e
Related: https://pagure.io/freeipa/issue/8044
e8574e
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
e8574e
---
e8574e
 .../ipa_extdom_cmocka_tests.c                 | 29 +++++++++++++++++++
e8574e
 1 file changed, 29 insertions(+)
e8574e
e8574e
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c
e8574e
index 29699cfa39..1fa4c6af82 100644
e8574e
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c
e8574e
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c
e8574e
@@ -493,6 +493,34 @@ void test_set_err_msg(void **state)
e8574e
 #define TEST_SID "S-1-2-3-4"
e8574e
 #define TEST_DOMAIN_NAME "DOMAIN"
e8574e
 
e8574e
+/* Always time out for test */
e8574e
+static
e8574e
+enum nss_status getgrgid_r_timeout(gid_t gid, struct group *result,
e8574e
+                                   char *buffer, size_t buflen, int *errnop) {
e8574e
+    return NSS_STATUS_UNAVAIL;
e8574e
+}
e8574e
+
e8574e
+void test_pack_ber_user_timeout(void **state)
e8574e
+{
e8574e
+    int ret;
e8574e
+    struct berval *resp_val = NULL;
e8574e
+    struct test_data *test_data;
e8574e
+    enum nss_status (*oldgetgrgid_r)(gid_t gid, struct group *result,
e8574e
+                                     char *buffer, size_t buflen, int *errnop);
e8574e
+
e8574e
+    test_data = (struct test_data *) *state;
e8574e
+
e8574e
+    oldgetgrgid_r = test_data->ctx->nss_ctx->getgrgid_r;
e8574e
+    test_data->ctx->nss_ctx->getgrgid_r = getgrgid_r_timeout;
e8574e
+
e8574e
+    ret = pack_ber_user(test_data->ctx, RESP_USER_GROUPLIST,
e8574e
+                        TEST_DOMAIN_NAME, "member001", 12345, 54321,
e8574e
+                        "gecos", "homedir", "shell", NULL, &resp_val);
e8574e
+    test_data->ctx->nss_ctx->getgrgid_r = oldgetgrgid_r;
e8574e
+    assert_int_equal(ret, LDAP_TIMELIMIT_EXCEEDED);
e8574e
+    ber_bvfree(resp_val);
e8574e
+}
e8574e
+
e8574e
 char res_sid[] = {0x30, 0x0e, 0x0a, 0x01, 0x01, 0x04, 0x09, 0x53, 0x2d, 0x31, \
e8574e
                   0x2d, 0x32, 0x2d, 0x33, 0x2d, 0x34};
e8574e
 char res_nam[] = {0x30, 0x13, 0x0a, 0x01, 0x02, 0x30, 0x0e, 0x04, 0x06, 0x44, \
e8574e
@@ -614,6 +642,7 @@ void test_decode(void **state)
e8574e
 int main(int argc, const char *argv[])
e8574e
 {
e8574e
     const struct CMUnitTest tests[] = {
e8574e
+        cmocka_unit_test(test_pack_ber_user_timeout),
e8574e
         cmocka_unit_test(test_getpwnam_r_wrapper),
e8574e
         cmocka_unit_test(test_getpwuid_r_wrapper),
e8574e
         cmocka_unit_test(test_getgrnam_r_wrapper),