1 /* $NetBSD: hdb-ldap.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $ */
4 * Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd.
5 * Copyright (c) 2004, Andrew Bartlett.
6 * Copyright (c) 2003 - 2008, Kungliga Tekniska Högskolan.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of PADL Software nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 static krb5_error_code
LDAP__connect(krb5_context context
, HDB
*);
47 static krb5_error_code
LDAP_close(krb5_context context
, HDB
*);
49 static krb5_error_code
50 LDAP_message2entry(krb5_context context
, HDB
* db
, LDAPMessage
* msg
,
51 int flags
, hdb_entry_ex
* ent
);
53 static const char *default_structural_object
= "account";
54 static char *structural_object
;
55 static krb5_boolean samba_forwardable
;
65 #define HDB2LDAP(db) (((struct hdbldapdb *)(db)->hdb_db)->h_lp)
66 #define HDB2MSGID(db) (((struct hdbldapdb *)(db)->hdb_db)->h_msgid)
67 #define HDBSETMSGID(db,msgid) \
68 do { ((struct hdbldapdb *)(db)->hdb_db)->h_msgid = msgid; } while(0)
69 #define HDB2BASE(dn) (((struct hdbldapdb *)(db)->hdb_db)->h_base)
70 #define HDB2URL(dn) (((struct hdbldapdb *)(db)->hdb_db)->h_url)
71 #define HDB2CREATE(db) (((struct hdbldapdb *)(db)->hdb_db)->h_createbase)
77 static char * krb5kdcentry_attrs
[] = {
84 "krb5KeyVersionNumber",
104 static char *krb5principal_attrs
[] = {
109 "krb5PrincipalRealm",
118 LDAP_no_size_limit(krb5_context context
, LDAP
*lp
)
120 int ret
, limit
= LDAP_NO_LIMIT
;
122 ret
= ldap_set_option(lp
, LDAP_OPT_SIZELIMIT
, (const void *)&limit
);
123 if (ret
!= LDAP_SUCCESS
) {
124 krb5_set_error_message(context
, HDB_ERR_BADVERSION
,
125 "ldap_set_option: %s",
126 ldap_err2string(ret
));
127 return HDB_ERR_BADVERSION
;
133 check_ldap(krb5_context context
, HDB
*db
, int ret
)
138 case LDAP_SERVER_DOWN
:
139 LDAP_close(context
, db
);
146 static krb5_error_code
147 LDAP__setmod(LDAPMod
*** modlist
, int modop
, const char *attribute
,
152 if (*modlist
== NULL
) {
153 *modlist
= (LDAPMod
**)ber_memcalloc(1, sizeof(LDAPMod
*));
154 if (*modlist
== NULL
)
158 for (cMods
= 0; (*modlist
)[cMods
] != NULL
; cMods
++) {
159 if ((*modlist
)[cMods
]->mod_op
== modop
&&
160 strcasecmp((*modlist
)[cMods
]->mod_type
, attribute
) == 0) {
167 if ((*modlist
)[cMods
] == NULL
) {
170 *modlist
= (LDAPMod
**)ber_memrealloc(*modlist
,
171 (cMods
+ 2) * sizeof(LDAPMod
*));
172 if (*modlist
== NULL
)
175 (*modlist
)[cMods
] = (LDAPMod
*)ber_memalloc(sizeof(LDAPMod
));
176 if ((*modlist
)[cMods
] == NULL
)
179 mod
= (*modlist
)[cMods
];
181 mod
->mod_type
= ber_strdup(attribute
);
182 if (mod
->mod_type
== NULL
) {
184 (*modlist
)[cMods
] = NULL
;
188 if (modop
& LDAP_MOD_BVALUES
) {
189 mod
->mod_bvalues
= NULL
;
191 mod
->mod_values
= NULL
;
194 (*modlist
)[cMods
+ 1] = NULL
;
200 static krb5_error_code
201 LDAP_addmod_len(LDAPMod
*** modlist
, int modop
, const char *attribute
,
202 unsigned char *value
, size_t len
)
207 ret
= LDAP__setmod(modlist
, modop
| LDAP_MOD_BVALUES
, attribute
, &cMods
);
214 bv
= (*modlist
)[cMods
]->mod_bvalues
;
216 for (i
= 0; bv
[i
] != NULL
; i
++)
218 bv
= ber_memrealloc(bv
, (i
+ 2) * sizeof(*bv
));
220 bv
= ber_memalloc(2 * sizeof(*bv
));
224 (*modlist
)[cMods
]->mod_bvalues
= bv
;
226 bv
[i
] = ber_memalloc(sizeof(**bv
));;
230 bv
[i
]->bv_val
= (void *)value
;
239 static krb5_error_code
240 LDAP_addmod(LDAPMod
*** modlist
, int modop
, const char *attribute
,
246 ret
= LDAP__setmod(modlist
, modop
, attribute
, &cMods
);
253 bv
= (*modlist
)[cMods
]->mod_values
;
255 for (i
= 0; bv
[i
] != NULL
; i
++)
257 bv
= ber_memrealloc(bv
, (i
+ 2) * sizeof(*bv
));
259 bv
= ber_memalloc(2 * sizeof(*bv
));
263 (*modlist
)[cMods
]->mod_values
= bv
;
265 bv
[i
] = ber_strdup(value
);
275 static krb5_error_code
276 LDAP_addmod_generalized_time(LDAPMod
*** mods
, int modop
,
277 const char *attribute
, KerberosTime
* time
)
282 /* XXX not threadsafe */
284 strftime(buf
, sizeof(buf
), "%Y%m%d%H%M%SZ", tm
);
286 return LDAP_addmod(mods
, modop
, attribute
, buf
);
289 static krb5_error_code
290 LDAP_addmod_integer(krb5_context context
,
291 LDAPMod
*** mods
, int modop
,
292 const char *attribute
, unsigned long l
)
297 ret
= asprintf(&buf
, "%ld", l
);
299 krb5_set_error_message(context
, ENOMEM
,
300 "asprintf: out of memory:");
303 ret
= LDAP_addmod(mods
, modop
, attribute
, buf
);
308 static krb5_error_code
309 LDAP_get_string_value(HDB
* db
, LDAPMessage
* entry
,
310 const char *attribute
, char **ptr
)
312 struct berval
**vals
;
314 vals
= ldap_get_values_len(HDB2LDAP(db
), entry
, attribute
);
315 if (vals
== NULL
|| vals
[0] == NULL
) {
317 return HDB_ERR_NOENTRY
;
320 *ptr
= malloc(vals
[0]->bv_len
+ 1);
322 ldap_value_free_len(vals
);
326 memcpy(*ptr
, vals
[0]->bv_val
, vals
[0]->bv_len
);
327 (*ptr
)[vals
[0]->bv_len
] = 0;
329 ldap_value_free_len(vals
);
334 static krb5_error_code
335 LDAP_get_integer_value(HDB
* db
, LDAPMessage
* entry
,
336 const char *attribute
, int *ptr
)
341 ret
= LDAP_get_string_value(db
, entry
, attribute
, &val
);
349 static krb5_error_code
350 LDAP_get_generalized_time_value(HDB
* db
, LDAPMessage
* entry
,
351 const char *attribute
, KerberosTime
* kt
)
359 ret
= LDAP_get_string_value(db
, entry
, attribute
, &gentime
);
363 tmp
= strptime(gentime
, "%Y%m%d%H%M%SZ", &tm
);
366 return HDB_ERR_NOENTRY
;
377 bervalstrcmp(struct berval
*v
, const char *str
)
379 size_t len
= strlen(str
);
380 return (v
->bv_len
== len
) && strncasecmp(str
, (char *)v
->bv_val
, len
) == 0;
384 static krb5_error_code
385 LDAP_entry2mods(krb5_context context
, HDB
* db
, hdb_entry_ex
* ent
,
386 LDAPMessage
* msg
, LDAPMod
*** pmods
)
389 krb5_boolean is_new_entry
;
391 LDAPMod
**mods
= NULL
;
393 unsigned long oflags
, nflags
;
396 krb5_boolean is_samba_account
= FALSE
;
397 krb5_boolean is_account
= FALSE
;
398 krb5_boolean is_heimdal_entry
= FALSE
;
399 krb5_boolean is_heimdal_principal
= FALSE
;
401 struct berval
**vals
;
407 ret
= LDAP_message2entry(context
, db
, msg
, 0, &orig
);
411 is_new_entry
= FALSE
;
413 vals
= ldap_get_values_len(HDB2LDAP(db
), msg
, "objectClass");
415 int num_objectclasses
= ldap_count_values_len(vals
);
416 for (i
=0; i
< num_objectclasses
; i
++) {
417 if (bervalstrcmp(vals
[i
], "sambaSamAccount"))
418 is_samba_account
= TRUE
;
419 else if (bervalstrcmp(vals
[i
], structural_object
))
421 else if (bervalstrcmp(vals
[i
], "krb5Principal"))
422 is_heimdal_principal
= TRUE
;
423 else if (bervalstrcmp(vals
[i
], "krb5KDCEntry"))
424 is_heimdal_entry
= TRUE
;
426 ldap_value_free_len(vals
);
430 * If this is just a "account" entry and no other objectclass
431 * is hanging on this entry, it's really a new entry.
433 if (is_samba_account
== FALSE
&& is_heimdal_principal
== FALSE
&&
434 is_heimdal_entry
== FALSE
) {
435 if (is_account
== TRUE
) {
438 ret
= HDB_ERR_NOENTRY
;
447 /* to make it perfectly obvious we're depending on
448 * orig being intiialized to zero */
449 memset(&orig
, 0, sizeof(orig
));
451 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass", "top");
455 /* account is the structural object class */
456 if (is_account
== FALSE
) {
457 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass",
464 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass", "krb5Principal");
465 is_heimdal_principal
= TRUE
;
469 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass", "krb5KDCEntry");
470 is_heimdal_entry
= TRUE
;
476 krb5_principal_compare(context
, ent
->entry
.principal
, orig
.entry
.principal
)
479 if (is_heimdal_principal
|| is_heimdal_entry
) {
481 ret
= krb5_unparse_name(context
, ent
->entry
.principal
, &tmp
);
485 ret
= LDAP_addmod(&mods
, LDAP_MOD_REPLACE
,
486 "krb5PrincipalName", tmp
);
494 if (is_account
|| is_samba_account
) {
495 ret
= krb5_unparse_name_short(context
, ent
->entry
.principal
, &tmp
);
498 ret
= LDAP_addmod(&mods
, LDAP_MOD_REPLACE
, "uid", tmp
);
507 if (is_heimdal_entry
&& (ent
->entry
.kvno
!= orig
.entry
.kvno
|| is_new_entry
)) {
508 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
509 "krb5KeyVersionNumber",
515 if (is_heimdal_entry
&& ent
->entry
.valid_start
) {
516 if (orig
.entry
.valid_end
== NULL
517 || (*(ent
->entry
.valid_start
) != *(orig
.entry
.valid_start
))) {
518 ret
= LDAP_addmod_generalized_time(&mods
, LDAP_MOD_REPLACE
,
520 ent
->entry
.valid_start
);
526 if (ent
->entry
.valid_end
) {
527 if (orig
.entry
.valid_end
== NULL
|| (*(ent
->entry
.valid_end
) != *(orig
.entry
.valid_end
))) {
528 if (is_heimdal_entry
) {
529 ret
= LDAP_addmod_generalized_time(&mods
, LDAP_MOD_REPLACE
,
531 ent
->entry
.valid_end
);
535 if (is_samba_account
) {
536 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
538 *(ent
->entry
.valid_end
));
545 if (ent
->entry
.pw_end
) {
546 if (orig
.entry
.pw_end
== NULL
|| (*(ent
->entry
.pw_end
) != *(orig
.entry
.pw_end
))) {
547 if (is_heimdal_entry
) {
548 ret
= LDAP_addmod_generalized_time(&mods
, LDAP_MOD_REPLACE
,
555 if (is_samba_account
) {
556 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
557 "sambaPwdMustChange",
558 *(ent
->entry
.pw_end
));
566 #if 0 /* we we have last_pw_change */
567 if (is_samba_account
&& ent
->entry
.last_pw_change
) {
568 if (orig
.entry
.last_pw_change
== NULL
|| (*(ent
->entry
.last_pw_change
) != *(orig
.entry
.last_pw_change
))) {
569 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
571 *(ent
->entry
.last_pw_change
));
578 if (is_heimdal_entry
&& ent
->entry
.max_life
) {
579 if (orig
.entry
.max_life
== NULL
580 || (*(ent
->entry
.max_life
) != *(orig
.entry
.max_life
))) {
582 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
584 *(ent
->entry
.max_life
));
590 if (is_heimdal_entry
&& ent
->entry
.max_renew
) {
591 if (orig
.entry
.max_renew
== NULL
592 || (*(ent
->entry
.max_renew
) != *(orig
.entry
.max_renew
))) {
594 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
596 *(ent
->entry
.max_renew
));
602 oflags
= HDBFlags2int(orig
.entry
.flags
);
603 nflags
= HDBFlags2int(ent
->entry
.flags
);
605 if (is_heimdal_entry
&& oflags
!= nflags
) {
607 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
614 /* Remove keys if they exists, and then replace keys. */
615 if (!is_new_entry
&& orig
.entry
.keys
.len
> 0) {
616 vals
= ldap_get_values_len(HDB2LDAP(db
), msg
, "krb5Key");
618 ldap_value_free_len(vals
);
620 ret
= LDAP_addmod(&mods
, LDAP_MOD_DELETE
, "krb5Key", NULL
);
626 for (i
= 0; i
< ent
->entry
.keys
.len
; i
++) {
629 && ent
->entry
.keys
.val
[i
].key
.keytype
== ETYPE_ARCFOUR_HMAC_MD5
) {
632 time_t now
= time(NULL
);
634 /* the key might have been 'sealed', but samba passwords
635 are clear in the directory */
636 ret
= hdb_unseal_key(context
, db
, &ent
->entry
.keys
.val
[i
]);
640 nt
= ent
->entry
.keys
.val
[i
].key
.keyvalue
.data
;
641 /* store in ntPassword, not krb5key */
642 ret
= hex_encode(nt
, 16, &ntHexPassword
);
645 krb5_set_error_message(context
, ret
, "hdb-ldap: failed to "
649 ret
= LDAP_addmod(&mods
, LDAP_MOD_REPLACE
, "sambaNTPassword",
654 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_REPLACE
,
655 "sambaPwdLastSet", now
);
659 /* have to kill the LM passwod if it exists */
660 vals
= ldap_get_values_len(HDB2LDAP(db
), msg
, "sambaLMPassword");
662 ldap_value_free_len(vals
);
663 ret
= LDAP_addmod(&mods
, LDAP_MOD_DELETE
,
664 "sambaLMPassword", NULL
);
669 } else if (is_heimdal_entry
) {
671 size_t len
, buf_size
;
673 ASN1_MALLOC_ENCODE(Key
, buf
, buf_size
, &ent
->entry
.keys
.val
[i
], &len
, ret
);
677 krb5_abortx(context
, "internal error in ASN.1 encoder");
679 /* addmod_len _owns_ the key, doesn't need to copy it */
680 ret
= LDAP_addmod_len(&mods
, LDAP_MOD_ADD
, "krb5Key", buf
, len
);
686 if (ent
->entry
.etypes
) {
687 int add_krb5EncryptionType
= 0;
690 * Only add/modify krb5EncryptionType if it's a new heimdal
691 * entry or krb5EncryptionType already exists on the entry.
695 vals
= ldap_get_values_len(HDB2LDAP(db
), msg
, "krb5EncryptionType");
697 ldap_value_free_len(vals
);
698 ret
= LDAP_addmod(&mods
, LDAP_MOD_DELETE
, "krb5EncryptionType",
702 add_krb5EncryptionType
= 1;
704 } else if (is_heimdal_entry
)
705 add_krb5EncryptionType
= 1;
707 if (add_krb5EncryptionType
) {
708 for (i
= 0; i
< ent
->entry
.etypes
->len
; i
++) {
709 if (is_samba_account
&&
710 ent
->entry
.keys
.val
[i
].key
.keytype
== ETYPE_ARCFOUR_HMAC_MD5
)
713 } else if (is_heimdal_entry
) {
714 ret
= LDAP_addmod_integer(context
, &mods
, LDAP_MOD_ADD
,
715 "krb5EncryptionType",
716 ent
->entry
.etypes
->val
[i
]);
731 else if (mods
!= NULL
) {
732 ldap_mods_free(mods
, 1);
737 hdb_free_entry(context
, &orig
);
742 static krb5_error_code
743 LDAP_dn2principal(krb5_context context
, HDB
* db
, const char *dn
,
744 krb5_principal
* principal
)
748 const char *filter
= "(objectClass=krb5Principal)";
749 LDAPMessage
*res
= NULL
, *e
;
752 ret
= LDAP_no_size_limit(context
, HDB2LDAP(db
));
756 rc
= ldap_search_ext_s(HDB2LDAP(db
), dn
, LDAP_SCOPE_SUBTREE
,
757 filter
, krb5principal_attrs
, 0,
760 if (check_ldap(context
, db
, rc
)) {
761 ret
= HDB_ERR_NOENTRY
;
762 krb5_set_error_message(context
, ret
, "ldap_search_ext_s: "
763 "filter: %s error: %s",
764 filter
, ldap_err2string(rc
));
768 e
= ldap_first_entry(HDB2LDAP(db
), res
);
770 ret
= HDB_ERR_NOENTRY
;
774 ret
= LDAP_get_string_value(db
, e
, "krb5PrincipalName", &p
);
776 ret
= HDB_ERR_NOENTRY
;
780 ret
= krb5_parse_name(context
, p
, principal
);
791 need_quote(unsigned char c
)
802 const static char hexchar
[] = "0123456789ABCDEF";
804 static krb5_error_code
805 escape_value(krb5_context context
, const unsigned char *unquoted
, char **quoted
)
809 for (i
= 0, len
= 0; unquoted
[i
] != '\0'; i
++, len
++) {
810 if (need_quote((unsigned char)unquoted
[i
]))
814 *quoted
= malloc(len
+ 1);
815 if (*quoted
== NULL
) {
816 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
820 for (i
= 0; unquoted
[0] ; unquoted
++) {
821 if (need_quote((unsigned char *)unquoted
[0])) {
822 (*quoted
)[i
++] = '\\';
823 (*quoted
)[i
++] = hexchar
[(unquoted
[0] >> 4) & 0xf];
824 (*quoted
)[i
++] = hexchar
[(unquoted
[0] ) & 0xf];
826 (*quoted
)[i
++] = (char)unquoted
[0];
833 static krb5_error_code
834 LDAP__lookup_princ(krb5_context context
,
836 const char *princname
,
842 char *quote
, *filter
= NULL
;
844 ret
= LDAP__connect(context
, db
);
849 * Quote searches that contain filter language, this quote
850 * searches for *@REALM, which takes very long time.
853 ret
= escape_value(context
, princname
, "e
);
857 rc
= asprintf(&filter
,
858 "(&(objectClass=krb5Principal)(krb5PrincipalName=%s))",
864 krb5_set_error_message(context
, ret
, "malloc: out of memory");
868 ret
= LDAP_no_size_limit(context
, HDB2LDAP(db
));
872 rc
= ldap_search_ext_s(HDB2LDAP(db
), HDB2BASE(db
),
873 LDAP_SCOPE_SUBTREE
, filter
,
874 krb5kdcentry_attrs
, 0,
877 if (check_ldap(context
, db
, rc
)) {
878 ret
= HDB_ERR_NOENTRY
;
879 krb5_set_error_message(context
, ret
, "ldap_search_ext_s: "
880 "filter: %s - error: %s",
881 filter
, ldap_err2string(rc
));
885 if (userid
&& ldap_count_entries(HDB2LDAP(db
), *msg
) == 0) {
891 ret
= escape_value(context
, userid
, "e
);
895 rc
= asprintf(&filter
,
896 "(&(|(objectClass=sambaSamAccount)(objectClass=%s))(uid=%s))",
897 structural_object
, quote
);
901 krb5_set_error_message(context
, ret
, "asprintf: out of memory");
905 ret
= LDAP_no_size_limit(context
, HDB2LDAP(db
));
909 rc
= ldap_search_ext_s(HDB2LDAP(db
), HDB2BASE(db
), LDAP_SCOPE_SUBTREE
,
910 filter
, krb5kdcentry_attrs
, 0,
913 if (check_ldap(context
, db
, rc
)) {
914 ret
= HDB_ERR_NOENTRY
;
915 krb5_set_error_message(context
, ret
,
916 "ldap_search_ext_s: filter: %s error: %s",
917 filter
, ldap_err2string(rc
));
931 static krb5_error_code
932 LDAP_principal2message(krb5_context context
, HDB
* db
,
933 krb5_const_principal princ
, LDAPMessage
** msg
)
935 char *name
, *name_short
= NULL
;
941 ret
= krb5_unparse_name(context
, princ
, &name
);
945 ret
= krb5_get_default_realms(context
, &r0
);
950 for (r
= r0
; *r
!= NULL
; r
++) {
951 if(strcmp(krb5_principal_get_realm(context
, princ
), *r
) == 0) {
952 ret
= krb5_unparse_name_short(context
, princ
, &name_short
);
954 krb5_free_host_realm(context
, r0
);
961 krb5_free_host_realm(context
, r0
);
963 ret
= LDAP__lookup_princ(context
, db
, name
, name_short
, msg
);
971 * Construct an hdb_entry from a directory entry.
973 static krb5_error_code
974 LDAP_message2entry(krb5_context context
, HDB
* db
, LDAPMessage
* msg
,
975 int flags
, hdb_entry_ex
* ent
)
977 char *unparsed_name
= NULL
, *dn
= NULL
, *ntPasswordIN
= NULL
;
978 char *samba_acct_flags
= NULL
;
979 struct berval
**keys
;
980 struct berval
**vals
;
981 int tmp
, tmp_time
, i
, ret
, have_arcfour
= 0;
983 memset(ent
, 0, sizeof(*ent
));
984 ent
->entry
.flags
= int2HDBFlags(0);
986 ret
= LDAP_get_string_value(db
, msg
, "krb5PrincipalName", &unparsed_name
);
988 ret
= krb5_parse_name(context
, unparsed_name
, &ent
->entry
.principal
);
992 ret
= LDAP_get_string_value(db
, msg
, "uid",
995 ret
= krb5_parse_name(context
, unparsed_name
, &ent
->entry
.principal
);
999 krb5_set_error_message(context
, HDB_ERR_NOENTRY
,
1000 "hdb-ldap: ldap entry missing"
1002 return HDB_ERR_NOENTRY
;
1008 ret
= LDAP_get_integer_value(db
, msg
, "krb5KeyVersionNumber",
1011 ent
->entry
.kvno
= 0;
1013 ent
->entry
.kvno
= integer
;
1016 keys
= ldap_get_values_len(HDB2LDAP(db
), msg
, "krb5Key");
1021 ent
->entry
.keys
.len
= ldap_count_values_len(keys
);
1022 ent
->entry
.keys
.val
= (Key
*) calloc(ent
->entry
.keys
.len
, sizeof(Key
));
1023 if (ent
->entry
.keys
.val
== NULL
) {
1025 krb5_set_error_message(context
, ret
, "calloc: out of memory");
1028 for (i
= 0; i
< ent
->entry
.keys
.len
; i
++) {
1029 decode_Key((unsigned char *) keys
[i
]->bv_val
,
1030 (size_t) keys
[i
]->bv_len
, &ent
->entry
.keys
.val
[i
], &l
);
1036 * This violates the ASN1 but it allows a principal to
1037 * be related to a general directory entry without creating
1038 * the keys. Hopefully it's OK.
1040 ent
->entry
.keys
.len
= 0;
1041 ent
->entry
.keys
.val
= NULL
;
1043 ret
= HDB_ERR_NOENTRY
;
1048 vals
= ldap_get_values_len(HDB2LDAP(db
), msg
, "krb5EncryptionType");
1052 ent
->entry
.etypes
= malloc(sizeof(*(ent
->entry
.etypes
)));
1053 if (ent
->entry
.etypes
== NULL
) {
1055 krb5_set_error_message(context
, ret
,"malloc: out of memory");
1058 ent
->entry
.etypes
->len
= ldap_count_values_len(vals
);
1059 ent
->entry
.etypes
->val
= calloc(ent
->entry
.etypes
->len
, sizeof(int));
1060 if (ent
->entry
.etypes
->val
== NULL
) {
1062 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1063 ent
->entry
.etypes
->len
= 0;
1066 for (i
= 0; i
< ent
->entry
.etypes
->len
; i
++) {
1069 buf
= malloc(vals
[i
]->bv_len
+ 1);
1072 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1075 memcpy(buf
, vals
[i
]->bv_val
, vals
[i
]->bv_len
);
1076 buf
[vals
[i
]->bv_len
] = '\0';
1077 ent
->entry
.etypes
->val
[i
] = atoi(buf
);
1080 ldap_value_free_len(vals
);
1083 for (i
= 0; i
< ent
->entry
.keys
.len
; i
++) {
1084 if (ent
->entry
.keys
.val
[i
].key
.keytype
== ETYPE_ARCFOUR_HMAC_MD5
) {
1090 /* manually construct the NT (type 23) key */
1091 ret
= LDAP_get_string_value(db
, msg
, "sambaNTPassword", &ntPasswordIN
);
1092 if (ret
== 0 && have_arcfour
== 0) {
1097 keys
= realloc(ent
->entry
.keys
.val
,
1098 (ent
->entry
.keys
.len
+ 1) * sizeof(ent
->entry
.keys
.val
[0]));
1102 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1105 ent
->entry
.keys
.val
= keys
;
1106 memset(&ent
->entry
.keys
.val
[ent
->entry
.keys
.len
], 0, sizeof(Key
));
1107 ent
->entry
.keys
.val
[ent
->entry
.keys
.len
].key
.keytype
= ETYPE_ARCFOUR_HMAC_MD5
;
1108 ret
= krb5_data_alloc (&ent
->entry
.keys
.val
[ent
->entry
.keys
.len
].key
.keyvalue
, 16);
1110 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1115 ret
= hex_decode(ntPasswordIN
,
1116 ent
->entry
.keys
.val
[ent
->entry
.keys
.len
].key
.keyvalue
.data
, 16);
1117 ent
->entry
.keys
.len
++;
1119 if (ent
->entry
.etypes
== NULL
) {
1120 ent
->entry
.etypes
= malloc(sizeof(*(ent
->entry
.etypes
)));
1121 if (ent
->entry
.etypes
== NULL
) {
1123 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1126 ent
->entry
.etypes
->val
= NULL
;
1127 ent
->entry
.etypes
->len
= 0;
1130 for (i
= 0; i
< ent
->entry
.etypes
->len
; i
++)
1131 if (ent
->entry
.etypes
->val
[i
] == ETYPE_ARCFOUR_HMAC_MD5
)
1133 /* If there is no ARCFOUR enctype, add one */
1134 if (i
== ent
->entry
.etypes
->len
) {
1135 etypes
= realloc(ent
->entry
.etypes
->val
,
1136 (ent
->entry
.etypes
->len
+ 1) *
1137 sizeof(ent
->entry
.etypes
->val
[0]));
1138 if (etypes
== NULL
) {
1140 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1143 ent
->entry
.etypes
->val
= etypes
;
1144 ent
->entry
.etypes
->val
[ent
->entry
.etypes
->len
] =
1145 ETYPE_ARCFOUR_HMAC_MD5
;
1146 ent
->entry
.etypes
->len
++;
1150 ret
= LDAP_get_generalized_time_value(db
, msg
, "createTimestamp",
1151 &ent
->entry
.created_by
.time
);
1153 ent
->entry
.created_by
.time
= time(NULL
);
1155 ent
->entry
.created_by
.principal
= NULL
;
1157 if (flags
& HDB_F_ADMIN_DATA
) {
1158 ret
= LDAP_get_string_value(db
, msg
, "creatorsName", &dn
);
1160 LDAP_dn2principal(context
, db
, dn
, &ent
->entry
.created_by
.principal
);
1164 ent
->entry
.modified_by
= calloc(1, sizeof(*ent
->entry
.modified_by
));
1165 if (ent
->entry
.modified_by
== NULL
) {
1167 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1171 ret
= LDAP_get_generalized_time_value(db
, msg
, "modifyTimestamp",
1172 &ent
->entry
.modified_by
->time
);
1174 ret
= LDAP_get_string_value(db
, msg
, "modifiersName", &dn
);
1176 LDAP_dn2principal(context
, db
, dn
, &ent
->entry
.modified_by
->principal
);
1179 free(ent
->entry
.modified_by
);
1180 ent
->entry
.modified_by
= NULL
;
1185 ent
->entry
.valid_start
= malloc(sizeof(*ent
->entry
.valid_start
));
1186 if (ent
->entry
.valid_start
== NULL
) {
1188 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1191 ret
= LDAP_get_generalized_time_value(db
, msg
, "krb5ValidStart",
1192 ent
->entry
.valid_start
);
1195 free(ent
->entry
.valid_start
);
1196 ent
->entry
.valid_start
= NULL
;
1199 ent
->entry
.valid_end
= malloc(sizeof(*ent
->entry
.valid_end
));
1200 if (ent
->entry
.valid_end
== NULL
) {
1202 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1205 ret
= LDAP_get_generalized_time_value(db
, msg
, "krb5ValidEnd",
1206 ent
->entry
.valid_end
);
1209 free(ent
->entry
.valid_end
);
1210 ent
->entry
.valid_end
= NULL
;
1213 ret
= LDAP_get_integer_value(db
, msg
, "sambaKickoffTime", &tmp_time
);
1215 if (ent
->entry
.valid_end
== NULL
) {
1216 ent
->entry
.valid_end
= malloc(sizeof(*ent
->entry
.valid_end
));
1217 if (ent
->entry
.valid_end
== NULL
) {
1219 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1223 *ent
->entry
.valid_end
= tmp_time
;
1226 ent
->entry
.pw_end
= malloc(sizeof(*ent
->entry
.pw_end
));
1227 if (ent
->entry
.pw_end
== NULL
) {
1229 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1232 ret
= LDAP_get_generalized_time_value(db
, msg
, "krb5PasswordEnd",
1236 free(ent
->entry
.pw_end
);
1237 ent
->entry
.pw_end
= NULL
;
1240 ret
= LDAP_get_integer_value(db
, msg
, "sambaPwdLastSet", &tmp_time
);
1244 if (ent
->entry
.pw_end
== NULL
) {
1245 ent
->entry
.pw_end
= malloc(sizeof(*ent
->entry
.pw_end
));
1246 if (ent
->entry
.pw_end
== NULL
) {
1248 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1253 delta
= krb5_config_get_time_default(context
, NULL
,
1256 "password_lifetime",
1258 *ent
->entry
.pw_end
= tmp_time
+ delta
;
1261 ret
= LDAP_get_integer_value(db
, msg
, "sambaPwdMustChange", &tmp_time
);
1263 if (ent
->entry
.pw_end
== NULL
) {
1264 ent
->entry
.pw_end
= malloc(sizeof(*ent
->entry
.pw_end
));
1265 if (ent
->entry
.pw_end
== NULL
) {
1267 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1271 *ent
->entry
.pw_end
= tmp_time
;
1275 ret
= LDAP_get_integer_value(db
, msg
, "sambaPwdLastSet", &tmp_time
);
1277 hdb_entry_set_pw_change_time(context
, &ent
->entry
, tmp_time
);
1282 ent
->entry
.max_life
= malloc(sizeof(*ent
->entry
.max_life
));
1283 if (ent
->entry
.max_life
== NULL
) {
1285 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1288 ret
= LDAP_get_integer_value(db
, msg
, "krb5MaxLife", &max_life
);
1290 free(ent
->entry
.max_life
);
1291 ent
->entry
.max_life
= NULL
;
1293 *ent
->entry
.max_life
= max_life
;
1299 ent
->entry
.max_renew
= malloc(sizeof(*ent
->entry
.max_renew
));
1300 if (ent
->entry
.max_renew
== NULL
) {
1302 krb5_set_error_message(context
, ret
, "malloc: out of memory");
1305 ret
= LDAP_get_integer_value(db
, msg
, "krb5MaxRenew", &max_renew
);
1307 free(ent
->entry
.max_renew
);
1308 ent
->entry
.max_renew
= NULL
;
1310 *ent
->entry
.max_renew
= max_renew
;
1313 ret
= LDAP_get_integer_value(db
, msg
, "krb5KDCFlags", &tmp
);
1317 ent
->entry
.flags
= int2HDBFlags(tmp
);
1319 /* Try and find Samba flags to put into the mix */
1320 ret
= LDAP_get_string_value(db
, msg
, "sambaAcctFlags", &samba_acct_flags
);
1322 /* parse the [UXW...] string:
1326 'H' Homedir required
1328 'U' User account (normal)
1329 'M' MNS logon user account - what is this ?
1330 'W' Workstation account
1333 'X' No Xpiry on password
1334 'I' Interdomain trust account
1339 int flags_len
= strlen(samba_acct_flags
);
1344 if (samba_acct_flags
[0] != '['
1345 || samba_acct_flags
[flags_len
- 1] != ']')
1348 /* Allow forwarding */
1349 if (samba_forwardable
)
1350 ent
->entry
.flags
.forwardable
= TRUE
;
1352 for (i
=0; i
< flags_len
; i
++) {
1353 switch (samba_acct_flags
[i
]) {
1359 /* how to handle no password in kerberos? */
1362 ent
->entry
.flags
.invalid
= TRUE
;
1367 /* temp duplicate */
1368 ent
->entry
.flags
.invalid
= TRUE
;
1371 ent
->entry
.flags
.client
= TRUE
;
1377 ent
->entry
.flags
.server
= TRUE
;
1378 ent
->entry
.flags
.client
= TRUE
;
1381 ent
->entry
.flags
.invalid
= TRUE
;
1384 if (ent
->entry
.pw_end
) {
1385 free(ent
->entry
.pw_end
);
1386 ent
->entry
.pw_end
= NULL
;
1390 ent
->entry
.flags
.server
= TRUE
;
1391 ent
->entry
.flags
.client
= TRUE
;
1396 free(samba_acct_flags
);
1403 free(unparsed_name
);
1406 hdb_free_entry(context
, ent
);
1411 static krb5_error_code
1412 LDAP_close(krb5_context context
, HDB
* db
)
1415 ldap_unbind_ext(HDB2LDAP(db
), NULL
, NULL
);
1416 ((struct hdbldapdb
*)db
->hdb_db
)->h_lp
= NULL
;
1422 static krb5_error_code
1423 LDAP_lock(krb5_context context
, HDB
* db
, int operation
)
1428 static krb5_error_code
1429 LDAP_unlock(krb5_context context
, HDB
* db
)
1434 static krb5_error_code
1435 LDAP_seq(krb5_context context
, HDB
* db
, unsigned flags
, hdb_entry_ex
* entry
)
1437 int msgid
, rc
, parserc
;
1438 krb5_error_code ret
;
1441 msgid
= HDB2MSGID(db
);
1443 return HDB_ERR_NOENTRY
;
1446 rc
= ldap_result(HDB2LDAP(db
), msgid
, LDAP_MSG_ONE
, NULL
, &e
);
1448 case LDAP_RES_SEARCH_REFERENCE
:
1452 case LDAP_RES_SEARCH_ENTRY
:
1453 /* We have an entry. Parse it. */
1454 ret
= LDAP_message2entry(context
, db
, e
, flags
, entry
);
1457 case LDAP_RES_SEARCH_RESULT
:
1458 /* We're probably at the end of the results. If not, abandon. */
1460 ldap_parse_result(HDB2LDAP(db
), e
, NULL
, NULL
, NULL
,
1462 ret
= HDB_ERR_NOENTRY
;
1463 if (parserc
!= LDAP_SUCCESS
1464 && parserc
!= LDAP_MORE_RESULTS_TO_RETURN
) {
1465 krb5_set_error_message(context
, ret
, "ldap_parse_result: %s",
1466 ldap_err2string(parserc
));
1467 ldap_abandon_ext(HDB2LDAP(db
), msgid
, NULL
, NULL
);
1469 HDBSETMSGID(db
, -1);
1471 case LDAP_SERVER_DOWN
:
1473 LDAP_close(context
, db
);
1474 HDBSETMSGID(db
, -1);
1478 /* Some unspecified error (timeout?). Abandon. */
1480 ldap_abandon_ext(HDB2LDAP(db
), msgid
, NULL
, NULL
);
1481 ret
= HDB_ERR_NOENTRY
;
1482 HDBSETMSGID(db
, -1);
1485 } while (rc
== LDAP_RES_SEARCH_REFERENCE
);
1488 if (db
->hdb_master_key_set
&& (flags
& HDB_F_DECRYPT
)) {
1489 ret
= hdb_unseal_keys(context
, db
, &entry
->entry
);
1491 hdb_free_entry(context
, entry
);
1498 static krb5_error_code
1499 LDAP_firstkey(krb5_context context
, HDB
*db
, unsigned flags
,
1500 hdb_entry_ex
*entry
)
1502 krb5_error_code ret
;
1505 ret
= LDAP__connect(context
, db
);
1509 ret
= LDAP_no_size_limit(context
, HDB2LDAP(db
));
1513 ret
= ldap_search_ext(HDB2LDAP(db
), HDB2BASE(db
),
1515 "(|(objectClass=krb5Principal)(objectClass=sambaSamAccount))",
1516 krb5kdcentry_attrs
, 0,
1517 NULL
, NULL
, NULL
, 0, &msgid
);
1519 return HDB_ERR_NOENTRY
;
1521 HDBSETMSGID(db
, msgid
);
1523 return LDAP_seq(context
, db
, flags
, entry
);
1526 static krb5_error_code
1527 LDAP_nextkey(krb5_context context
, HDB
* db
, unsigned flags
,
1528 hdb_entry_ex
* entry
)
1530 return LDAP_seq(context
, db
, flags
, entry
);
1533 static krb5_error_code
1534 LDAP__connect(krb5_context context
, HDB
* db
)
1536 int rc
, version
= LDAP_VERSION3
;
1538 * Empty credentials to do a SASL bind with LDAP. Note that empty
1539 * different from NULL credentials. If you provide NULL
1540 * credentials instead of empty credentials you will get a SASL
1541 * bind in progress message.
1543 struct berval bv
= { 0, "" };
1546 /* connection has been opened. ping server. */
1547 struct sockaddr_un addr
;
1548 socklen_t len
= sizeof(addr
);
1551 if (ldap_get_option(HDB2LDAP(db
), LDAP_OPT_DESC
, &sd
) == 0 &&
1552 getpeername(sd
, (struct sockaddr
*) &addr
, &len
) < 0) {
1553 /* the other end has died. reopen. */
1554 LDAP_close(context
, db
);
1558 if (HDB2LDAP(db
) != NULL
) /* server is UP */
1561 rc
= ldap_initialize(&((struct hdbldapdb
*)db
->hdb_db
)->h_lp
, HDB2URL(db
));
1562 if (rc
!= LDAP_SUCCESS
) {
1563 krb5_set_error_message(context
, HDB_ERR_NOENTRY
, "ldap_initialize: %s",
1564 ldap_err2string(rc
));
1565 return HDB_ERR_NOENTRY
;
1568 rc
= ldap_set_option(HDB2LDAP(db
), LDAP_OPT_PROTOCOL_VERSION
,
1569 (const void *)&version
);
1570 if (rc
!= LDAP_SUCCESS
) {
1571 krb5_set_error_message(context
, HDB_ERR_BADVERSION
,
1572 "ldap_set_option: %s", ldap_err2string(rc
));
1573 LDAP_close(context
, db
);
1574 return HDB_ERR_BADVERSION
;
1577 rc
= ldap_sasl_bind_s(HDB2LDAP(db
), NULL
, "EXTERNAL", &bv
,
1579 if (rc
!= LDAP_SUCCESS
) {
1580 krb5_set_error_message(context
, HDB_ERR_BADVERSION
,
1581 "ldap_sasl_bind_s: %s", ldap_err2string(rc
));
1582 LDAP_close(context
, db
);
1583 return HDB_ERR_BADVERSION
;
1589 static krb5_error_code
1590 LDAP_open(krb5_context context
, HDB
* db
, int flags
, mode_t mode
)
1592 /* Not the right place for this. */
1593 #ifdef HAVE_SIGACTION
1594 struct sigaction sa
;
1597 sa
.sa_handler
= SIG_IGN
;
1598 sigemptyset(&sa
.sa_mask
);
1600 sigaction(SIGPIPE
, &sa
, NULL
);
1602 signal(SIGPIPE
, SIG_IGN
);
1603 #endif /* HAVE_SIGACTION */
1605 return LDAP__connect(context
, db
);
1608 static krb5_error_code
1609 LDAP_fetch_kvno(krb5_context context
, HDB
* db
, krb5_const_principal principal
,
1610 unsigned flags
, krb5_kvno kvno
, hdb_entry_ex
* entry
)
1612 LDAPMessage
*msg
, *e
;
1613 krb5_error_code ret
;
1615 ret
= LDAP_principal2message(context
, db
, principal
, &msg
);
1619 e
= ldap_first_entry(HDB2LDAP(db
), msg
);
1621 ret
= HDB_ERR_NOENTRY
;
1625 ret
= LDAP_message2entry(context
, db
, e
, flags
, entry
);
1627 if (db
->hdb_master_key_set
&& (flags
& HDB_F_DECRYPT
)) {
1628 ret
= hdb_unseal_keys(context
, db
, &entry
->entry
);
1630 hdb_free_entry(context
, entry
);
1640 static krb5_error_code
1641 LDAP_fetch(krb5_context context
, HDB
* db
, krb5_const_principal principal
,
1642 unsigned flags
, hdb_entry_ex
* entry
)
1644 return LDAP_fetch_kvno(context
, db
, principal
,
1645 flags
& (~HDB_F_KVNO_SPECIFIED
), 0, entry
);
1648 static krb5_error_code
1649 LDAP_store(krb5_context context
, HDB
* db
, unsigned flags
,
1650 hdb_entry_ex
* entry
)
1652 LDAPMod
**mods
= NULL
;
1653 krb5_error_code ret
;
1656 LDAPMessage
*msg
= NULL
, *e
= NULL
;
1657 char *dn
= NULL
, *name
= NULL
;
1659 ret
= LDAP_principal2message(context
, db
, entry
->entry
.principal
, &msg
);
1661 e
= ldap_first_entry(HDB2LDAP(db
), msg
);
1663 ret
= krb5_unparse_name(context
, entry
->entry
.principal
, &name
);
1669 ret
= hdb_seal_keys(context
, db
, &entry
->entry
);
1673 /* turn new entry into LDAPMod array */
1674 ret
= LDAP_entry2mods(context
, db
, entry
, e
, &mods
);
1679 ret
= asprintf(&dn
, "krb5PrincipalName=%s,%s", name
, HDB2CREATE(db
));
1682 krb5_set_error_message(context
, ret
, "asprintf: out of memory");
1685 } else if (flags
& HDB_F_REPLACE
) {
1686 /* Entry exists, and we're allowed to replace it. */
1687 dn
= ldap_get_dn(HDB2LDAP(db
), e
);
1689 /* Entry exists, but we're not allowed to replace it. Bail. */
1690 ret
= HDB_ERR_EXISTS
;
1694 /* write entry into directory */
1696 /* didn't exist before */
1697 rc
= ldap_add_ext_s(HDB2LDAP(db
), dn
, mods
, NULL
, NULL
);
1698 errfn
= "ldap_add_ext_s";
1700 /* already existed, send deltas only */
1701 rc
= ldap_modify_ext_s(HDB2LDAP(db
), dn
, mods
, NULL
, NULL
);
1702 errfn
= "ldap_modify_ext_s";
1705 if (check_ldap(context
, db
, rc
)) {
1706 char *ld_error
= NULL
;
1707 ldap_get_option(HDB2LDAP(db
), LDAP_OPT_ERROR_STRING
,
1709 ret
= HDB_ERR_CANT_LOCK_DB
;
1710 krb5_set_error_message(context
, ret
, "%s: %s (DN=%s) %s: %s",
1711 errfn
, name
, dn
, ldap_err2string(rc
), ld_error
);
1722 ldap_mods_free(mods
, 1);
1729 static krb5_error_code
1730 LDAP_remove(krb5_context context
, HDB
*db
, krb5_const_principal principal
)
1732 krb5_error_code ret
;
1733 LDAPMessage
*msg
, *e
;
1735 int rc
, limit
= LDAP_NO_LIMIT
;
1737 ret
= LDAP_principal2message(context
, db
, principal
, &msg
);
1741 e
= ldap_first_entry(HDB2LDAP(db
), msg
);
1743 ret
= HDB_ERR_NOENTRY
;
1747 dn
= ldap_get_dn(HDB2LDAP(db
), e
);
1749 ret
= HDB_ERR_NOENTRY
;
1753 rc
= ldap_set_option(HDB2LDAP(db
), LDAP_OPT_SIZELIMIT
, (const void *)&limit
);
1754 if (rc
!= LDAP_SUCCESS
) {
1755 ret
= HDB_ERR_BADVERSION
;
1756 krb5_set_error_message(context
, ret
, "ldap_set_option: %s",
1757 ldap_err2string(rc
));
1761 rc
= ldap_delete_ext_s(HDB2LDAP(db
), dn
, NULL
, NULL
);
1762 if (check_ldap(context
, db
, rc
)) {
1763 ret
= HDB_ERR_CANT_LOCK_DB
;
1764 krb5_set_error_message(context
, ret
, "ldap_delete_ext_s: %s",
1765 ldap_err2string(rc
));
1778 static krb5_error_code
1779 LDAP_destroy(krb5_context context
, HDB
* db
)
1781 krb5_error_code ret
;
1783 LDAP_close(context
, db
);
1785 ret
= hdb_clear_master_key(context
, db
);
1789 free(HDB2CREATE(db
));
1800 static krb5_error_code
1801 hdb_ldap_common(krb5_context context
,
1803 const char *search_base
,
1806 struct hdbldapdb
*h
;
1807 const char *create_base
= NULL
;
1809 if (search_base
== NULL
&& search_base
[0] == '\0') {
1810 krb5_set_error_message(context
, ENOMEM
, "ldap search base not configured");
1811 return ENOMEM
; /* XXX */
1814 if (structural_object
== NULL
) {
1817 p
= krb5_config_get_string(context
, NULL
, "kdc",
1818 "hdb-ldap-structural-object", NULL
);
1820 p
= default_structural_object
;
1821 structural_object
= strdup(p
);
1822 if (structural_object
== NULL
) {
1823 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
1829 krb5_config_get_bool_default(context
, NULL
, TRUE
,
1830 "kdc", "hdb-samba-forwardable", NULL
);
1832 *db
= calloc(1, sizeof(**db
));
1834 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
1837 memset(*db
, 0, sizeof(**db
));
1839 h
= calloc(1, sizeof(*h
));
1843 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
1849 if (asprintf(&(*db
)->hdb_name
, "ldap:%s", search_base
) == -1) {
1850 LDAP_destroy(context
, *db
);
1852 krb5_set_error_message(context
, ENOMEM
, "strdup: out of memory");
1856 h
->h_url
= strdup(url
);
1857 h
->h_base
= strdup(search_base
);
1858 if (h
->h_url
== NULL
|| h
->h_base
== NULL
) {
1859 LDAP_destroy(context
, *db
);
1861 krb5_set_error_message(context
, ENOMEM
, "strdup: out of memory");
1865 create_base
= krb5_config_get_string(context
, NULL
, "kdc",
1866 "hdb-ldap-create-base", NULL
);
1867 if (create_base
== NULL
)
1868 create_base
= h
->h_base
;
1870 h
->h_createbase
= strdup(create_base
);
1871 if (h
->h_createbase
== NULL
) {
1872 LDAP_destroy(context
, *db
);
1874 krb5_set_error_message(context
, ENOMEM
, "strdup: out of memory");
1878 (*db
)->hdb_master_key_set
= 0;
1879 (*db
)->hdb_openp
= 0;
1880 (*db
)->hdb_capability_flags
= 0;
1881 (*db
)->hdb_open
= LDAP_open
;
1882 (*db
)->hdb_close
= LDAP_close
;
1883 (*db
)->hdb_fetch_kvno
= LDAP_fetch_kvno
;
1884 (*db
)->hdb_store
= LDAP_store
;
1885 (*db
)->hdb_remove
= LDAP_remove
;
1886 (*db
)->hdb_firstkey
= LDAP_firstkey
;
1887 (*db
)->hdb_nextkey
= LDAP_nextkey
;
1888 (*db
)->hdb_lock
= LDAP_lock
;
1889 (*db
)->hdb_unlock
= LDAP_unlock
;
1890 (*db
)->hdb_rename
= NULL
;
1891 (*db
)->hdb__get
= NULL
;
1892 (*db
)->hdb__put
= NULL
;
1893 (*db
)->hdb__del
= NULL
;
1894 (*db
)->hdb_destroy
= LDAP_destroy
;
1900 hdb_ldap_create(krb5_context context
, HDB
** db
, const char *arg
)
1902 return hdb_ldap_common(context
, db
, arg
, "ldapi:///");
1906 hdb_ldapi_create(krb5_context context
, HDB
** db
, const char *arg
)
1908 krb5_error_code ret
;
1909 char *search_base
, *p
;
1911 asprintf(&p
, "ldapi:%s", arg
);
1914 krb5_set_error_message(context
, ENOMEM
, "out of memory");
1917 search_base
= strchr(p
+ strlen("ldapi://"), ':');
1918 if (search_base
== NULL
) {
1920 krb5_set_error_message(context
, HDB_ERR_BADVERSION
,
1921 "search base missing");
1922 return HDB_ERR_BADVERSION
;
1924 *search_base
= '\0';
1927 ret
= hdb_ldap_common(context
, db
, search_base
, p
);
1932 #ifdef OPENLDAP_MODULE
1934 struct hdb_so_method hdb_ldap_interface
= {
1935 HDB_INTERFACE_VERSION
,
1940 struct hdb_so_method hdb_ldapi_interface
= {
1941 HDB_INTERFACE_VERSION
,
1948 #endif /* OPENLDAP */