UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2023 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifdef __gnu_linux__ 30 #define _GNU_SOURCE 31 #endif 32 33 #include "ldap_resource.h" 34 35 #include "../util/util.h" 36 37 38 39 static ResourceType ldap_resource_type = { 40 (resource_pool_init_func)ldap_resourcepool_init, 41 (resource_pool_destroy_func)ldap_resourcepool_destroy, 42 (resource_pool_createresource_func)ldap_resourcepool_createresource, 43 (resource_pool_freeresource_func)ldap_resourcepool_freeresource, 44 (resource_pool_prepare_func)ldap_resourcepool_prepare, 45 (resource_pool_finish_func)ldap_resourcepool_finish, 46 (resource_pool_getresourcedata_func)ldap_resourcepool_getresourcedata 47 }; 48 49 50 ResourceType* ldap_get_resource_type(void) { 51 return &ldap_resource_type; 52 } 53 54 LDAP* ws_ldap_resource_create_connection( 55 const char *hostname, 56 int port, 57 int ssl, 58 int ldap_version) 59 { 60 LDAP *ld = NULL; 61 62 #ifdef SOLARIS 63 ld = ldap_init(config->hostname, config->port); 64 #else 65 char *ldap_uri = NULL; 66 asprintf(&ldap_uri, "ldap://%s:%d", hostname, port); 67 ld = ws_ldap_resource_create_uri_connection(ldap_uri, ldap_version); 68 free(ldap_uri); 69 #endif 70 71 if(ld) { 72 ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); 73 } 74 75 return ld; 76 } 77 78 LDAP* ws_ldap_resource_create_uri_connection( 79 const char *uri, 80 int ldap_version) 81 { 82 #ifdef SOLARIS 83 log_ereport(LOG_FAILURE, "ldap_resource_create_connection_uri is not implemented on Solaris yet"); 84 return NULL; 85 #else 86 87 LDAP *ld = NULL; 88 int init_ret = ldap_initialize(&ld, uri); 89 if(init_ret) { 90 log_ereport( 91 LOG_FAILURE, 92 "ldap_resource_create_connection failed: uri: %s", 93 uri); 94 } 95 return ld; 96 #endif 97 } 98 99 void ws_ldap_close(LDAP *ldap) { 100 #ifdef SOLARIS 101 ldap_unbind(ldap); 102 #else 103 ldap_unbind_ext_s(ldap, NULL, NULL); 104 #endif 105 } 106 107 108 /* 109 * Validates settings from the pb pblock 110 * and creates an LDAPResourcePool object 111 * 112 * LDAPResourcePool contains all settings necessary for creating 113 * ldap connections. 114 */ 115 void * ldap_resourcepool_init(pool_handle_t *pool, const char *rpname, pblock *pb) { 116 char *ldap_uri = pblock_findval("Uri", pb); 117 char *host = pblock_findval("Host", pb); 118 char *port = pblock_findval("Port", pb); 119 char *binddn = pblock_findval("Binddn", pb); 120 char *bindpw = pblock_findval("Bindpw", pb); 121 char *bind = pblock_findval("Bind", pb); 122 123 log_ereport( 124 LOG_INFORM, 125 "create ldap resource pool: name=%s : %s%s%s%s : binddn=%s", 126 rpname, 127 ldap_uri ? "uri=" : "host=", 128 ldap_uri ? ldap_uri : host, 129 ldap_uri || !port ? "" : ":", 130 !port ? "" : port, 131 binddn ? binddn : "''''"); 132 133 if(!ldap_uri && !host) { 134 log_ereport(LOG_MISCONFIG, "Resource pool %s: No host or ldap uri specified", rpname); 135 return NULL; 136 } 137 if(ldap_uri && host) { 138 log_ereport(LOG_MISCONFIG, "Resource pool %s: Either Uri or Host must be specified, not both", rpname); 139 return NULL; 140 } 141 142 int64_t port_i = 0; 143 if(host) { 144 if(port) { 145 if(util_strtoint(port, &port_i)) { 146 if(port_i < 1 || port_i > 65535) { 147 log_ereport(LOG_MISCONFIG, "Resource pool %s: Port %s is out of range", rpname, port); 148 } 149 } else { 150 log_ereport(LOG_MISCONFIG, "Resource pool %s: Port ''%s'' is not a valid number", rpname, port); 151 } 152 } else { 153 port_i = LDAP_PORT; 154 } 155 } 156 157 LDAPResourcePool *ldap_pool = pool_malloc(pool, sizeof(LDAPResourcePool)); 158 if(!ldap_pool) { 159 return NULL; 160 } 161 162 ldap_pool->name = rpname; 163 ldap_pool->pool = pool; 164 ldap_pool->ldap_uri = ldap_uri; 165 ldap_pool->host = host; 166 ldap_pool->port = (int)port_i; 167 ldap_pool->binddn = binddn; 168 ldap_pool->bindpw = bindpw; 169 WSBool bind_def = binddn != NULL; 170 ldap_pool->bind = bind ? util_getboolean(bind, bind_def) : bind_def; 171 172 return ldap_pool; 173 } 174 175 void ldap_resourcepool_destroy(LDAPResourcePool *pool) { 176 // unused 177 } 178 179 void * ldap_resourcepool_createresource(LDAPResourcePool *respool) { 180 LDAP *ldap = NULL; 181 if(respool->ldap_uri) { 182 ldap = ws_ldap_resource_create_uri_connection(respool->ldap_uri, LDAP_VERSION3); 183 } else { 184 ldap = ws_ldap_resource_create_connection(respool->host, respool->port, FALSE, LDAP_VERSION3); 185 } 186 187 if(!ldap) { 188 log_ereport( 189 LOG_FAILURE, 190 "resource pool %s: %s: cannot create LDAP session", 191 respool->name, 192 respool->ldap_uri ? respool->ldap_uri : respool->host); 193 return NULL; 194 } 195 196 if(respool->bind) { 197 struct berval *server_cred; 198 int r = ldap_resource_bind(respool, ldap, &server_cred); 199 if(r != LDAP_SUCCESS) { 200 log_ereport(LOG_FAILURE, "resource pool %s: bind failed: %s", respool->name, ldap_err2string(r)); 201 ws_ldap_close(ldap); 202 return NULL; 203 } 204 } 205 206 LDAPResource *res = pool_malloc(respool->pool, sizeof(LDAPResource)); 207 if(!res) { 208 ws_ldap_close(ldap); 209 log_ereport(LOG_CATASTROPHE, "ldap_resourcepool_createresource: OOM"); 210 return NULL; 211 } 212 res->ldap = ldap; 213 res->res_pool = respool; 214 215 return res; 216 } 217 218 void ldap_resourcepool_freeresource(LDAPResourcePool *pool, LDAPResource *res) { 219 if(res->ldap) { 220 ws_ldap_close(res->ldap); 221 } 222 pool_free(pool->pool, res); 223 } 224 225 int ldap_resourcepool_prepare(LDAPResourcePool *pool, LDAPResource *res) { 226 // unused 227 return 0; 228 } 229 230 int ldap_resourcepool_finish(LDAPResourcePool *pool, LDAPResource *res) { 231 // unused 232 return 0; 233 } 234 235 void * ldap_resourcepool_getresourcedata(LDAPResource *res) { 236 return res->ldap; 237 } 238 239 240 int ldap_resource_bind(LDAPResourcePool *respool, LDAP *ldap, struct berval **server_cred) { 241 if(!respool->binddn) { 242 return -1; 243 } 244 return ws_ldap_bind(ldap, respool->binddn, respool->bindpw, server_cred); 245 } 246 247 int ws_ldap_bind(LDAP *ldap, const char *binddn, const char *bindpw, struct berval **server_cred) { 248 struct berval cred; 249 cred.bv_val = (char*)bindpw; 250 cred.bv_len = strlen(cred.bv_val); 251 return ldap_sasl_bind_s( 252 ldap, 253 binddn, 254 LDAP_SASL_SIMPLE, 255 &cred, 256 NULL, 257 NULL, 258 server_cred); 259 } 260 261