#ifdef __gnu_linux__
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <ucx/utils.h>
#include "ldap_auth.h"
static void ws_ldap_close(
LDAP *ldap) {
#ifdef SOLARIS
ldap_unbind(ldap);
#else
ldap_unbind_ext_s(ldap,
NULL,
NULL);
#endif
}
AuthDB* create_ldap_authdb(
char *name, LDAPConfig *conf) {
LDAPAuthDB *authdb = malloc(
sizeof(LDAPAuthDB));
authdb->authdb.name = strdup(name);
authdb->authdb.get_user = ldap_get_user;
authdb->authdb.use_cache =
1;
authdb->config = *conf;
if (!authdb->config.usersearch) {
authdb->config.usersearch =
"uid";
}
if (!authdb->config.groupsearch) {
authdb->config.groupsearch =
"uniquemember";
}
authdb->groups.first =
NULL;
authdb->groups.last =
NULL;
authdb->groups.map = ucx_map_new(
32);
return (AuthDB*) authdb;
}
LDAP* get_ldap_session(LDAPAuthDB *authdb) {
LDAPConfig *config = &authdb->config;
LDAP *ld =
NULL;
#ifdef SOLARIS
ld = ldap_init(config->hostname, config->port);
#else
char *ldap_uri =
NULL;
asprintf(&ldap_uri,
"ldap://%s:%d", config->hostname, config->port);
int init_ret = ldap_initialize(&ld, ldap_uri);
free(ldap_uri);
if(init_ret) {
fprintf(stderr,
"ldap_initialize failed\n");
}
#endif
if(!ld) {
return NULL;
}
int ldapv =
LDAP_VERSION3;
ldap_set_option(ld,
LDAP_OPT_PROTOCOL_VERSION, &ldapv);
struct berval cred;
cred.bv_val = config->bindpw;
cred.bv_len = strlen(config->bindpw);
struct berval *server_cred;
int r = ldap_sasl_bind_s(
ld,
config->binddn,
LDAP_SASL_SIMPLE,
&cred,
NULL,
NULL,
&server_cred);
if (r !=
LDAP_SUCCESS) {
ws_ldap_close(ld);
fprintf(stderr,
"ldap_simple_bind_s failed: %s\n", ldap_err2string(r));
return NULL;
}
return ld;
}
User* ldap_get_user(AuthDB *db,
char *username) {
LDAPAuthDB *authdb = (LDAPAuthDB*) db;
LDAPConfig *config = &authdb->config;
LDAP *ld = get_ldap_session(authdb);
if (ld ==
NULL) {
fprintf(stderr,
"ldap_init failed\n");
return NULL;
}
char filter[
128];
int s = snprintf(filter,
127,
"uid=%s", username);
filter[s] =
0;
LDAPMessage *result;
struct timeval timeout;
timeout.tv_sec =
8;
timeout.tv_usec =
0;
int r = ldap_search_ext_s(
ld,
config->basedn,
LDAP_SCOPE_SUBTREE,
filter,
NULL,
0,
NULL,
NULL,
&timeout,
1,
&result);
if (r !=
LDAP_SUCCESS) {
ws_ldap_close(ld);
fprintf(stderr,
"ldap_search_ext_s failed\n");
return NULL;
}
LDAPMessage *msg = ldap_first_entry(ld, result);
if (msg) {
LDAPUser *user = malloc(
sizeof(LDAPUser));
if (user !=
NULL) {
user->authdb = authdb;
user->user.verify_password = ldap_user_verify_password;
user->user.check_group = ldap_user_check_group;
user->user.free = ldap_user_free;
user->user.name = username;
user->user.uid = -
1;
user->user.gid = -
1;
user->ldap = ld;
user->userdn = ldap_get_dn(ld, msg);
ldap_msgfree(result);
return (User*)user;
}
}
ws_ldap_close(ld);
return NULL;
}
LDAPGroup* ldap_get_group(LDAPAuthDB *authdb,
char *group) {
printf(
"ldap_get_group: %s\n", group);
LDAPConfig *config = &authdb->config;
LDAP *ld = get_ldap_session(authdb);
if (ld ==
NULL) {
fprintf(stderr,
"ldap_init failed\n");
return NULL;
}
char filter[
128];
int s = snprintf(filter,
127,
"cn=%s", group);
filter[s] =
0;
LDAPMessage *result;
struct timeval timeout;
timeout.tv_sec =
8;
timeout.tv_usec =
0;
int r = ldap_search_ext_s(
ld,
config->basedn,
LDAP_SCOPE_SUBTREE,
filter,
NULL,
0,
NULL,
NULL,
&timeout,
1,
&result);
if (r !=
LDAP_SUCCESS) {
ws_ldap_close(ld);
fprintf(stderr,
"ldap_search_ext_s failed\n");
return NULL;
}
LDAPGroup *wsgroup =
NULL;
LDAPMessage *msg = ldap_first_entry(ld, result);
if (msg) {
wsgroup = malloc(
sizeof(LDAPGroup));
wsgroup->name = strdup(group);
wsgroup->members =
NULL;
wsgroup->nmembers =
0;
wsgroup->update =
0;
wsgroup->next =
NULL;
BerElement *ber =
NULL;
char *attribute = attribute=ldap_first_attribute(ld, msg, &ber);
while(attribute !=
NULL) {
printf(
"attribute: %s\n", attribute);
if(!strcasecmp(attribute,
"memberuid")) {
struct berval **values = ldap_get_values_len(ld, msg, attribute);
if(values) {
int count = ldap_count_values_len(values);
wsgroup->members = calloc(count,
sizeof(LDAPMember));
wsgroup->nmembers = count;
for(
int i=
0;i<count;i++) {
sstr_t member = sstrn(
values[i]->bv_val,
values[i]->bv_len);
wsgroup->members[i].name = sstrdup(member).ptr;
printf(
"added member: %.*s\n", (
int)member.length, member.ptr);
}
}
}
attribute = ldap_next_attribute(ld, msg, ber);
}
if(ber) {
}
if(attribute) {
ldap_memfree(attribute);
}
}
ws_ldap_close(ld);
return wsgroup;
}
int ldap_user_verify_password(User *u,
char *password) {
LDAPUser *user = (LDAPUser*)u;
struct berval cred;
cred.bv_val = password;
cred.bv_len = strlen(password);
struct berval *server_cred;
int r = ldap_sasl_bind_s(
user->ldap,
user->userdn,
LDAP_SASL_SIMPLE,
&cred,
NULL,
NULL,
&server_cred);
if(r ==
LDAP_SUCCESS) {
printf(
"ldap password ok\n");
return 1;
}
else {
printf(
"ldap password not ok\n");
return 0;
}
}
int ldap_user_check_group(User *u,
char *group_str) {
LDAPUser *user = (LDAPUser*)u;
int ret =
0;
LDAPGroup *group = ldap_get_group(user->authdb, group_str);
for(
int i=
0;i<group->nmembers;i++) {
char *member = group->members[i].name;
if(!strcmp(member, u->name)) {
printf(
"is member\n");
ret =
1;
}
}
return ret;
}
void ldap_user_free(User *u) {
LDAPUser *user = (LDAPUser*)u;
ldap_memfree(user->userdn);
ws_ldap_close(user->ldap);
free(user);
}