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