Blame SOURCES/0102-autofs-delete-possible-duplicate-of-an-autofs-entry.patch

8d3578
From 41606494979da8cb7fb09170687131a556a643c7 Mon Sep 17 00:00:00 2001
8d3578
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
8d3578
Date: Mon, 11 Nov 2019 13:56:34 +0100
8d3578
Subject: [PATCH 102/103] autofs: delete possible duplicate of an autofs entry
8d3578
8d3578
Steps to reproduce:
8d3578
1. Create the following autofs objects
8d3578
```ldif
8d3578
dn: ou=auto.master,ou=autofs,dc=ldap,dc=vm
8d3578
objectClass: automountMap
8d3578
objectClass: top
8d3578
ou: auto.master
8d3578
8d3578
dn: automountKey=/home,ou=auto.master,ou=autofs,dc=ldap,dc=vm
8d3578
objectClass: automount
8d3578
objectClass: top
8d3578
automountInformation: auto.home
8d3578
automountKey: /home
8d3578
8d3578
dn: ou=auto.home,ou=autofs,dc=ldap,dc=vm
8d3578
objectClass: automountMap
8d3578
objectClass: top
8d3578
ou: auto.home
8d3578
8d3578
dn: automountKey=/home1,ou=auto.home,ou=autofs,dc=ldap,dc=vm
8d3578
objectClass: automount
8d3578
objectClass: top
8d3578
automountInformation: home1
8d3578
automountKey: /home1
8d3578
```
8d3578
8d3578
2. Use e.g. the test tool to fetch the maps:
8d3578
```
8d3578
  ./autofs_test_client auto.master
8d3578
  ./autofs_test_client auto.home -n /home1
8d3578
```
8d3578
8d3578
3. Change automountInformation of /home1
8d3578
```
8d3578
dn: automountKey=/home1,ou=auto.home,ou=autofs,dc=ldap,dc=vm
8d3578
objectClass: automount
8d3578
objectClass: top
8d3578
automountInformation: home1_1
8d3578
automountKey: /home1
8d3578
```
8d3578
8d3578
4. Run the test tool again:
8d3578
```
8d3578
  ./autofs_test_client auto.master
8d3578
  ./autofs_test_client auto.home -n /home1
8d3578
  > error happens
8d3578
```
8d3578
8d3578
It is important the `get entry by name is called` thus the `-n` parameter.
8d3578
8d3578
Resolves:
8d3578
https://pagure.io/SSSD/sssd/issue/4116
8d3578
(cherry picked from commit 14b44e721c52207fd17e449cc6ae0a75fbb05369)
8d3578
---
8d3578
 src/providers/ldap/sdap_async_autofs.c | 93 ++++++++++++++++++++------
8d3578
 1 file changed, 74 insertions(+), 19 deletions(-)
8d3578
8d3578
diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c
8d3578
index 232d0c34a..6f37b1c84 100644
8d3578
--- a/src/providers/ldap/sdap_async_autofs.c
8d3578
+++ b/src/providers/ldap/sdap_async_autofs.c
8d3578
@@ -1337,6 +1337,12 @@ static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq)
8d3578
     tevent_req_set_callback(subreq, sdap_autofs_get_entry_done, req);
8d3578
 }
8d3578
 
8d3578
+static errno_t sdap_autofs_save_entry(struct sss_domain_info *domain,
8d3578
+                                      struct sdap_options *opts,
8d3578
+                                      struct sysdb_attrs *newentry,
8d3578
+                                      const char *mapname,
8d3578
+                                      const char *entryname);
8d3578
+
8d3578
 static void sdap_autofs_get_entry_done(struct tevent_req *subreq)
8d3578
 {
8d3578
     struct tevent_req *req;
8d3578
@@ -1365,31 +1371,18 @@ static void sdap_autofs_get_entry_done(struct tevent_req *subreq)
8d3578
         return;
8d3578
     }
8d3578
 
