config UPDATE share clients between endpoints
diff --git a/src/server_config.c b/src/server_config.c
index 4221741..4d4191c 100644
--- a/src/server_config.c
+++ b/src/server_config.c
@@ -275,6 +275,13 @@
 }
 
 static void
+nc_server_config_del_endpt_reference(struct nc_endpt *endpt)
+{
+    free(endpt->referenced_endpt_name);
+    endpt->referenced_endpt_name = NULL;
+}
+
+static void
 nc_server_config_del_local_address(struct nc_bind *bind)
 {
     free(bind->address);
@@ -447,6 +454,7 @@
 nc_server_config_del_endpt_ssh(struct nc_endpt *endpt, struct nc_bind *bind)
 {
     nc_server_config_del_endpt_name(endpt);
+    nc_server_config_del_endpt_reference(endpt);
     nc_server_config_del_ssh(bind, endpt->opts.ssh);
 
     server_opts.endpt_count--;
@@ -491,14 +499,15 @@
 int
 nc_server_config_listen(struct lyd_node *node, NC_OPERATION op)
 {
-    uint16_t i;
+    uint16_t i, endpt_count;
 
     (void) node;
 
     assert(op == NC_OP_CREATE || op == NC_OP_DELETE);
 
     if (op == NC_OP_DELETE) {
-        for (i = 0; i < server_opts.endpt_count; i++) {
+        endpt_count = server_opts.endpt_count;
+        for (i = 0; i < endpt_count; i++) {
             switch (server_opts.endpts[i].ti) {
 #ifdef NC_ENABLED_SSH
             case NC_TI_LIBSSH:
@@ -1912,6 +1921,129 @@
     return ret;
 }
 
+/**
+ * @brief Set all endpoint client auth references, which couldn't be set beforehand.
+ *
+ * The references that could not be set are those, which reference endpoints, which
+ * lie below the given endpoint in the YANG data (because of DFS tree parsing).
+ *
+ * @return 0 on success, 1 on error.
+ */
+static int
+nc_server_config_fill_endpt_client_auth(void)
+{
+    uint16_t i, j;
+
+    for (i = 0; i < server_opts.endpt_count; i++) {
+        /* go through all the endpoint */
+        if (server_opts.endpts[i].referenced_endpt_name) {
+            /* endpt has a reference, that hasn't been set yet */
+            for (j = i + 1; j < server_opts.endpt_count; j++) {
+                /* go through all the remaining endpts */
+                if (!strcmp(server_opts.endpts[i].referenced_endpt_name, server_opts.endpts[j].name)) {
+                    /* found the endpoint we were looking for */
+                    if (server_opts.endpts[i].ti == NC_TI_LIBSSH) {
+                        server_opts.endpts[i].opts.ssh->endpt_client_ref = &server_opts.endpts[j];
+                        break;
+                    } else {
+                        ERRINT;
+                        return 1;
+                    }
+                }
+            }
+
+            /* didn't find the endpoint */
+            if (j == server_opts.endpt_count) {
+                ERR(NULL, "Endpoint \"%s\" referenced by \"%s\" not found.",
+                        server_opts.endpts[i].referenced_endpt_name, server_opts.endpts[i].name);
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int
+nc_server_config_endpoint_client_auth_has_cycle(struct nc_endpt *original, struct nc_endpt *next, NC_TRANSPORT_IMPL transport)
+{
+    if (transport == NC_TI_LIBSSH) {
+        if (next->opts.ssh->endpt_client_ref) {
+            if (next->opts.ssh->endpt_client_ref == original) {
+                return 1;
+            } else {
+                return nc_server_config_endpoint_client_auth_has_cycle(original, next->opts.ssh->endpt_client_ref, NC_TI_LIBSSH);
+            }
+        } else {
+            return 0;
+        }
+    } else {
+        ERRINT;
+        return 1;
+    }
+}
+
+static int
+nc_server_config_endpoint_client_auth(const struct lyd_node *node, NC_OPERATION op)
+{
+    int ret = 0;
+    uint16_t i;
+    const char *endpt_name;
+    struct nc_endpt *endpt;
+
+    assert(!strcmp(LYD_NAME(node), "endpoint-client-auth"));
+
+    /* get current endpoint */
+    ret = nc_server_config_get_endpt(node, &endpt, NULL);
+    if (ret) {
+        goto cleanup;
+    }
+
+    if (op == NC_OP_DELETE) {
+        endpt->opts.ssh->endpt_client_ref = NULL;
+        goto cleanup;
+    }
+
+    /* find the endpoint leafref is referring to */
+    endpt_name = lyd_get_value(node);
+    for (i = 0; i < server_opts.endpt_count; i++) {
+        if (!strcmp(endpt_name, server_opts.endpts[i].name)) {
+            break;
+        }
+    }
+
+    if (i == server_opts.endpt_count) {
+        /* endpt not found, save the name and try to look it up later */
+        endpt->referenced_endpt_name = strdup(endpt_name);
+        if (!endpt->referenced_endpt_name) {
+            ERRMEM;
+            ret = 1;
+            goto cleanup;
+        }
+        goto cleanup;
+    }
+
+    /* check for self reference */
+    if (endpt == &server_opts.endpts[i]) {
+        ERR(NULL, "Self client authentication reference detected.");
+        ret = 1;
+        goto cleanup;
+    }
+
+    /* check for cyclic references */
+    ret = nc_server_config_endpoint_client_auth_has_cycle(endpt, &server_opts.endpts[i], endpt->ti);
+    if (ret) {
+        ERR(NULL, "Cyclic client authentication reference detected.");
+        goto cleanup;
+    }
+
+    /* assign the current endpt the referrenced endpt */
+    endpt->opts.ssh->endpt_client_ref = &server_opts.endpts[i];
+
+cleanup:
+    return ret;
+}
+
 static int
 nc_server_config_parse_netconf_server(const struct lyd_node *node, NC_OPERATION op)
 {
@@ -2033,6 +2165,10 @@
         if (nc_server_config_unix_socket(node, op)) {
             goto error;
         }
+    } else if (!strcmp(name, "endpoint-client-auth")) {
+        if (nc_server_config_endpoint_client_auth(node, op)) {
+            goto error;
+        }
     } else if (!strcmp(name, "cert-data")) {} else if (!strcmp(name, "expiration-date")) {} else if (!strcmp(name, "asymmetric-key")) {} else if (!strcmp(name, "certificate")) {} else if (!strcmp(name, "key-format")) {} else if (!strcmp(name,
             "cleartext-key")) {} else if (!strcmp(name, "hidden-key")) {} else if (!strcmp(name, "id_hint")) {} else if (!strcmp(name, "external-identity")) {} else if (!strcmp(name, "hash")) {} else if (!strcmp(name, "context")) {} else if (!strcmp(name,
             "target-protocol")) {} else if (!strcmp(name, "target-kdf")) {} else if (!strcmp(name, "client-authentication")) {} else if (!strcmp(name, "ca-certs")) {} else if (!strcmp(name, "ee-certs")) {} else if (!strcmp(name,
@@ -2048,7 +2184,7 @@
 }
 
 int
-nc_session_server_parse_tree(const struct lyd_node *node, NC_OPERATION parent_op, NC_MODULE module)
+nc_server_config_parse_tree(const struct lyd_node *node, NC_OPERATION parent_op, NC_MODULE module)
 {
     struct lyd_node *child;
     struct lyd_meta *m;
@@ -2103,7 +2239,7 @@
 
     if (current_op != NC_OP_DELETE) {
         LY_LIST_FOR(lyd_child(node), child) {
-            if (nc_session_server_parse_tree(child, current_op, module)) {
+            if (nc_server_config_parse_tree(child, current_op, module)) {
                 return 1;
             }
         }
@@ -2230,7 +2366,12 @@
         goto cleanup;
     }
 
-    if (nc_session_server_parse_tree(tree, op, NC_MODULE_NETCONF_SERVER)) {
+    if (nc_server_config_parse_tree(tree, op, NC_MODULE_NETCONF_SERVER)) {
+        ret = 1;
+        goto cleanup;
+    }
+
+    if (nc_server_config_fill_endpt_client_auth()) {
         ret = 1;
         goto cleanup;
     }
diff --git a/src/server_config_ks.c b/src/server_config_ks.c
index da00811..dfcb385 100644
--- a/src/server_config_ks.c
+++ b/src/server_config_ks.c
@@ -478,7 +478,7 @@
         goto cleanup;
     }
 
-    if (nc_session_server_parse_tree(tree, op, NC_MODULE_KEYSTORE)) {
+    if (nc_server_config_parse_tree(tree, op, NC_MODULE_KEYSTORE)) {
         ret = 1;
         goto cleanup;
     }
diff --git a/src/server_config_p.h b/src/server_config_p.h
index deaec67..7d5469d 100644
--- a/src/server_config_p.h
+++ b/src/server_config_p.h
@@ -106,7 +106,7 @@
  * @param[in] module Module for which to parse the data - either ietf-netconf-server, ietf-keystore or ietf-truststore
  * @return 0 on success, 1 on error.
  */
-int nc_session_server_parse_tree(const struct lyd_node *node, NC_OPERATION parent_op, NC_MODULE module);
+int nc_server_config_parse_tree(const struct lyd_node *node, NC_OPERATION parent_op, NC_MODULE module);
 
 /**
  * @brief Configures the listen subtree in the ietf-netconf-server module.
diff --git a/src/server_config_ts.c b/src/server_config_ts.c
index 12c4cdd..9b06ada 100644
--- a/src/server_config_ts.c
+++ b/src/server_config_ts.c
@@ -618,7 +618,7 @@
         goto cleanup;
     }
 
-    if (nc_session_server_parse_tree(tree, op, NC_MODULE_TRUSTSTORE)) {
+    if (nc_server_config_parse_tree(tree, op, NC_MODULE_TRUSTSTORE)) {
         ret = 1;
         goto cleanup;
     }
diff --git a/src/session_p.h b/src/session_p.h
index f6d07fa..6628a3d 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -208,6 +208,8 @@
     struct nc_client_auth *auth_clients;    /**< Server's authorized clients. */
     uint16_t client_count;                  /**< Number of server's authorized clients. */
 
+    struct nc_endpt *endpt_client_ref;      /**< Reference to another endpoint (used for client authentication). */
+
     char *hostkey_algs;                     /**< Hostkey algorithms supported by the server. */
     char *encryption_algs;                  /**< Encryption algorithms supported by the server. */
     char *kex_algs;                         /**< Key exchange algorithms supported by the server. */
@@ -419,7 +421,7 @@
     struct nc_bind *binds;
     struct nc_endpt {
         char *name;
-        int changed;
+        char *referenced_endpt_name;
         NC_TRANSPORT_IMPL ti;
         struct nc_keepalives ka;