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

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