mirror of https://github.com/yandex/odyssey.git
779 lines
18 KiB
C
779 lines
18 KiB
C
/*
|
|
* Odyssey.
|
|
*
|
|
* Scalable PostgreSQL connection pooler.
|
|
*/
|
|
|
|
#include <kiwi.h>
|
|
#include <machinarium.h>
|
|
#include <odyssey.h>
|
|
|
|
od_retcode_t od_ldap_server_free(od_ldap_server_t *serv)
|
|
{
|
|
od_list_unlink(&serv->link);
|
|
/* free memory alloc from LDAP lib */
|
|
if (serv->conn) {
|
|
ldap_unbind(serv->conn);
|
|
}
|
|
|
|
free(serv);
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
//#define LDAP_DBG
|
|
|
|
static inline od_retcode_t od_ldap_error_report_client(od_client_t *cl, int rc)
|
|
{
|
|
switch (rc) {
|
|
case LDAP_SUCCESS:
|
|
return OK_RESPONSE;
|
|
case LDAP_INVALID_CREDENTIALS:
|
|
return NOT_OK_RESPONSE;
|
|
case LDAP_INSUFFICIENT_ACCESS: {
|
|
// disabling blind ldapsearch via odyssey error messages
|
|
// to collect user account attributes
|
|
od_frontend_error(cl, KIWI_SYNTAX_ERROR, "incorrect password");
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
case LDAP_UNAVAILABLE:
|
|
case LDAP_UNWILLING_TO_PERFORM:
|
|
case LDAP_BUSY: {
|
|
od_frontend_error(cl, KIWI_SYNTAX_ERROR,
|
|
"LDAP auth failed: ldap server is down");
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
case LDAP_INVALID_SYNTAX: {
|
|
od_frontend_error(
|
|
cl, KIWI_SYNTAX_ERROR,
|
|
"LDAP auth failed: invalid attribute value was specified");
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
default: {
|
|
#ifdef LDAP_DBG
|
|
od_frontend_error(cl, KIWI_SYNTAX_ERROR,
|
|
"LDAP auth failed: %s %d",
|
|
ldap_err2string(rc), rc);
|
|
#else
|
|
od_frontend_error(cl, KIWI_SYNTAX_ERROR,
|
|
"LDAP auth failed: unknown error");
|
|
#endif
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline int od_init_ldap_conn(LDAP **l, char *uri)
|
|
{
|
|
od_retcode_t rc = ldap_initialize(l, uri);
|
|
if (rc != LDAP_SUCCESS) {
|
|
// set to null, we do not need to unbind this
|
|
// ldap_initialize frees assosated memory
|
|
*l = NULL;
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
int ldapversion = LDAP_VERSION3;
|
|
rc = ldap_set_option(*l, LDAP_OPT_PROTOCOL_VERSION, &ldapversion);
|
|
|
|
if (rc != LDAP_SUCCESS) {
|
|
// same as above
|
|
*l = NULL;
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_retcode_t od_ldap_endpoint_prepare(od_ldap_endpoint_t *le)
|
|
{
|
|
const char *scheme;
|
|
scheme = le->ldapscheme; // ldap or ldaps
|
|
if (scheme == NULL) {
|
|
scheme = "ldap";
|
|
}
|
|
|
|
le->ldapurl = NULL;
|
|
if (!le->ldapserver) {
|
|
// TODO: support mulitple ldap servers
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
if (od_asprintf(&le->ldapurl, "%s://%s:%d", scheme, le->ldapserver,
|
|
le->ldapport) != OK_RESPONSE) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_retcode_t
|
|
od_ldap_change_storage_credentials(od_logger_t *logger,
|
|
od_ldap_storage_credentials_t *lsc,
|
|
od_client_t *client)
|
|
{
|
|
client->ldap_storage_username = lsc->lsc_username;
|
|
client->ldap_storage_username_len = strlen(lsc->lsc_username);
|
|
client->ldap_storage_password = lsc->lsc_password;
|
|
client->ldap_storage_password_len = strlen(lsc->lsc_password);
|
|
od_debug(logger, "auth_ldap", client, NULL,
|
|
"storage_user changed to %s", lsc->lsc_username);
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_retcode_t od_ldap_search_storage_credentials(od_logger_t *logger,
|
|
struct berval **values,
|
|
od_rule_t *rule,
|
|
od_client_t *client)
|
|
{
|
|
int i;
|
|
for (i = 0; i < ldap_count_values_len(values); i++) {
|
|
char host_db[128];
|
|
od_snprintf(host_db, sizeof(host_db), "%s_%s",
|
|
rule->storage->host,
|
|
client->startup.database.value);
|
|
if (strstr((char *)values[i]->bv_val, host_db)) {
|
|
od_list_t *j;
|
|
od_list_foreach(&rule->ldap_storage_creds_list, j)
|
|
{
|
|
od_ldap_storage_credentials_t *lsc = NULL;
|
|
lsc = od_container_of(
|
|
j, od_ldap_storage_credentials_t, link);
|
|
char host_db_user[128];
|
|
od_snprintf(host_db_user, sizeof(host_db_user),
|
|
"%s_%s", host_db, lsc->name);
|
|
|
|
if (strstr((char *)values[i]->bv_val,
|
|
host_db_user)) {
|
|
od_debug(logger, "auth_ldap", client,
|
|
NULL, "matched group %s",
|
|
(char *)values[i]->bv_val);
|
|
od_ldap_change_storage_credentials(
|
|
logger, lsc, client);
|
|
return OK_RESPONSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
od_debug(logger, "auth_ldap", client, NULL,
|
|
"error: route does not match any user attribute");
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
od_retcode_t od_ldap_server_prepare(od_logger_t *logger, od_ldap_server_t *serv,
|
|
od_rule_t *rule, od_client_t *client)
|
|
{
|
|
od_retcode_t rc;
|
|
char *auth_user = NULL;
|
|
|
|
if (serv->endpoint->ldapbasedn) {
|
|
// copy pasted from ./src/backend/libpq/auth.c:2635
|
|
char *filter;
|
|
LDAPMessage *search_message;
|
|
LDAPMessage *entry;
|
|
char *attributes[] = { LDAP_NO_ATTRS, NULL };
|
|
char *dn;
|
|
int count;
|
|
|
|
if (rule->ldap_storage_credentials_attr)
|
|
attributes[0] = rule->ldap_storage_credentials_attr;
|
|
|
|
if (serv->endpoint->ldapsearchattribute) {
|
|
od_asprintf(&filter, "(%s=%s)",
|
|
serv->endpoint->ldapsearchattribute,
|
|
client->startup.user.value);
|
|
} else {
|
|
od_asprintf(&filter, "(uid=%s)",
|
|
client->startup.user.value);
|
|
}
|
|
|
|
if (serv->endpoint->ldapsearchfilter) {
|
|
od_asprintf(&filter, "(&%s%s)", filter,
|
|
serv->endpoint->ldapsearchfilter);
|
|
}
|
|
|
|
rc = ldap_search_s(serv->conn, serv->endpoint->ldapbasedn,
|
|
LDAP_SCOPE_SUBTREE, filter, attributes, 0,
|
|
&search_message);
|
|
|
|
od_debug(logger, "auth_ldap", client, NULL,
|
|
"basedn search entries with filter: %s and attrib %s ",
|
|
filter, attributes[0]);
|
|
|
|
if (rc != LDAP_SUCCESS) {
|
|
od_error(logger, "auth_ldap", client, NULL,
|
|
"basednn search result: %d", rc);
|
|
free(filter);
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
count = ldap_count_entries(serv->conn, search_message);
|
|
if (count != 1) {
|
|
od_error(logger, "auth_ldap", client, NULL,
|
|
"basedn search entries count: %d", count);
|
|
|
|
if (count == 0) {
|
|
free(filter);
|
|
ldap_msgfree(search_message);
|
|
return LDAP_INSUFFICIENT_ACCESS;
|
|
} else {
|
|
}
|
|
|
|
free(filter);
|
|
ldap_msgfree(search_message);
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
entry = ldap_first_entry(serv->conn, search_message);
|
|
dn = ldap_get_dn(serv->conn, entry);
|
|
if (dn == NULL) {
|
|
// TODO: report err
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
if (rule->ldap_storage_credentials_attr) {
|
|
struct berval **values = NULL;
|
|
values = ldap_get_values_len(serv->conn, entry,
|
|
attributes[0]);
|
|
if (ldap_count_values_len(values) > 0) {
|
|
rc = od_ldap_search_storage_credentials(
|
|
logger, values, rule, client);
|
|
if (rc != OK_RESPONSE) {
|
|
free(filter);
|
|
ldap_memfree(dn);
|
|
ldap_value_free_len(values);
|
|
ldap_msgfree(search_message);
|
|
return LDAP_INSUFFICIENT_ACCESS;
|
|
}
|
|
} else {
|
|
od_debug(logger, "auth_ldap", client, NULL,
|
|
"error: empty search results");
|
|
free(filter);
|
|
ldap_memfree(dn);
|
|
ldap_value_free_len(values);
|
|
ldap_msgfree(search_message);
|
|
return LDAP_INSUFFICIENT_ACCESS;
|
|
}
|
|
ldap_value_free_len(values);
|
|
}
|
|
auth_user = strdup(dn);
|
|
|
|
free(filter);
|
|
ldap_memfree(dn);
|
|
ldap_msgfree(search_message);
|
|
|
|
} else {
|
|
od_asprintf(&auth_user, "%s%s%s",
|
|
serv->endpoint->ldapprefix ?
|
|
serv->endpoint->ldapprefix :
|
|
"",
|
|
client->startup.user.value,
|
|
serv->endpoint->ldapsuffix ?
|
|
serv->endpoint->ldapsuffix :
|
|
"");
|
|
}
|
|
|
|
client->ldap_auth_dn = auth_user;
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_ldap_server_t *od_ldap_server_allocate()
|
|
{
|
|
od_ldap_server_t *serv = malloc(sizeof(od_ldap_server_t));
|
|
serv->conn = NULL;
|
|
serv->endpoint = NULL;
|
|
|
|
return serv;
|
|
}
|
|
|
|
od_retcode_t od_ldap_server_init(od_logger_t *logger, od_ldap_server_t *server,
|
|
od_rule_t *rule)
|
|
{
|
|
od_retcode_t rc;
|
|
od_id_generate(&server->id, "ls");
|
|
od_list_init(&server->link);
|
|
|
|
server->global = NULL;
|
|
|
|
od_ldap_endpoint_t *le = rule->ldap_endpoint;
|
|
server->endpoint = le;
|
|
|
|
if (od_init_ldap_conn(&server->conn, le->ldapurl) != OK_RESPONSE) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
rc = ldap_simple_bind_s(server->conn,
|
|
server->endpoint->ldapbinddn ?
|
|
server->endpoint->ldapbinddn :
|
|
"",
|
|
server->endpoint->ldapbindpasswd ?
|
|
server->endpoint->ldapbindpasswd :
|
|
"");
|
|
|
|
if (rc) {
|
|
od_error(logger, "auth_ldap", NULL, NULL,
|
|
"basednn simple bind result: %d", rc);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static inline int od_ldap_server_auth(od_ldap_server_t *serv, od_client_t *cl,
|
|
kiwi_password_t *tok)
|
|
{
|
|
int rc;
|
|
rc = ldap_simple_bind_s(serv->conn, cl->ldap_auth_dn, tok->password);
|
|
|
|
od_route_t *route = cl->route;
|
|
if (route->rule->client_fwd_error) {
|
|
od_ldap_error_report_client(cl, rc);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
od_ldap_server_t *od_ldap_server_pull(od_logger_t *logger, od_rule_t *rule,
|
|
bool auth_pool)
|
|
{
|
|
od_retcode_t rc;
|
|
od_ldap_endpoint_t *le = rule->ldap_endpoint;
|
|
od_ldap_server_t *ldap_server = NULL;
|
|
|
|
od_server_pool_t *ldap_server_pool;
|
|
if (auth_pool) {
|
|
ldap_server_pool = le->ldap_auth_pool;
|
|
} else {
|
|
ldap_server_pool = le->ldap_search_pool;
|
|
}
|
|
|
|
od_debug(logger, "auth_ldap", NULL, NULL,
|
|
"total connections in selected pool: %d",
|
|
od_server_pool_total(ldap_server_pool));
|
|
od_ldap_endpoint_lock(le);
|
|
|
|
/* get client server from route server pool */
|
|
for (;;) {
|
|
ldap_server = od_ldap_server_pool_next(ldap_server_pool,
|
|
OD_SERVER_IDLE);
|
|
if (ldap_server) {
|
|
od_debug(logger, "auth_ldap", NULL, NULL,
|
|
"pulling ldap_server from ldap_pool");
|
|
if (rule->ldap_pool_ttl > 0) {
|
|
if (time(NULL) - ldap_server->idle_timestamp >
|
|
rule->ldap_pool_ttl) {
|
|
od_debug(
|
|
logger, "auth_ldap", NULL, NULL,
|
|
"bad ldap_server_ttl - closing ldap connection");
|
|
od_ldap_server_pool_set(
|
|
ldap_server_pool, ldap_server,
|
|
OD_SERVER_UNDEF);
|
|
od_ldap_server_free(ldap_server);
|
|
ldap_server = NULL;
|
|
od_ldap_endpoint_unlock(le);
|
|
break;
|
|
}
|
|
}
|
|
od_ldap_server_pool_set(ldap_server_pool, ldap_server,
|
|
OD_SERVER_ACTIVE);
|
|
od_ldap_endpoint_unlock(le);
|
|
break;
|
|
}
|
|
|
|
if (false) {
|
|
/* special case, when we are interested only in an idle connection
|
|
* and do not want to start a new one */
|
|
// NOT IMPL
|
|
od_ldap_endpoint_unlock(le);
|
|
return NULL;
|
|
} else {
|
|
/* Maybe start new connection, if pool_size is zero */
|
|
/* Maybe start new connection, if we still have capacity for it */
|
|
|
|
int connections_in_pool =
|
|
od_server_pool_total(ldap_server_pool);
|
|
int pool_size = rule->ldap_pool_size;
|
|
|
|
if (pool_size == 0 || connections_in_pool < pool_size) {
|
|
// TODO: better limit logic here
|
|
// We are allowed to spun new server connection
|
|
od_debug(
|
|
logger, "auth_ldap", NULL, NULL,
|
|
"spun new connection to ldap server %s",
|
|
rule->ldap_endpoint_name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Wait wakeup condition for pool_timeout milliseconds.
|
|
*
|
|
* The condition triggered when a server connection
|
|
* put into idle state by DETACH events.
|
|
*/
|
|
od_ldap_endpoint_unlock(le);
|
|
|
|
uint32_t timeout = rule->ldap_pool_timeout;
|
|
if (timeout == 0)
|
|
timeout = UINT32_MAX;
|
|
rc = od_ldap_endpoint_wait(le, timeout);
|
|
|
|
if (rc == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
od_ldap_endpoint_lock(le);
|
|
}
|
|
|
|
if (ldap_server == NULL) {
|
|
/* create new server object */
|
|
ldap_server = od_ldap_server_allocate();
|
|
|
|
int ldap_rc = od_ldap_server_init(logger, ldap_server, rule);
|
|
|
|
if (ldap_rc != LDAP_SUCCESS) {
|
|
od_ldap_server_free(ldap_server);
|
|
od_ldap_endpoint_unlock(le);
|
|
return NULL;
|
|
}
|
|
|
|
od_ldap_server_pool_set(ldap_server_pool, ldap_server,
|
|
OD_SERVER_ACTIVE);
|
|
od_ldap_endpoint_unlock(le);
|
|
}
|
|
|
|
return ldap_server;
|
|
}
|
|
|
|
static inline od_retcode_t od_ldap_server_attach(od_client_t *client)
|
|
{
|
|
od_instance_t *instance = client->global->instance;
|
|
od_logger_t *logger = &instance->logger;
|
|
|
|
od_retcode_t rc;
|
|
|
|
/* get client server from route server pool */
|
|
od_ldap_server_t *server =
|
|
od_ldap_server_pull(logger, client->rule, false);
|
|
|
|
if (server == NULL) {
|
|
od_debug(&instance->logger, "auth_ldap", client, NULL,
|
|
"failed to get ldap connection");
|
|
if (client->rule->client_fwd_error) {
|
|
od_ldap_error_report_client(client, NOT_OK_RESPONSE);
|
|
}
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
od_ldap_endpoint_lock(client->rule->ldap_endpoint);
|
|
|
|
rc = od_ldap_server_prepare(logger, server, client->rule, client);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
od_debug(&instance->logger, "auth_ldap", client, NULL,
|
|
"closing bad ldap connection, need relogin");
|
|
od_ldap_server_pool_set(
|
|
client->rule->ldap_endpoint->ldap_search_pool, server,
|
|
OD_SERVER_UNDEF);
|
|
od_ldap_server_free(server);
|
|
} else {
|
|
server->idle_timestamp = time(NULL);
|
|
od_ldap_server_pool_set(
|
|
client->rule->ldap_endpoint->ldap_search_pool, server,
|
|
OD_SERVER_IDLE);
|
|
}
|
|
|
|
od_ldap_endpoint_unlock(client->rule->ldap_endpoint);
|
|
if (rc != OK_RESPONSE) {
|
|
if (client->rule->client_fwd_error) {
|
|
od_ldap_error_report_client(client, rc);
|
|
}
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_retcode_t od_auth_ldap(od_client_t *cl, kiwi_password_t *tok)
|
|
{
|
|
od_instance_t *instance = cl->global->instance;
|
|
od_retcode_t rc;
|
|
|
|
if (cl->rule->ldap_storage_credentials_attr &&
|
|
cl->rule->ldap_endpoint_name) {
|
|
rc = OK_RESPONSE;
|
|
} else {
|
|
rc = od_ldap_server_attach(cl);
|
|
}
|
|
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
od_ldap_server_t *serv =
|
|
od_ldap_server_pull(&instance->logger, cl->rule, true);
|
|
|
|
if (serv == NULL) {
|
|
od_debug(&instance->logger, "auth_ldap", cl, NULL,
|
|
"failed to get ldap connection");
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
int ldap_rc = od_ldap_server_auth(serv, cl, tok);
|
|
|
|
od_ldap_endpoint_lock(cl->rule->ldap_endpoint);
|
|
|
|
switch (ldap_rc) {
|
|
case LDAP_SUCCESS: {
|
|
serv->idle_timestamp = time(NULL);
|
|
od_ldap_server_pool_set(cl->rule->ldap_endpoint->ldap_auth_pool,
|
|
serv, OD_SERVER_IDLE);
|
|
rc = OK_RESPONSE;
|
|
break;
|
|
}
|
|
case LDAP_INVALID_SYNTAX:
|
|
/* fallthrough */
|
|
case LDAP_INVALID_CREDENTIALS: {
|
|
serv->idle_timestamp = time(NULL);
|
|
od_ldap_server_pool_set(cl->rule->ldap_endpoint->ldap_auth_pool,
|
|
serv, OD_SERVER_IDLE);
|
|
rc = NOT_OK_RESPONSE;
|
|
break;
|
|
}
|
|
default: {
|
|
/*Need to rebind */
|
|
od_ldap_server_pool_set(cl->rule->ldap_endpoint->ldap_auth_pool,
|
|
serv, OD_SERVER_UNDEF);
|
|
od_ldap_server_free(serv);
|
|
rc = NOT_OK_RESPONSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
od_ldap_endpoint_unlock(cl->rule->ldap_endpoint);
|
|
|
|
return rc;
|
|
}
|
|
|
|
od_retcode_t od_ldap_conn_close(od_attribute_unused() od_route_t *route,
|
|
od_ldap_server_t *server)
|
|
{
|
|
ldap_unbind(server->conn);
|
|
od_list_unlink(&server->link);
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
|
|
/* ldap endpoints ADD/REMOVE API */
|
|
od_ldap_endpoint_t *od_ldap_endpoint_alloc()
|
|
{
|
|
od_ldap_endpoint_t *le = malloc(sizeof(od_ldap_endpoint_t));
|
|
if (le == NULL) {
|
|
return NULL;
|
|
}
|
|
od_list_init(&le->link);
|
|
|
|
le->name = NULL;
|
|
|
|
le->ldapserver = NULL;
|
|
le->ldapport = 0;
|
|
|
|
le->ldapscheme = NULL;
|
|
|
|
le->ldapprefix = NULL;
|
|
le->ldapsuffix = NULL;
|
|
le->ldapbindpasswd = NULL;
|
|
le->ldapsearchfilter = NULL;
|
|
le->ldapsearchattribute = NULL;
|
|
le->ldapscope = NULL;
|
|
le->ldapbasedn = NULL;
|
|
le->ldapbinddn = NULL;
|
|
// preparsed connect url
|
|
le->ldapurl = NULL;
|
|
|
|
od_server_pool_t *ldap_auth_pool = malloc(sizeof(*ldap_auth_pool));
|
|
od_server_pool_init(ldap_auth_pool);
|
|
le->ldap_auth_pool = ldap_auth_pool;
|
|
|
|
od_server_pool_t *ldap_search_pool = malloc(sizeof(*ldap_search_pool));
|
|
od_server_pool_init(ldap_search_pool);
|
|
le->ldap_search_pool = ldap_search_pool;
|
|
|
|
le->wait_bus = machine_channel_create();
|
|
if (le->wait_bus == NULL) {
|
|
od_ldap_endpoint_free(le);
|
|
return NULL;
|
|
}
|
|
|
|
pthread_mutex_init(&le->lock, NULL);
|
|
return le;
|
|
}
|
|
|
|
od_retcode_t od_ldap_endpoint_free(od_ldap_endpoint_t *le)
|
|
{
|
|
if (le->name) {
|
|
free(le->name);
|
|
}
|
|
|
|
if (le->ldapserver) {
|
|
free(le->ldapserver);
|
|
}
|
|
if (le->ldapscheme) {
|
|
free(le->ldapscheme);
|
|
}
|
|
|
|
if (le->ldapprefix) {
|
|
free(le->ldapprefix);
|
|
}
|
|
if (le->ldapsuffix) {
|
|
free(le->ldapsuffix);
|
|
}
|
|
if (le->ldapbindpasswd) {
|
|
free(le->ldapbindpasswd);
|
|
}
|
|
if (le->ldapsearchfilter) {
|
|
free(le->ldapsearchfilter);
|
|
}
|
|
if (le->ldapsearchattribute) {
|
|
free(le->ldapsearchattribute);
|
|
}
|
|
if (le->ldapscope) {
|
|
free(le->ldapscope);
|
|
}
|
|
if (le->ldapbasedn) {
|
|
free(le->ldapbasedn);
|
|
}
|
|
// preparsed connect url
|
|
if (le->ldapurl) {
|
|
free(le->ldapurl);
|
|
}
|
|
|
|
od_list_unlink(&le->link);
|
|
if (le->ldap_search_pool) {
|
|
od_ldap_server_pool_free(le->ldap_search_pool);
|
|
}
|
|
|
|
if (le->ldap_auth_pool) {
|
|
od_ldap_server_pool_free(le->ldap_auth_pool);
|
|
}
|
|
|
|
pthread_mutex_destroy(&le->lock);
|
|
if (le->wait_bus)
|
|
machine_channel_free(le->wait_bus);
|
|
|
|
free(le);
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_ldap_storage_credentials_t *od_ldap_storage_credentials_alloc()
|
|
{
|
|
od_ldap_storage_credentials_t *lsc =
|
|
malloc(sizeof(od_ldap_storage_credentials_t));
|
|
if (lsc == NULL) {
|
|
return NULL;
|
|
}
|
|
od_list_init(&lsc->link);
|
|
|
|
lsc->name = NULL;
|
|
|
|
lsc->lsc_username = NULL;
|
|
lsc->lsc_password = NULL;
|
|
|
|
return lsc;
|
|
}
|
|
|
|
od_retcode_t
|
|
od_ldap_storage_credentials_free(od_ldap_storage_credentials_t *lsc)
|
|
{
|
|
if (lsc->name) {
|
|
free(lsc->name);
|
|
}
|
|
|
|
if (lsc->lsc_username) {
|
|
free(lsc->lsc_username);
|
|
}
|
|
|
|
if (lsc->lsc_password) {
|
|
free(lsc->lsc_password);
|
|
}
|
|
|
|
od_list_unlink(&lsc->link);
|
|
|
|
free(lsc);
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_retcode_t od_ldap_endpoint_add(od_ldap_endpoint_t *ldaps,
|
|
od_ldap_endpoint_t *target)
|
|
{
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&(ldaps->link), i)
|
|
{
|
|
od_ldap_endpoint_t *s =
|
|
od_container_of(i, od_ldap_endpoint_t, link);
|
|
if (strcmp(s->name, target->name) == 0) {
|
|
/* already loaded */
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
}
|
|
|
|
od_list_append(&ldaps->link, &target->link);
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
od_ldap_endpoint_t *od_ldap_endpoint_find(od_list_t *ldaps, char *name)
|
|
{
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(ldaps, i)
|
|
{
|
|
od_ldap_endpoint_t *serv =
|
|
od_container_of(i, od_ldap_endpoint_t, link);
|
|
if (strcmp(serv->name, name) == 0) {
|
|
return serv;
|
|
}
|
|
}
|
|
|
|
/* target ldap server was not found */
|
|
return NULL;
|
|
}
|
|
|
|
od_retcode_t od_ldap_endpoint_remove(od_ldap_endpoint_t *ldaps,
|
|
od_ldap_endpoint_t *target)
|
|
{
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&ldaps->link, i)
|
|
{
|
|
od_ldap_endpoint_t *serv =
|
|
od_container_of(i, od_ldap_endpoint_t, link);
|
|
if (strcmp(serv->name, target->name) == 0) {
|
|
od_list_unlink(&target->link);
|
|
return OK_RESPONSE;
|
|
}
|
|
}
|
|
|
|
/* target ldap server was not found */
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
od_ldap_storage_credentials_t *
|
|
od_ldap_storage_credentials_find(od_list_t *ldap_storage_creds_list, char *name)
|
|
{
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(ldap_storage_creds_list, i)
|
|
{
|
|
od_ldap_storage_credentials_t *lsc =
|
|
od_container_of(i, od_ldap_storage_credentials_t, link);
|
|
if (strcmp(lsc->name, name) == 0) {
|
|
return lsc;
|
|
}
|
|
}
|
|
|
|
/* target storage user was not found */
|
|
return NULL;
|
|
}
|