2 * Copyright (c) 1999-2001, PADL Software Pty Ltd.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of PADL Software nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 RCSID("$Id: hdb-ldap.c,v 1.10.4.1 2003/09/18 20:49:09 lha Exp $");
44 static krb5_error_code
LDAP__connect(krb5_context context
, HDB
* db
);
46 static krb5_error_code
47 LDAP_message2entry(krb5_context context
, HDB
* db
, LDAPMessage
* msg
,
50 static char *krb5kdcentry_attrs
[] =
51 { "krb5PrincipalName", "cn", "krb5PrincipalRealm",
52 "krb5KeyVersionNumber", "krb5Key",
53 "krb5ValidStart", "krb5ValidEnd", "krb5PasswordEnd",
54 "krb5MaxLife", "krb5MaxRenew", "krb5KDCFlags", "krb5EncryptionType",
55 "modifiersName", "modifyTimestamp", "creatorsName", "createTimestamp",
59 static char *krb5principal_attrs
[] =
60 { "krb5PrincipalName", "cn", "krb5PrincipalRealm",
61 "modifiersName", "modifyTimestamp", "creatorsName", "createTimestamp",
65 static krb5_error_code
66 LDAP__setmod(LDAPMod
*** modlist
, int modop
, const char *attribute
,
71 if (*modlist
== NULL
) {
72 *modlist
= (LDAPMod
**)ber_memcalloc(1, sizeof(LDAPMod
*));
73 if (*modlist
== NULL
) {
78 for (cMods
= 0; (*modlist
)[cMods
] != NULL
; cMods
++) {
79 if ((*modlist
)[cMods
]->mod_op
== modop
&&
80 strcasecmp((*modlist
)[cMods
]->mod_type
, attribute
) == 0) {
87 if ((*modlist
)[cMods
] == NULL
) {
90 *modlist
= (LDAPMod
**)ber_memrealloc(*modlist
,
91 (cMods
+ 2) * sizeof(LDAPMod
*));
92 if (*modlist
== NULL
) {
95 (*modlist
)[cMods
] = (LDAPMod
*)ber_memalloc(sizeof(LDAPMod
));
96 if ((*modlist
)[cMods
] == NULL
) {
100 mod
= (*modlist
)[cMods
];
102 mod
->mod_type
= ber_strdup(attribute
);
103 if (mod
->mod_type
== NULL
) {
105 (*modlist
)[cMods
] = NULL
;
109 if (modop
& LDAP_MOD_BVALUES
) {
110 mod
->mod_bvalues
= NULL
;
112 mod
->mod_values
= NULL
;
115 (*modlist
)[cMods
+ 1] = NULL
;
121 static krb5_error_code
122 LDAP_addmod_len(LDAPMod
*** modlist
, int modop
, const char *attribute
,
123 unsigned char *value
, size_t len
)
125 int cMods
, cValues
= 0;
128 ret
= LDAP__setmod(modlist
, modop
| LDAP_MOD_BVALUES
, attribute
, &cMods
);
134 struct berval
*bValue
;
135 struct berval
***pbValues
= &((*modlist
)[cMods
]->mod_bvalues
);
137 if (*pbValues
!= NULL
) {
138 for (cValues
= 0; (*pbValues
)[cValues
] != NULL
; cValues
++)
140 *pbValues
= (struct berval
**)ber_memrealloc(*pbValues
, (cValues
+ 2)
141 * sizeof(struct berval
*));
143 *pbValues
= (struct berval
**)ber_memalloc(2 * sizeof(struct berval
*));
145 if (*pbValues
== NULL
) {
148 (*pbValues
)[cValues
] = (struct berval
*)ber_memalloc(sizeof(struct berval
));;
149 if ((*pbValues
)[cValues
] == NULL
) {
153 bValue
= (*pbValues
)[cValues
];
154 bValue
->bv_val
= value
;
155 bValue
->bv_len
= len
;
157 (*pbValues
)[cValues
+ 1] = NULL
;
163 static krb5_error_code
164 LDAP_addmod(LDAPMod
*** modlist
, int modop
, const char *attribute
,
167 int cMods
, cValues
= 0;
170 ret
= LDAP__setmod(modlist
, modop
, attribute
, &cMods
);
176 char ***pValues
= &((*modlist
)[cMods
]->mod_values
);
178 if (*pValues
!= NULL
) {
179 for (cValues
= 0; (*pValues
)[cValues
] != NULL
; cValues
++)
181 *pValues
= (char **)ber_memrealloc(*pValues
, (cValues
+ 2) * sizeof(char *));
183 *pValues
= (char **)ber_memalloc(2 * sizeof(char *));
185 if (*pValues
== NULL
) {
188 (*pValues
)[cValues
] = ber_strdup(value
);
189 if ((*pValues
)[cValues
] == NULL
) {
192 (*pValues
)[cValues
+ 1] = NULL
;
198 static krb5_error_code
199 LDAP_addmod_generalized_time(LDAPMod
*** mods
, int modop
,
200 const char *attribute
, KerberosTime
* time
)
205 /* XXX not threadsafe */
207 strftime(buf
, sizeof(buf
), "%Y%m%d%H%M%SZ", tm
);
209 return LDAP_addmod(mods
, modop
, attribute
, buf
);
212 static krb5_error_code
213 LDAP_get_string_value(HDB
* db
, LDAPMessage
* entry
,
214 const char *attribute
, char **ptr
)
219 vals
= ldap_get_values((LDAP
*) db
->db
, entry
, (char *) attribute
);
221 return HDB_ERR_NOENTRY
;
223 *ptr
= strdup(vals
[0]);
230 ldap_value_free(vals
);
235 static krb5_error_code
236 LDAP_get_integer_value(HDB
* db
, LDAPMessage
* entry
,
237 const char *attribute
, int *ptr
)
241 vals
= ldap_get_values((LDAP
*) db
->db
, entry
, (char *) attribute
);
243 return HDB_ERR_NOENTRY
;
245 *ptr
= atoi(vals
[0]);
246 ldap_value_free(vals
);
250 static krb5_error_code
251 LDAP_get_generalized_time_value(HDB
* db
, LDAPMessage
* entry
,
252 const char *attribute
, KerberosTime
* kt
)
260 ret
= LDAP_get_string_value(db
, entry
, attribute
, &gentime
);
265 tmp
= strptime(gentime
, "%Y%m%d%H%M%SZ", &tm
);
268 return HDB_ERR_NOENTRY
;
278 static krb5_error_code
279 LDAP_entry2mods(krb5_context context
, HDB
* db
, hdb_entry
* ent
,
280 LDAPMessage
* msg
, LDAPMod
*** pmods
)
283 krb5_boolean is_new_entry
;
286 LDAPMod
**mods
= NULL
;
288 unsigned long oflags
, nflags
;
291 ret
= LDAP_message2entry(context
, db
, msg
, &orig
);
295 is_new_entry
= FALSE
;
297 /* to make it perfectly obvious we're depending on
298 * orig being intiialized to zero */
299 memset(&orig
, 0, sizeof(orig
));
304 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass", "top");
308 /* person is the structural object class */
309 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass", "person");
314 LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass",
319 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "objectClass",
327 krb5_principal_compare(context
, ent
->principal
, orig
.principal
) ==
329 ret
= krb5_unparse_name(context
, ent
->principal
, &tmp
);
334 LDAP_addmod(&mods
, LDAP_MOD_REPLACE
, "krb5PrincipalName", tmp
);
342 if (ent
->kvno
!= orig
.kvno
) {
343 rc
= asprintf(&tmp
, "%d", ent
->kvno
);
345 krb5_set_error_string(context
, "asprintf: out of memory");
350 LDAP_addmod(&mods
, LDAP_MOD_REPLACE
, "krb5KeyVersionNumber",
358 if (ent
->valid_start
) {
359 if (orig
.valid_end
== NULL
360 || (*(ent
->valid_start
) != *(orig
.valid_start
))) {
362 LDAP_addmod_generalized_time(&mods
, LDAP_MOD_REPLACE
,
371 if (ent
->valid_end
) {
372 if (orig
.valid_end
== NULL
373 || (*(ent
->valid_end
) != *(orig
.valid_end
))) {
375 LDAP_addmod_generalized_time(&mods
, LDAP_MOD_REPLACE
,
385 if (orig
.pw_end
== NULL
|| (*(ent
->pw_end
) != *(orig
.pw_end
))) {
387 LDAP_addmod_generalized_time(&mods
, LDAP_MOD_REPLACE
,
397 if (orig
.max_life
== NULL
398 || (*(ent
->max_life
) != *(orig
.max_life
))) {
399 rc
= asprintf(&tmp
, "%d", *(ent
->max_life
));
401 krb5_set_error_string(context
, "asprintf: out of memory");
405 ret
= LDAP_addmod(&mods
, LDAP_MOD_REPLACE
, "krb5MaxLife", tmp
);
413 if (ent
->max_renew
) {
414 if (orig
.max_renew
== NULL
415 || (*(ent
->max_renew
) != *(orig
.max_renew
))) {
416 rc
= asprintf(&tmp
, "%d", *(ent
->max_renew
));
418 krb5_set_error_string(context
, "asprintf: out of memory");
423 LDAP_addmod(&mods
, LDAP_MOD_REPLACE
, "krb5MaxRenew", tmp
);
431 oflags
= HDBFlags2int(orig
.flags
);
432 nflags
= HDBFlags2int(ent
->flags
);
434 if (oflags
!= nflags
) {
435 rc
= asprintf(&tmp
, "%lu", nflags
);
437 krb5_set_error_string(context
, "asprintf: out of memory");
441 ret
= LDAP_addmod(&mods
, LDAP_MOD_REPLACE
, "krb5KDCFlags", tmp
);
448 if (is_new_entry
== FALSE
&& orig
.keys
.len
> 0) {
449 /* for the moment, clobber and replace keys. */
450 ret
= LDAP_addmod(&mods
, LDAP_MOD_DELETE
, "krb5Key", NULL
);
456 for (i
= 0; i
< ent
->keys
.len
; i
++) {
460 ASN1_MALLOC_ENCODE(Key
, buf
, len
, &ent
->keys
.val
[i
], &len
, ret
);
464 /* addmod_len _owns_ the key, doesn't need to copy it */
465 ret
= LDAP_addmod_len(&mods
, LDAP_MOD_ADD
, "krb5Key", buf
, len
);
472 /* clobber and replace encryption types. */
473 if (is_new_entry
== FALSE
) {
475 LDAP_addmod(&mods
, LDAP_MOD_DELETE
, "krb5EncryptionType",
478 for (i
= 0; i
< ent
->etypes
->len
; i
++) {
479 rc
= asprintf(&tmp
, "%d", ent
->etypes
->val
[i
]);
481 krb5_set_error_string(context
, "asprintf: out of memory");
487 LDAP_addmod(&mods
, LDAP_MOD_ADD
, "krb5EncryptionType",
502 } else if (mods
!= NULL
) {
503 ldap_mods_free(mods
, 1);
508 hdb_free_entry(context
, &orig
);
514 static krb5_error_code
515 LDAP_dn2principal(krb5_context context
, HDB
* db
, const char *dn
,
516 krb5_principal
* principal
)
521 LDAPMessage
*res
= NULL
, *e
;
523 rc
= ldap_set_option((LDAP
*) db
->db
, LDAP_OPT_SIZELIMIT
, (const void *)&limit
);
524 if (rc
!= LDAP_SUCCESS
) {
525 krb5_set_error_string(context
, "ldap_set_option: %s", ldap_err2string(rc
));
526 ret
= HDB_ERR_BADVERSION
;
530 rc
= ldap_search_s((LDAP
*) db
->db
, dn
, LDAP_SCOPE_BASE
,
531 "(objectclass=krb5Principal)", krb5principal_attrs
,
533 if (rc
!= LDAP_SUCCESS
) {
534 krb5_set_error_string(context
, "ldap_search_s: %s", ldap_err2string(rc
));
535 ret
= HDB_ERR_NOENTRY
;
539 e
= ldap_first_entry((LDAP
*) db
->db
, res
);
541 ret
= HDB_ERR_NOENTRY
;
545 values
= ldap_get_values((LDAP
*) db
->db
, e
, "krb5PrincipalName");
546 if (values
== NULL
) {
547 ret
= HDB_ERR_NOENTRY
;
551 ret
= krb5_parse_name(context
, values
[0], principal
);
552 ldap_value_free(values
);
561 static krb5_error_code
562 LDAP__lookup_princ(krb5_context context
, HDB
* db
, const char *princname
,
569 (void) LDAP__connect(context
, db
);
573 "(&(objectclass=krb5KDCEntry)(krb5PrincipalName=%s))",
576 krb5_set_error_string(context
, "asprintf: out of memory");
581 rc
= ldap_set_option((LDAP
*) db
->db
, LDAP_OPT_SIZELIMIT
, (const void *)&limit
);
582 if (rc
!= LDAP_SUCCESS
) {
583 krb5_set_error_string(context
, "ldap_set_option: %s", ldap_err2string(rc
));
584 ret
= HDB_ERR_BADVERSION
;
588 rc
= ldap_search_s((LDAP
*) db
->db
, db
->name
, LDAP_SCOPE_ONELEVEL
, filter
,
589 krb5kdcentry_attrs
, 0, msg
);
590 if (rc
!= LDAP_SUCCESS
) {
591 krb5_set_error_string(context
, "ldap_search_s: %s", ldap_err2string(rc
));
592 ret
= HDB_ERR_NOENTRY
;
599 if (filter
!= NULL
) {
605 static krb5_error_code
606 LDAP_principal2message(krb5_context context
, HDB
* db
,
607 krb5_principal princ
, LDAPMessage
** msg
)
609 char *princname
= NULL
;
612 ret
= krb5_unparse_name(context
, princ
, &princname
);
617 ret
= LDAP__lookup_princ(context
, db
, princname
, msg
);
624 * Construct an hdb_entry from a directory entry.
626 static krb5_error_code
627 LDAP_message2entry(krb5_context context
, HDB
* db
, LDAPMessage
* msg
,
630 char *unparsed_name
= NULL
, *dn
= NULL
;
633 struct berval
**keys
;
636 memset(ent
, 0, sizeof(*ent
));
637 ent
->flags
= int2HDBFlags(0);
640 LDAP_get_string_value(db
, msg
, "krb5PrincipalName",
646 ret
= krb5_parse_name(context
, unparsed_name
, &ent
->principal
);
652 LDAP_get_integer_value(db
, msg
, "krb5KeyVersionNumber",
658 keys
= ldap_get_values_len((LDAP
*) db
->db
, msg
, "krb5Key");
663 ent
->keys
.len
= ldap_count_values_len(keys
);
664 ent
->keys
.val
= (Key
*) calloc(ent
->keys
.len
, sizeof(Key
));
665 if (ent
->keys
.val
== NULL
) {
666 krb5_set_error_string(context
, "calloc: out of memory");
670 for (i
= 0; i
< ent
->keys
.len
; i
++) {
671 decode_Key((unsigned char *) keys
[i
]->bv_val
,
672 (size_t) keys
[i
]->bv_len
, &ent
->keys
.val
[i
], &l
);
678 * This violates the ASN1 but it allows a principal to
679 * be related to a general directory entry without creating
680 * the keys. Hopefully it's OK.
683 ent
->keys
.val
= NULL
;
685 ret
= HDB_ERR_NOENTRY
;
691 LDAP_get_generalized_time_value(db
, msg
, "createTimestamp",
692 &ent
->created_by
.time
);
694 ent
->created_by
.time
= time(NULL
);
697 ent
->created_by
.principal
= NULL
;
699 ret
= LDAP_get_string_value(db
, msg
, "creatorsName", &dn
);
701 if (LDAP_dn2principal(context
, db
, dn
, &ent
->created_by
.principal
)
703 ent
->created_by
.principal
= NULL
;
708 ent
->modified_by
= (Event
*) malloc(sizeof(Event
));
709 if (ent
->modified_by
== NULL
) {
710 krb5_set_error_string(context
, "malloc: out of memory");
715 LDAP_get_generalized_time_value(db
, msg
, "modifyTimestamp",
716 &ent
->modified_by
->time
);
718 ret
= LDAP_get_string_value(db
, msg
, "modifiersName", &dn
);
719 if (LDAP_dn2principal
720 (context
, db
, dn
, &ent
->modified_by
->principal
) != 0) {
721 ent
->modified_by
->principal
= NULL
;
725 free(ent
->modified_by
);
726 ent
->modified_by
= NULL
;
729 if ((ent
->valid_start
= (KerberosTime
*) malloc(sizeof(KerberosTime
)))
731 krb5_set_error_string(context
, "malloc: out of memory");
736 LDAP_get_generalized_time_value(db
, msg
, "krb5ValidStart",
740 free(ent
->valid_start
);
741 ent
->valid_start
= NULL
;
744 if ((ent
->valid_end
= (KerberosTime
*) malloc(sizeof(KerberosTime
))) ==
746 krb5_set_error_string(context
, "malloc: out of memory");
751 LDAP_get_generalized_time_value(db
, msg
, "krb5ValidEnd",
755 free(ent
->valid_end
);
756 ent
->valid_end
= NULL
;
759 if ((ent
->pw_end
= (KerberosTime
*) malloc(sizeof(KerberosTime
))) ==
761 krb5_set_error_string(context
, "malloc: out of memory");
766 LDAP_get_generalized_time_value(db
, msg
, "krb5PasswordEnd",
774 ent
->max_life
= (int *) malloc(sizeof(int));
775 if (ent
->max_life
== NULL
) {
776 krb5_set_error_string(context
, "malloc: out of memory");
780 ret
= LDAP_get_integer_value(db
, msg
, "krb5MaxLife", ent
->max_life
);
783 ent
->max_life
= NULL
;
786 ent
->max_renew
= (int *) malloc(sizeof(int));
787 if (ent
->max_renew
== NULL
) {
788 krb5_set_error_string(context
, "malloc: out of memory");
792 ret
= LDAP_get_integer_value(db
, msg
, "krb5MaxRenew", ent
->max_renew
);
794 free(ent
->max_renew
);
795 ent
->max_renew
= NULL
;
798 values
= ldap_get_values((LDAP
*) db
->db
, msg
, "krb5KDCFlags");
799 if (values
!= NULL
) {
800 tmp
= strtoul(values
[0], (char **) NULL
, 10);
801 if (tmp
== ULONG_MAX
&& errno
== ERANGE
) {
802 krb5_set_error_string(context
, "strtoul: could not convert flag");
809 ent
->flags
= int2HDBFlags(tmp
);
811 values
= ldap_get_values((LDAP
*) db
->db
, msg
, "krb5EncryptionType");
812 if (values
!= NULL
) {
815 ent
->etypes
= malloc(sizeof(*(ent
->etypes
)));
816 if (ent
->etypes
== NULL
) {
817 krb5_set_error_string(context
, "malloc: out of memory");
821 ent
->etypes
->len
= ldap_count_values(values
);
822 ent
->etypes
->val
= calloc(ent
->etypes
->len
, sizeof(int));
823 for (i
= 0; i
< ent
->etypes
->len
; i
++) {
824 ent
->etypes
->val
[i
] = atoi(values
[i
]);
826 ldap_value_free(values
);
832 if (unparsed_name
!= NULL
) {
837 /* I don't think this frees ent itself. */
838 hdb_free_entry(context
, ent
);
844 static krb5_error_code
LDAP_close(krb5_context context
, HDB
* db
)
846 ldap_unbind_ext((LDAP
*) db
->db
, NULL
, NULL
);
852 static krb5_error_code
853 LDAP_lock(krb5_context context
, HDB
* db
, int operation
)
858 static krb5_error_code
LDAP_unlock(krb5_context context
, HDB
* db
)
863 static krb5_error_code
864 LDAP_seq(krb5_context context
, HDB
* db
, unsigned flags
, hdb_entry
* entry
)
866 int msgid
, rc
, parserc
;
870 msgid
= db
->openp
; /* BOGUS OVERLOADING */
872 return HDB_ERR_NOENTRY
;
876 rc
= ldap_result((LDAP
*) db
->db
, msgid
, LDAP_MSG_ONE
, NULL
, &e
);
878 case LDAP_RES_SEARCH_ENTRY
:
879 /* We have an entry. Parse it. */
880 ret
= LDAP_message2entry(context
, db
, e
, entry
);
883 case LDAP_RES_SEARCH_RESULT
:
884 /* We're probably at the end of the results. If not, abandon. */
886 ldap_parse_result((LDAP
*) db
->db
, e
, NULL
, NULL
, NULL
,
888 if (parserc
!= LDAP_SUCCESS
889 && parserc
!= LDAP_MORE_RESULTS_TO_RETURN
) {
890 krb5_set_error_string(context
, "ldap_parse_result: %s", ldap_err2string(parserc
));
891 ldap_abandon((LDAP
*) db
->db
, msgid
);
893 ret
= HDB_ERR_NOENTRY
;
899 /* Some unspecified error (timeout?). Abandon. */
901 ldap_abandon((LDAP
*) db
->db
, msgid
);
902 ret
= HDB_ERR_NOENTRY
;
906 } while (rc
== LDAP_RES_SEARCH_REFERENCE
);
909 if (db
->master_key_set
&& (flags
& HDB_F_DECRYPT
)) {
910 ret
= hdb_unseal_keys(context
, db
, entry
);
912 hdb_free_entry(context
,entry
);
919 static krb5_error_code
920 LDAP_firstkey(krb5_context context
, HDB
* db
, unsigned flags
,
923 int msgid
, limit
= LDAP_NO_LIMIT
, rc
;
925 (void) LDAP__connect(context
, db
);
927 rc
= ldap_set_option((LDAP
*) db
->db
, LDAP_OPT_SIZELIMIT
, (const void *)&limit
);
928 if (rc
!= LDAP_SUCCESS
) {
929 krb5_set_error_string(context
, "ldap_set_option: %s", ldap_err2string(rc
));
930 return HDB_ERR_BADVERSION
;
933 msgid
= ldap_search((LDAP
*) db
->db
, db
->name
,
934 LDAP_SCOPE_ONELEVEL
, "(objectclass=krb5KDCEntry)",
935 krb5kdcentry_attrs
, 0);
937 return HDB_ERR_NOENTRY
;
942 return LDAP_seq(context
, db
, flags
, entry
);
945 static krb5_error_code
946 LDAP_nextkey(krb5_context context
, HDB
* db
, unsigned flags
,
949 return LDAP_seq(context
, db
, flags
, entry
);
952 static krb5_error_code
953 LDAP_rename(krb5_context context
, HDB
* db
, const char *new_name
)
955 return HDB_ERR_DB_INUSE
;
958 static krb5_error_code
LDAP__connect(krb5_context context
, HDB
* db
)
960 int rc
, version
= LDAP_VERSION3
;
962 * Empty credentials to do a SASL bind with LDAP. Note that empty
963 * different from NULL credentials. If you provide NULL
964 * credentials instead of empty credentials you will get a SASL
965 * bind in progress message.
967 struct berval bv
= { 0, "" };
969 if (db
->db
!= NULL
) {
970 /* connection has been opened. ping server. */
971 struct sockaddr_un addr
;
975 if (ldap_get_option((LDAP
*) db
->db
, LDAP_OPT_DESC
, &sd
) == 0 &&
976 getpeername(sd
, (struct sockaddr
*) &addr
, &len
) < 0) {
977 /* the other end has died. reopen. */
978 LDAP_close(context
, db
);
982 if (db
->db
!= NULL
) {
987 rc
= ldap_initialize((LDAP
**) & db
->db
, "ldapi:///");
988 if (rc
!= LDAP_SUCCESS
) {
989 krb5_set_error_string(context
, "ldap_initialize: %s", ldap_err2string(rc
));
990 return HDB_ERR_NOENTRY
;
993 rc
= ldap_set_option((LDAP
*) db
->db
, LDAP_OPT_PROTOCOL_VERSION
, (const void *)&version
);
994 if (rc
!= LDAP_SUCCESS
) {
995 krb5_set_error_string(context
, "ldap_set_option: %s", ldap_err2string(rc
));
996 ldap_unbind_ext((LDAP
*) db
->db
, NULL
, NULL
);
998 return HDB_ERR_BADVERSION
;
1001 rc
= ldap_sasl_bind_s((LDAP
*) db
->db
, NULL
, "EXTERNAL", &bv
, NULL
, NULL
, NULL
);
1002 if (rc
!= LDAP_SUCCESS
) {
1003 krb5_set_error_string(context
, "ldap_sasl_bind_s: %s", ldap_err2string(rc
));
1004 ldap_unbind_ext((LDAP
*) db
->db
, NULL
, NULL
);
1006 return HDB_ERR_BADVERSION
;
1012 static krb5_error_code
1013 LDAP_open(krb5_context context
, HDB
* db
, int flags
, mode_t mode
)
1015 /* Not the right place for this. */
1016 #ifdef HAVE_SIGACTION
1017 struct sigaction sa
;
1020 sa
.sa_handler
= SIG_IGN
;
1021 sigemptyset(&sa
.sa_mask
);
1023 sigaction(SIGPIPE
, &sa
, NULL
);
1025 signal(SIGPIPE
, SIG_IGN
);
1026 #endif /* HAVE_SIGACTION */
1028 return LDAP__connect(context
, db
);
1031 static krb5_error_code
1032 LDAP_fetch(krb5_context context
, HDB
* db
, unsigned flags
,
1035 LDAPMessage
*msg
, *e
;
1036 krb5_error_code ret
;
1038 ret
= LDAP_principal2message(context
, db
, entry
->principal
, &msg
);
1043 e
= ldap_first_entry((LDAP
*) db
->db
, msg
);
1045 ret
= HDB_ERR_NOENTRY
;
1049 ret
= LDAP_message2entry(context
, db
, e
, entry
);
1051 if (db
->master_key_set
&& (flags
& HDB_F_DECRYPT
)) {
1052 ret
= hdb_unseal_keys(context
, db
, entry
);
1054 hdb_free_entry(context
,entry
);
1064 static krb5_error_code
1065 LDAP_store(krb5_context context
, HDB
* db
, unsigned flags
,
1068 LDAPMod
**mods
= NULL
;
1069 krb5_error_code ret
;
1072 LDAPMessage
*msg
= NULL
, *e
= NULL
;
1073 char *dn
= NULL
, *name
= NULL
;
1075 ret
= krb5_unparse_name(context
, entry
->principal
, &name
);
1080 ret
= LDAP__lookup_princ(context
, db
, name
, &msg
);
1082 e
= ldap_first_entry((LDAP
*) db
->db
, msg
);
1085 ret
= hdb_seal_keys(context
, db
, entry
);
1090 /* turn new entry into LDAPMod array */
1091 ret
= LDAP_entry2mods(context
, db
, entry
, e
, &mods
);
1097 /* Doesn't exist yet. */
1102 /* normalize the naming attribute */
1103 for (p
= name
; *p
!= '\0'; p
++) {
1104 *p
= (char) tolower((int) *p
);
1108 * We could do getpwnam() on the local component of
1109 * the principal to find cn/sn but that's probably
1110 * bad thing to do from inside a KDC. Better leave
1111 * it to management tools.
1113 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "cn", name
);
1118 ret
= LDAP_addmod(&mods
, LDAP_MOD_ADD
, "sn", name
);
1123 if (db
->name
!= NULL
) {
1124 ret
= asprintf(&dn
, "cn=%s,%s", name
, db
->name
);
1126 /* A bit bogus, but we don't have a search base */
1127 ret
= asprintf(&dn
, "cn=%s", name
);
1130 krb5_set_error_string(context
, "asprintf: out of memory");
1134 } else if (flags
& HDB_F_REPLACE
) {
1135 /* Entry exists, and we're allowed to replace it. */
1136 dn
= ldap_get_dn((LDAP
*) db
->db
, e
);
1138 /* Entry exists, but we're not allowed to replace it. Bail. */
1139 ret
= HDB_ERR_EXISTS
;
1143 /* write entry into directory */
1145 /* didn't exist before */
1146 rc
= ldap_add_s((LDAP
*) db
->db
, dn
, mods
);
1147 errfn
= "ldap_add_s";
1149 /* already existed, send deltas only */
1150 rc
= ldap_modify_s((LDAP
*) db
->db
, dn
, mods
);
1151 errfn
= "ldap_modify_s";
1154 if (rc
== LDAP_SUCCESS
) {
1157 krb5_set_error_string(context
, "%s: %s (dn=%s) %s",
1158 errfn
, name
, dn
, ldap_err2string(rc
));
1159 ret
= HDB_ERR_CANT_LOCK_DB
;
1173 ldap_mods_free(mods
, 1);
1183 static krb5_error_code
1184 LDAP_remove(krb5_context context
, HDB
* db
, hdb_entry
* entry
)
1186 krb5_error_code ret
;
1187 LDAPMessage
*msg
, *e
;
1189 int rc
, limit
= LDAP_NO_LIMIT
;
1191 ret
= LDAP_principal2message(context
, db
, entry
->principal
, &msg
);
1196 e
= ldap_first_entry((LDAP
*) db
->db
, msg
);
1198 ret
= HDB_ERR_NOENTRY
;
1202 dn
= ldap_get_dn((LDAP
*) db
->db
, e
);
1204 ret
= HDB_ERR_NOENTRY
;
1208 rc
= ldap_set_option((LDAP
*) db
->db
, LDAP_OPT_SIZELIMIT
, (const void *)&limit
);
1209 if (rc
!= LDAP_SUCCESS
) {
1210 krb5_set_error_string(context
, "ldap_set_option: %s", ldap_err2string(rc
));
1211 ret
= HDB_ERR_BADVERSION
;
1215 rc
= ldap_delete_s((LDAP
*) db
->db
, dn
);
1216 if (rc
== LDAP_SUCCESS
) {
1219 krb5_set_error_string(context
, "ldap_delete_s: %s", ldap_err2string(rc
));
1220 ret
= HDB_ERR_CANT_LOCK_DB
;
1235 static krb5_error_code
1236 LDAP__get(krb5_context context
, HDB
* db
, krb5_data key
, krb5_data
* reply
)
1238 fprintf(stderr
, "LDAP__get not implemented\n");
1243 static krb5_error_code
1244 LDAP__put(krb5_context context
, HDB
* db
, int replace
,
1245 krb5_data key
, krb5_data value
)
1247 fprintf(stderr
, "LDAP__put not implemented\n");
1252 static krb5_error_code
1253 LDAP__del(krb5_context context
, HDB
* db
, krb5_data key
)
1255 fprintf(stderr
, "LDAP__del not implemented\n");
1260 static krb5_error_code
LDAP_destroy(krb5_context context
, HDB
* db
)
1262 krb5_error_code ret
;
1264 ret
= hdb_clear_master_key(context
, db
);
1265 if (db
->name
!= NULL
) {
1274 hdb_ldap_create(krb5_context context
, HDB
** db
, const char *arg
)
1276 *db
= malloc(sizeof(**db
));
1278 krb5_set_error_string(context
, "malloc: out of memory");
1284 if (arg
== NULL
|| arg
[0] == '\0') {
1286 * if no argument specified in the configuration file
1287 * then use NULL, which tells OpenLDAP to look in
1288 * the ldap.conf file. This doesn't work for
1289 * writing entries because we don't know where to
1290 * put new principals.
1294 (*db
)->name
= strdup(arg
);
1295 if ((*db
)->name
== NULL
) {
1296 krb5_set_error_string(context
, "strdup: out of memory");
1303 (*db
)->master_key_set
= 0;
1305 (*db
)->open
= LDAP_open
;
1306 (*db
)->close
= LDAP_close
;
1307 (*db
)->fetch
= LDAP_fetch
;
1308 (*db
)->store
= LDAP_store
;
1309 (*db
)->remove
= LDAP_remove
;
1310 (*db
)->firstkey
= LDAP_firstkey
;
1311 (*db
)->nextkey
= LDAP_nextkey
;
1312 (*db
)->lock
= LDAP_lock
;
1313 (*db
)->unlock
= LDAP_unlock
;
1314 (*db
)->rename
= LDAP_rename
;
1315 /* can we ditch these? */
1316 (*db
)->_get
= LDAP__get
;
1317 (*db
)->_put
= LDAP__put
;
1318 (*db
)->_del
= LDAP__del
;
1319 (*db
)->destroy
= LDAP_destroy
;
1324 #endif /* OPENLDAP */