areguera / rpms / ipa

Forked from rpms/ipa 5 years ago
Clone

Blame SOURCES/0001-extdom-unify-error-code-handling.patch

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