diff -r b9a447b02046 -r 9b20b8f3582b src/server/daemon/ldap_resource.c --- /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; +}