8d3578
-    if (reply_count == 0) {
8d3578
-        ret = sysdb_del_autofsentry_by_key(state->id_ctx->be->domain,
8d3578
-                                           state->mapname, state->entryname);
8d3578
-        if (ret != EOK) {
8d3578
-            DEBUG(SSSDBG_MINOR_FAILURE, "Cannot delete entry %s:%s\n",
8d3578
-                  state->mapname, state->entryname);
8d3578
-            tevent_req_error(req, ret);
8d3578
-            return;
8d3578
-        }
8d3578
-
8d3578
-        tevent_req_done(req);
8d3578
-        return;
8d3578
-    }
8d3578
-
8d3578
-    ret = add_autofs_entry(state->id_ctx->be->domain, state->mapname,
8d3578
-                           state->opts, reply[0], time(NULL));
8d3578
+    ret = sdap_autofs_save_entry(state->id_ctx->be->domain,
8d3578
+                                 state->opts,
8d3578
+                                 reply_count != 0 ? reply[0] : NULL,
8d3578
+                                 state->mapname,
8d3578
+                                 state->entryname);
8d3578
     if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_OP_FAILURE,
8d3578
-             "Cannot save autofs entry %s:%s [%d]: %s\n",
8d3578
-              state->mapname, state->entryname, ret, strerror(ret));
8d3578
         tevent_req_error(req, ret);
8d3578
         return;
8d3578
     }
8d3578
 
8d3578
     tevent_req_done(req);
8d3578
+    return;
8d3578
 }
8d3578
 
8d3578
 errno_t sdap_autofs_get_entry_recv(struct tevent_req *req,
8d3578
@@ -1405,3 +1398,65 @@ errno_t sdap_autofs_get_entry_recv(struct tevent_req *req,
8d3578
 
8d3578
     return EOK;
8d3578
 }
8d3578
+
8d3578
+static errno_t sdap_autofs_save_entry(struct sss_domain_info *domain,
8d3578
+                                      struct sdap_options *opts,
8d3578
+                                      struct sysdb_attrs *newentry,
8d3578
+                                      const char *mapname,
8d3578
+                                      const char *entryname)
8d3578
+{
8d3578
+    bool in_transaction = false;
8d3578
+    errno_t ret;
8d3578
+    int tret;
8d3578
+
8d3578
+    ret = sysdb_transaction_start(domain->sysdb);
8d3578
+    if (ret != EOK) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot start sysdb transaction [%d]: %s\n",
8d3578
+              ret, sss_strerror(ret));
8d3578
+        goto done;
8d3578
+    }
8d3578
+    in_transaction = true;
8d3578
+
8d3578
+    /* Delete existing entry to cover case where new entry has the same key
8d3578
+     * but different automountInformation. Because the dn is created from the
8d3578
+     * combination of key and information it would be possible to end up with
8d3578
+     * two entries with same key but different information otherwise.
8d3578
+     */
8d3578
+    ret = sysdb_del_autofsentry_by_key(domain, mapname, entryname);
8d3578
+    if (ret != EOK) {
8d3578
+        DEBUG(SSSDBG_MINOR_FAILURE, "Cannot delete entry %s:%s\n",
8d3578
+              mapname, entryname);
8d3578
+        goto done;
8d3578
+    }
8d3578
+
8d3578
+    if (newentry != NULL) {
8d3578
+        ret = add_autofs_entry(domain, mapname, opts, newentry, time(NULL));
8d3578
+        if (ret != EOK) {
8d3578
+            DEBUG(SSSDBG_OP_FAILURE,
8d3578
+                  "Cannot save autofs entry %s:%s [%d]: %s\n",
8d3578
+                  mapname, entryname, ret, sss_strerror(ret));
8d3578
+            goto done;
8d3578
+        }
8d3578
+    }
8d3578
+
8d3578
+    ret = sysdb_transaction_commit(domain->sysdb);
8d3578
+    if (ret != EOK) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot commit sysdb transaction [%d]: %s\n",
8d3578
+              ret, sss_strerror(ret));
8d3578
+        goto done;
8d3578
+    }
8d3578
+    in_transaction = false;
8d3578
+
8d3578
+    ret = EOK;
8d3578
+
8d3578
+done:
8d3578
+    if (in_transaction) {
8d3578
+        tret = sysdb_transaction_cancel(domain->sysdb);
8d3578
+        if (tret != EOK) {
8d3578
+            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot cancel sysdb transaction "
8d3578
+                  "[%d]: %s\n", ret, sss_strerror(ret));
8d3578
+        }
8d3578
+    }
8d3578
+
8d3578
+    return ret;
8d3578
+}
8d3578
-- 
8d3578
2.20.1
8d3578