2 #include <ldap_schema.h>
15 const char *filter,
char **attrs,
int b64enc,
int *err);
103 static int ldap_count(LDAP *ld, LDAPMessage *message,
int *err);
104 static struct ldap_entry *ldap_getent(LDAP *ld, LDAPMessage **msgptr, LDAPMessage *result,
int b64enc,
int *err);
105 static int dts_sasl_interact(LDAP *ld,
unsigned flags,
void *defaults,
void *in );
107 static void free_simple(
void *data) {
109 struct berval *bv = simple->
cred;
111 if (bv && bv->bv_val) {
118 free((
void *)simple->
dn);
122 static void free_modval(
void *data) {
126 free((
void *)modv->
value);
130 static void free_modreq(
void *data) {
135 free((
void *)modr->
attr);
137 for(modv = modr->
first; modv; modv = modv->
next) {
142 static void free_modify(
void *data) {
146 free((
void *)lmod->
dn);
149 for(cnt=0; cnt < 3; cnt++) {
156 static void free_add(
void *data) {
160 free((
void *)lmod->
dn);
168 static void free_sasl(
void *data) {
172 free((
void *)sasl->
mech);
175 free((
void *)sasl->
realm);
181 free((
void *)sasl->
passwd);
188 static void free_ldapconn(
void *data) {
206 static void free_result(
void *data) {
213 static void free_entry(
void *data) {
225 ldap_memfree((
void *)ent->
dn);
231 free((
void *)ent->
dnufn);
243 static void free_rdnarr(
void *data) {
251 static void free_rdn(
void *data) {
262 static void free_attr(
void *data) {
270 ldap_memfree((
char *)la->
name);
276 static void free_attrvalarr(
void *data) {
283 static void free_attrval(
void *data) {
290 static int32_t modify_hash(
const void *data,
int key) {
293 const char *hashkey = (key) ? data : modr->
attr;
296 ret =
jenhash(hashkey, strlen(hashkey), 0);
298 ret =
jenhash(modr,
sizeof(modr), 0);
303 static int ldap_rebind_proc(LDAP *ld, LDAP_CONST
char *url, ber_tag_t request, ber_int_t msgid,
void *params) {
305 int res = LDAP_UNAVAILABLE;
308 return LDAP_UNAVAILABLE;
312 int sasl_flags = LDAP_SASL_AUTOMATIC | LDAP_SASL_QUIET;
315 res = ldap_sasl_interactive_bind_s(ld, NULL, sasl->
mech, ldap->
sctrlsp , NULL, sasl_flags, dts_sasl_interact, sasl);
320 res = ldap_sasl_bind_s(ld, simple->
dn, LDAP_SASL_SIMPLE, simple->
cred, ldap->
sctrlsp, NULL, NULL);
339 struct timeval timeout;
341 if (!(ld =
objalloc(
sizeof(*ld), free_ldapconn))) {
345 ld->
uri = strdup(uri);
351 if ((res = ldap_initialize(&ld->
ldap, ld->
uri) != LDAP_SUCCESS)) {
356 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
357 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &debug);
360 timeout.tv_sec = timelimit;
362 ldap_set_option(ld->
ldap, LDAP_OPT_NETWORK_TIMEOUT, (
void *)&timeout);
364 ldap_set_option(ld->
ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
365 ldap_set_option(ld->
ldap, LDAP_OPT_REFERRALS, (
void *)LDAP_OPT_ON);
366 ldap_set_rebind_proc(ld->
ldap, ldap_rebind_proc, ld);
380 static int interaction(
unsigned flags, sasl_interact_t *interact,
struct sasl_defaults *defaults) {
381 const char *res = interact->defresult;
383 switch( interact->id ) {
384 case SASL_CB_GETREALM:
385 if (defaults->
realm) {
386 res = defaults->
realm;
389 case SASL_CB_AUTHNAME:
406 interact->result = (res) ? res :
"";
407 interact->len = strlen(interact->result);
412 static int dts_sasl_interact(LDAP *ld,
unsigned flags,
void *defaults,
void *in ) {
413 sasl_interact_t *interact = in;
416 return LDAP_PARAM_ERROR;
419 while( interact->id != SASL_CB_LIST_END ) {
420 int rc = interaction(flags, interact, defaults);
440 return LDAP_UNAVAILABLE;
444 len = strlen(passwd);
446 simple =
objalloc(
sizeof(*simple), free_simple);
447 cred = calloc(
sizeof(*cred), 1);
448 cred->bv_val = malloc(len);
449 memcpy(cred->bv_val, passwd, len);
452 simple->
dn = strdup(dn);
459 res = ldap_sasl_bind_s(ld->
ldap, simple->
dn, LDAP_SASL_SIMPLE, simple->
cred, ld->
sctrlsp, NULL, NULL);
479 const char *uidrdn,
const char *uid,
const char *passwd) {
485 return LDAP_UNAVAILABLE;
493 flen=strlen(uidrdn) + strlen(filter) + strlen(uid) + 7;
494 sfilt = malloc(flen);
495 snprintf((
char *)sfilt, flen,
"(&(%s=%s)%s)", uidrdn, uid, filter);
497 if (!(results =
ldap_search_sub(ldap, base, sfilt, 0, &res, uidrdn, NULL))) {
504 if (results->
count != 1) {
507 return LDAP_INAPPROPRIATE_AUTH;
524 extern int ldap_saslbind(
struct ldap_conn *ld,
const char *mech,
const char *realm,
const char *authcid,
const char *passwd,
const char *authzid ) {
526 int res, sasl_flags = LDAP_SASL_AUTOMATIC | LDAP_SASL_QUIET;
529 return LDAP_UNAVAILABLE;
532 if (!(sasl =
objalloc(
sizeof(*sasl), free_sasl))) {
533 return LDAP_NO_MEMORY;
541 ldap_get_option(ld->
ldap, LDAP_OPT_X_SASL_MECH, &sasl->
mech);
547 ldap_get_option(ld->
ldap, LDAP_OPT_X_SASL_REALM, &sasl->
realm );
553 ldap_get_option(ld->
ldap, LDAP_OPT_X_SASL_AUTHCID, &sasl->
authcid );
559 ldap_get_option(ld->
ldap, LDAP_OPT_X_SASL_AUTHZID, &sasl->
authzid );
567 res = ldap_sasl_interactive_bind_s(ld->
ldap, NULL, sasl->
mech, ld->
sctrlsp , NULL, sasl_flags, dts_sasl_interact, sasl);
577 return ldap_err2string(res);
580 static int32_t searchresults_hash(
const void *data,
int key) {
583 const char *hashkey = (key) ? data : ent->
dn;
586 ret =
jenhash(hashkey, strlen(hashkey), 0);
588 ret =
jenhash(ent,
sizeof(ent), 0);
603 char *attr, **tmp, **attrs = NULL;
606 va_start(a_list, res);
607 while (( attr=va_arg(a_list,
void *))) {
613 tmp = attrs = malloc(
sizeof(
void *)*cnt);
615 va_start(a_list, res);
616 while (( attr=va_arg(a_list,
char *))) {
624 return _dtsldapsearch(ld, base, LDAP_SCOPE_SUBTREE, filter, attrs, b64enc, res);
637 char *attr, **tmp, **attrs = NULL;
640 va_start(a_list, res);
641 while (( attr=va_arg(a_list,
void *))) {
647 tmp = attrs = malloc(
sizeof(
void *)*cnt);
649 va_start(a_list, res);
650 while (( attr=va_arg(a_list,
char *))) {
658 return _dtsldapsearch(ld, base, LDAP_SCOPE_ONELEVEL, filter, attrs, b64enc, res);
671 char *attr, **tmp, **attrs = NULL;
674 va_start(a_list, res);
675 while (( attr=va_arg(a_list,
void *))) {
681 tmp = attrs = malloc(
sizeof(
void *)*cnt);
683 va_start(a_list, res);
684 while (( attr=va_arg(a_list,
char *))) {
692 return _dtsldapsearch(ld, base, LDAP_SCOPE_BASE, filter, attrs, b64enc, res);
696 int ldap_count(LDAP *ld, LDAPMessage *message,
int *err) {
700 x = ldap_count_entries(ld, message);
709 ldap_get_option(ld, LDAP_OPT_RESULT_CODE, err);
717 static char *ldap_getdn(LDAP *ld, LDAPMessage *message,
int *err) {
721 dn = ldap_get_dn(ld, message);
730 ldap_get_option(ld, LDAP_OPT_RESULT_CODE, err);
739 static char *ldap_getattribute(LDAP *ld, LDAPMessage *message, BerElement **berptr,
int *err) {
740 BerElement *ber = *berptr;
745 attr = ldap_next_attribute(ld, message, ber);
747 attr = ldap_first_attribute(ld, message, berptr);
755 ldap_get_option(ld, LDAP_OPT_RESULT_CODE, err);
765 struct berval *val = attrval;
770 for(pos=0; isprint(val->bv_val[pos]); pos++)
773 aval =
objalloc(val->bv_len+1, NULL);
774 strncpy(aval, val->bv_val,
objsize(aval));
778 aval =
b64enc_buf(val->bv_val, val->bv_len, 0);
782 memcpy(aval, val->bv_val,
objsize(aval));
793 static struct berval **ldap_attrvals(LDAP *ld, LDAPMessage *message,
char *attr,
int *cnt,
int *err) {
794 struct berval **vals = NULL;
797 vals = ldap_get_values_len(ld, message, attr);
801 *cnt = ldap_count_values_len(vals);
809 ldap_get_option(ld, LDAP_OPT_RESULT_CODE, err);
817 static int32_t ldapattr_hash(
const void *data,
int key) {
820 const char *hashkey = (key) ? data : la->
name;
823 ret =
jenhash(hashkey, strlen(hashkey), 0);
825 ret =
jenhash(la,
sizeof(la), 0);
830 static struct bucket_list *attr2bl(LDAP *ld, LDAPMessage *message,
struct ldap_attr **first,
int b64enc,
int *res) {
831 BerElement *ber = NULL;
835 struct berval **tmp, **vals = NULL;
843 *res = LDAP_NO_MEMORY;
848 while((attr = ldap_getattribute(ld, message, &ber, res))) {
849 tmp = vals = ldap_attrvals(ld, message, attr, &cnt, res);
850 la =
objalloc(
sizeof(*la), free_attr);
851 if (first && !*first) {
862 lavals =
objalloc(
sizeof(
void *) * (cnt+1), free_attrvalarr);
863 if (!lavals || !la) {
865 *res = LDAP_NO_MEMORY;
874 ldap_value_free_len(vals);
885 struct berval *bval = *tmp;
887 *lavals = lav =
objalloc(
sizeof(*lav), free_attrval);
890 eval = ldap_encattr(bval, b64enc, &type);
893 *res = LDAP_NO_MEMORY;
900 ldap_value_free_len(vals);
906 lav->
len = bval->bv_len;
911 ldap_value_free_len(vals);
921 struct ldap_entry *ldap_getent(LDAP *ld, LDAPMessage **msgptr, LDAPMessage *result,
int b64enc,
int *err) {
922 LDAPMessage *message = *msgptr;
924 struct ldap_rdn *lrdn, *prev = NULL, *first = NULL;
929 int res, cnt, tlen=0, dccnt=0;
933 message = ldap_next_entry(ld, message);
935 message = ldap_first_entry(ld, result);
940 if (message && !(ent =
objalloc(
sizeof(*ent), free_entry))) {
942 *err = LDAP_NO_MEMORY;
949 ldap_get_option(ld, LDAP_OPT_RESULT_CODE, err);
955 if (!(ent->
dn = ldap_getdn(ld, message, &res))) {
964 if ((res = ldap_str2dn(ent->
dn, &dnarr, LDAP_DN_PEDANTIC))) {
975 for (cnt=0; dnarr[cnt]; cnt++) {
977 for (; *rdnarr; rdnarr++) {
978 if (!(lrdn =
objalloc(
sizeof(*lrdn), free_rdn))) {
979 for(lrdn = first; lrdn; lrdn=lrdn->
next) {
984 *err = LDAP_NO_MEMORY;
999 if (!strcmp(
"dc", rdn->la_attr.bv_val)) {
1002 tlen += rdn->la_value.bv_len;
1015 ent->
dnufn = calloc(tlen + (ent->
rdncnt-dccnt)*2+dccnt, 1);
1019 for(lrdn = first; lrdn; lrdn=lrdn->
next) {
1024 *err = LDAP_NO_MEMORY;
1028 for(lrdn = first; lrdn ; lrdn = lrdn->
next) {
1030 if (lrdn->
next && !strcmp(lrdn->
name,
"dc")) {
1031 strcat((
char *)ent->
dnufn,
".");
1034 strcat((
char *)ent->
dnufn,
", ");
1041 if (!(ent->
attrs = attr2bl(ld, message, &ent->
first_attr, b64enc, &res))) {
1050 *err = LDAP_SUCCESS;
1060 if (!entry || !attr) {
1078 if (!results || !entry) {
1097 if (!results || !dn) {
1109 if (!entry || !entry->
attrs) {
1122 if (!(mod =
objalloc(
sizeof(*mod), free_modify))) {
1132 for(cnt=0; cnt < 3; cnt++) {
1145 if (!(modr =
objalloc(
sizeof(*modr), free_modreq))) {
1162 case LDAP_MOD_REPLACE:
1165 case LDAP_MOD_DELETE:
1174 if (!(modr = new_modreq(bl, attr))) {
1181 static int add_modifyval(
struct ldap_modreq *modr,
const char *value) {
1184 if (!(newval =
objalloc(
sizeof(*newval), free_modval))) {
1189 if (!newval->
value) {
1195 modr->
first = newval;
1201 modr->
last = newval;
1216 if (!(modr = getmodreq(lmod, attr, LDAP_MOD_DELETE))) {
1220 va_start(a_list, attr);
1221 while((val = va_arg(a_list,
void *))) {
1222 if (add_modifyval(modr, val)) {
1243 if (!(modr = getmodreq(lmod, attr, LDAP_MOD_ADD))) {
1247 va_start(a_list, attr);
1248 while((val = va_arg(a_list,
void *))) {
1249 if (add_modifyval(modr, val)) {
1270 if (!(modr = getmodreq(lmod, attr, LDAP_MOD_REPLACE))) {
1274 va_start(a_list, attr);
1275 while((val = va_arg(a_list,
void *))) {
1276 if (add_modifyval(modr, val)) {
1287 static LDAPMod *ldap_reqtoarr(
struct ldap_modreq *modr,
int type) {
1292 if (!(modi = calloc(
sizeof(LDAPMod), 1))) {
1296 if (!(modi->mod_values = calloc(
sizeof(
void *), modr->
cnt+1))) {
1303 modi->mod_op = LDAP_MOD_REPLACE;
1306 modi->mod_op = LDAP_MOD_DELETE;
1309 modi->mod_op = LDAP_MOD_ADD;
1317 if (!(modi->mod_type = strdup(modr->
attr))) {
1322 mval = (
const char **)modi->mod_values;
1323 for(modv = modr->
first; modv; modv=modv->
next) {
1324 if (!(*mval = strdup(modv->
value))) {
1325 ldap_mods_free(&modi, 0);
1342 LDAPMod **modarr, **tmp, *item;
1343 int cnt, tot=0, res;
1346 return LDAP_UNAVAILABLE;
1349 for(cnt = 0; cnt < 3; cnt++) {
1352 tmp = modarr = calloc(
sizeof(
void *), (tot+1));
1354 for(cnt = 0; cnt < 3; cnt++) {
1357 if (!(item = ldap_reqtoarr(modr, cnt))) {
1358 ldap_mods_free(modarr, 1);
1360 return LDAP_NO_MEMORY;
1371 res = ldap_modify_ext_s(ld->
ldap, lmod->
dn, modarr, ld->
sctrlsp, NULL);
1373 ldap_mods_free(modarr, 1);
1389 return LDAP_NO_MEMORY;
1393 return LDAP_NO_MEMORY;
1421 return LDAP_NO_MEMORY;
1426 return LDAP_NO_MEMORY;
1446 return LDAP_NO_MEMORY;
1451 return LDAP_NO_MEMORY;
1465 if (!(mod =
objalloc(
sizeof(*mod), free_add))) {
1488 if (!(modr = new_modreq(bl, attr))) {
1505 if (!(modr = getaddreq(ladd, attr))) {
1509 va_start(a_list, attr);
1510 while((val = va_arg(a_list,
void *))) {
1511 if (add_modifyval(modr, val)) {
1529 LDAPMod **modarr, **tmp, *item;
1533 tmp = modarr = calloc(
sizeof(
void *), (tot+1));
1537 if (!(item = ldap_reqtoarr(modr, -1))) {
1538 ldap_mods_free(modarr, 1);
1539 return LDAP_NO_MEMORY;
1549 res = ldap_modify_ext_s(ld->
ldap, ladd->
dn, modarr, ld->
sctrlsp, NULL);
1551 ldap_mods_free(modarr, 1);
1559 struct ldap_results *_dtsldapsearch(
struct ldap_conn *ldap,
const char *base,
int scope,
const char *filter,
char **attrs,
int b64enc,
int *err) {
1560 struct timeval timeout;
1563 LDAPMessage *result, *message = NULL;
1564 int res = LDAP_SUCCESS;
1568 *err = LDAP_UNAVAILABLE;
1576 if ((results =
objalloc(
sizeof(*results), free_result))) {
1580 timeout.tv_sec = ldap->
timelim;
1581 timeout.tv_usec = 0;
1584 if (!results || !results->
entries ||
1585 (res = ldap_search_ext_s(ldap->
ldap, base, scope, filter, attrs, 0, ldap->
sctrlsp, NULL, &timeout, ldap->
limit, &result))) {
1589 ldap_msgfree(result);
1591 *err = (!results || !results->
entries) ? LDAP_NO_MEMORY : res;
1604 if ((results->
count = ldap_count(ldap->
ldap, result, err)) < 0) {
1607 ldap_msgfree(result);
1611 while((lent = ldap_getent(ldap->
ldap, &message, result, b64enc, err))) {
1616 res = LDAP_NO_MEMORY;
1630 ldap_msgfree(result);
int ldap_mod_remattr(struct ldap_conn *ldap, const char *dn, const char *attr)
Delete a attribute from a DN.
SSL not attempted at all.
void ldap_unref_attr(struct ldap_entry *entry, struct ldap_attr *attr)
Remove a attribute from a entry.
const char * ldap_errmsg(int res)
Return LDAP error for a ldap error.
int ldap_mod_delattr(struct ldap_conn *ldap, const char *dn, const char *attr, const char *value)
Delete a value from a attribute in a DN.
struct ldap_rdn * next
Next RDN element.
struct ldap_simple * simple
LDAP Simple bind information.
const char * dn
Distingushed Name.
void * create_bucketlist(int bitmask, blisthash hash_function)
int ldap_simplerebind(struct ldap_conn *ld, const char *initialdn, const char *initialpw, const char *base, const char *filter, const char *uidrdn, const char *uid, const char *passwd)
Bind to LDAP connection using rebind.
const char * dn
LDAP distiguished name.
int ldap_simplebind(struct ldap_conn *ld, const char *dn, const char *passwd)
Bind to the connection with simple bind requireing a distingushed name and password.
LDAPControl ** sctrlsp
LDAP control.
const char * authcid
Auth ID.
int ldap_domodify(struct ldap_conn *ld, struct ldap_modify *lmod)
Apply the modification to the server.
int objref(void *data)
Reference a object.
const char * mech
SASL Mechanisim.
struct ldap_results * ldap_search_base(struct ldap_conn *ld, const char *base, const char *filter, int b64enc, int *res,...)
Search LDAP connection base.
struct ldap_attr * first_attr
First attr (head of list).
struct ldap_add * ldap_addinit(const char *dn)
Create a reference to add a new DN.
struct ldap_entry * ldap_getentry(struct ldap_results *results, const char *dn)
Find and return the entry from the results for a specific dn.
struct ldap_modval * last
Linked list tail.
char * buffer
Value buffer.
int objlock(void *data)
Lock the reference.
struct bucket_list * bl
bucket containing item to add
ldap_starttls
SSL connection requirements.
const char * attr
Attribute modified.
int ldap_mod_repattr(struct ldap_conn *ldap, const char *dn, const char *attr, const char *value)
Replace the value of a attribute in a DN.
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
int count
Number of entries.
const char * dn
Distingushed name.
int bucket_list_cnt(struct bucket_list *blist)
Return number of items in the list.
const char * name
RDN element name.
struct ldap_attrval ** vals
Attribute value array.
const char * realm
SASL Realm.
struct bucket_list * bl[3]
Bucket list containg modify / modify_add / delete requests.
Linked list of mod values.
void ldap_unref_entry(struct ldap_results *results, struct ldap_entry *entry)
Remove a entry from a result.
int objcnt(void *data)
Return current reference count.
void * next_bucket_loop(struct bucket_loop *bloop)
Return a reference to the next item in the list this could be the first item.
const char * authzid
Proxy auth ID.
struct ldap_modval * next
Next Value.
struct ldap_modify * ldap_modifyinit(const char *dn)
Create a modification reference for a DN.
struct ldap_rdn * prev
Previous RDN element.
DTS Application library API Include file.
struct sasl_defaults * sasl
SASL auth information.
int ldap_mod_rep(struct ldap_modify *lmod, const char *attr,...)
Replace a attribute.
LDAP Relative distingushed name linked list.
int ldap_mod_addattr(struct ldap_conn *ldap, const char *dn, const char *attr, const char *value)
Add a value for a attribute in a DN.
struct ldap_entry * first_entry
Linked list of entries.
int rdncnt
RDN element count.
struct ldap_entry * prev
Previous entry.
const char * passwd
Password.
int ldap_saslbind(struct ldap_conn *ld, const char *mech, const char *realm, const char *authcid, const char *passwd, const char *authzid)
Bind to the server with SASL.
int ldap_mod_del(struct ldap_modify *lmod, const char *attr,...)
Delete values from a attribute.
struct berval * cred
Credentials (password).
SASL Paramaters used in authentification.
int ldap_mod_add(struct ldap_modify *lmod, const char *attr,...)
Add values to a attribute.
struct ldap_attr * ldap_getattr(struct ldap_entry *entry, const char *attr)
Find and return attribute in a entry.
struct ldap_results * ldap_search_one(struct ldap_conn *ld, const char *base, const char *filter, int b64enc, int *res,...)
Search LDAP connection one level.
ldap_attrtype
LDAP attribute types.
const char * name
Name of attribute.
struct ldap_entry * next
Next entry.
int ldap_doadd(struct ldap_conn *ld, struct ldap_add *ladd)
Write new DN to server.
struct ldap_conn * ldap_connect(const char *uri, enum ldap_starttls starttls, int timelimit, int limit, int debug, int *err)
Connect to a LDAP server.
int objunlock(void *data)
Unlock a reference.
struct bucket_list * attrs
Bucket list of attributes.
const char * value
RDN element value.
enum ldap_attrtype type
Data type stored in buffer.
struct ldap_modval * first
Linked list head.
struct ldap_results * ldap_search_sub(struct ldap_conn *ld, const char *base, const char *filter, int b64enc, int *res,...)
Search LDAP connection subtree.
const char * dn
Distingushed name.
#define jenhash(key, length, initval)
Define jenhash as hashlittle on big endian it should be hashbig.
char * b64enc(const char *message, int nonl)
Base 64 encode a string.
struct ldap_attr * next
Next attribute.
#define ALLOC_CONST(const_var, val)
Macro to assign values to char const.
int objsize(void *data)
Size requested for data.
const char * dnufn
LDAP user format distingushed name.
struct bucket_list * entries
Bucket list of entries.
int addtobucket(struct bucket_list *blist, void *data)
Add a reference to the bucketlist.
void * bucket_list_find_key(struct bucket_list *list, const void *key)
Find and return a reference to a item matching supplied key.
void remove_bucket_item(struct bucket_list *blist, void *data)
Remove and unreference a item from the list.
struct ldap_rdn ** rdn
RDN element array.
int objunref(void *data)
Drop reference held.
char * b64enc_buf(const char *message, uint32_t len, int nonl)
Base 64 encode a buffer.
int ldap_add_attr(struct ldap_add *ladd, const char *attr,...)
Add a attribute to new DN.
struct bucket_loop * init_bucket_loop(struct bucket_list *blist)
Create a bucket list iterator to safely iterate the list.
struct ldap_attr * prev
Previous attribute.
Bucket list, hold hashed objects in buckets.