src/server/daemon/ldap_resource.c

changeset 461
9b20b8f3582b
child 462
72848970541a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/daemon/ldap_resource.c	Sat Mar 11 11:56:55 2023 +0100
@@ -0,0 +1,213 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2023 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_resource.h"
+
+#include "../util/util.h"
+
+
+
+static ResourceType ldap_resource_type = {
+    (resource_pool_init_func)ldap_resourcepool_init,
+    (resource_pool_destroy_func)ldap_resourcepool_destroy,
+    (resource_pool_createresource_func)ldap_resourcepool_createresource,
+    (resource_pool_freeresource_func)ldap_resourcepool_freeresource,
+    (resource_pool_prepare_func)ldap_resourcepool_prepare,
+    (resource_pool_finish_func)ldap_resourcepool_finish,
+    (resource_pool_getresourcedata_func)ldap_resourcepool_getresourcedata
+};
+
+
+ResourceType* ldap_get_resource_type(void) {
+    return &ldap_resource_type;
+}
+
+LDAP* ws_ldap_resource_create_connection(
+        const char *hostname,
+        int port,
+        int ssl,
+        int ldap_version)
+{
+    LDAP *ld = NULL;
+    
+#ifdef SOLARIS
+    ld = ldap_init(config->hostname, config->port);
+    if(ld) {
+        ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
+    } else {
+        log_ereport(
+                LOG_FAILURE,
+                "ldap_resource_create_connection failed: host: %s port: %d",
+                hostname,
+                port);
+    }
+#else
+    char *ldap_uri = NULL;
+    asprintf(&ldap_uri, "ldap://%s:%d", hostname, port);
+    ld = ws_ldap_resource_create_uri_connection(ldap_uri, ldap_version);
+    free(ldap_uri);
+#endif
+    if(!ld) {
+        return NULL;
+    }
+    
+    return NULL;
+}
+
+LDAP* ws_ldap_resource_create_uri_connection(
+        const char *uri,
+        int ldap_version)
+{
+#ifdef SOLARIS
+    log_ereport(LOG_FAILURE, "ldap_resource_create_connection_uri is not implemented on Solaris yet");
+    return NULL;
+#else
+    
+    LDAP *ld = NULL;
+    int init_ret = ldap_initialize(&ld, uri);
+    if(init_ret) {
+        log_ereport(
+                LOG_FAILURE,
+                "ldap_resource_create_connection failed: uri: %s",
+                uri);
+    }
+    return ld;
+#endif
+}
+
+void ws_ldap_close(LDAP *ldap) {
+#ifdef SOLARIS
+    ldap_unbind(ldap);
+#else
+    ldap_unbind_ext_s(ldap, NULL, NULL);
+#endif
+}
+
+
+/*
+ * Validates settings from the pb pblock
+ * and creates an LDAPResourcePool object
+ * 
+ * LDAPResourcePool contains all settings necessary for creating
+ * ldap connections.
+ */
+void * ldap_resourcepool_init(pool_handle_t *pool, const char *rpname, pblock *pb) {
+    char *ldap_uri = pblock_findval("Uri", pb);
+    char *host = pblock_findval("Host", pb);
+    char *port = pblock_findval("Port", pb);
+    
+    if(!ldap_uri || !host) {
+        log_ereport(LOG_MISCONFIG, "Resource pool %s: No host or ldap uri specified", rpname);
+        return NULL;
+    }
+    if(ldap_uri && host) {
+        log_ereport(LOG_MISCONFIG, "Resource pool %s: Either Uri or Host must be specified, not both", rpname);
+        return NULL;
+    }
+    
+    int64_t port_i = 0;
+    if(host) {
+        if(port) {
+            if(util_strtoint(port, &port_i)) {
+                if(port_i < 1 || port_i > 65535) {
+                    log_ereport(LOG_MISCONFIG, "Resource pool %s: Port %s is out of range", rpname, port);
+                }
+            } else {
+                log_ereport(LOG_MISCONFIG, "Resource pool %s: Port '%s' is not a valid number", rpname, port);
+            }
+        } else {
+            port_i = LDAP_PORT;
+        }
+    }
+    
+    LDAPResourcePool *ldap_pool = pool_malloc(pool, sizeof(LDAPResourcePool));
+    if(!ldap_pool) {
+        return NULL;
+    }
+    
+    ldap_pool->name = rpname;
+    ldap_pool->pool = pool;
+    ldap_pool->ldap_uri = ldap_uri;
+    ldap_pool->host = host;
+    ldap_pool->port = (int)port_i;
+    
+    return ldap_pool;
+}
+
+void   ldap_resourcepool_destroy(LDAPResourcePool *pool) {
+    // unused
+}
+
+void * ldap_resourcepool_createresource(LDAPResourcePool *respool) {
+    LDAP *ldap = NULL;
+    if(respool->ldap_uri) {
+        ldap = ws_ldap_resource_create_uri_connection(respool->ldap_uri, LDAP_VERSION3);
+    } else {
+        ldap = ws_ldap_resource_create_connection(respool->host, respool->port, FALSE, LDAP_VERSION3);
+    }
+    
+    if(!ldap) {
+        log_ereport(
+                LOG_FAILURE,
+                "Resource pool %s: %s: cannot create LDAP session",
+                respool->name,
+                respool->ldap_uri ? respool->ldap_uri : respool->host);
+        return NULL;
+    }
+    
+    LDAPResource *res = pool_malloc(respool->pool, sizeof(LDAPResource));
+    if(!res) {
+        ws_ldap_close(ldap);
+        log_ereport(LOG_CATASTROPHE, "ldap_resourcepool_createresource: OOM");
+        return NULL;
+    }
+    res->ldap = ldap;
+    
+    return res;
+}
+
+void   ldap_resourcepool_freeresource(LDAPResourcePool *pool, LDAPResource *res) {
+    if(res->ldap) {
+        ws_ldap_close(res->ldap);
+    }
+    pool_free(pool->pool, res);
+}
+
+int    ldap_resourcepool_prepare(LDAPResourcePool *pool, LDAPResource *res) {
+    // unused
+    return 0;
+}
+
+int    ldap_resourcepool_finish(LDAPResourcePool *pool, LDAPResource *res) {
+    // unused
+    return 0;
+}
+
+void * ldap_resourcepool_getresourcedata(LDAPResource *res) {
+    return res->ldap;
+}

mercurial