Mon, 13 Mar 2023 22:39:51 +0100
refactor ldap user authentication, use new filter config
/* * 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); #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) { ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); } return ld; } 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); char *binddn = pblock_findval("Binddn", pb); char *bindpw = pblock_findval("Bindpw", pb); char *bind = pblock_findval("Bind", pb); log_ereport( LOG_INFORM, "create ldap resource pool: name=%s : %s%s%s%s : binddn=%s", rpname, ldap_uri ? "uri=" : "host=", ldap_uri ? ldap_uri : host, ldap_uri || !port ? "" : ":", !port ? "" : port, binddn ? binddn : "''"); 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; ldap_pool->binddn = binddn; ldap_pool->bindpw = bindpw; WSBool bind_def = binddn != NULL; ldap_pool->bind = bind ? util_getboolean(bind, bind_def) : bind_def; 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; } if(respool->bind) { struct berval *server_cred; int r = ldap_resource_bind(respool, ldap, &server_cred); if(r != LDAP_SUCCESS) { log_ereport(LOG_FAILURE, "resource pool %s: bind failed: %s", respool->name, ldap_err2string(r)); ws_ldap_close(ldap); 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; res->res_pool = respool; 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; } int ldap_resource_bind(LDAPResourcePool *respool, LDAP *ldap, struct berval **server_cred) { if(!respool->binddn) { return -1; } return ws_ldap_bind(ldap, respool->binddn, respool->bindpw, server_cred); } int ws_ldap_bind(LDAP *ldap, const char *binddn, const char *bindpw, struct berval **server_cred) { struct berval cred; cred.bv_val = (char*)bindpw; cred.bv_len = strlen(cred.bv_val); return ldap_sasl_bind_s( ldap, binddn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, server_cred); }