#ifdef __gnu_linux__
#define _GNU_SOURCE
#endif
#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
}
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) {
}
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) {
return 0;
}
int ldap_resourcepool_finish(LDAPResourcePool *pool, LDAPResource *res) {
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);
}