From e05574d103881f898de1e61963fae0a5bcb311cf Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Wed, 8 Nov 2006 23:44:31 +0000 Subject: [PATCH] pull up r18750 from trunk r18750@cathode-dark-space: wfiveash | 2006-10-30 15:56:57 -0500 ticket: new subject: latest Novell ldap patches and kdb5_util dump support for ldap Target_Version: krb5-1.6 Tags: pullup I've applied Novell's latest patches for their LDAP KDB plugin. I've also implemented and tested support for kdb5_util dump using the LDAP KDB plugin. I also added a Sun copyright on files that I've modified. ticket: 4562 version_fixed: 1.6 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@18774 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/main.c | 3 + src/lib/krb5/asn.1/ldap_key_seq.c | 25 +- .../kdb/ldap/ldap_util/kdb5_ldap_policy.c | 14 +- .../kdb/ldap/ldap_util/kdb5_ldap_realm.c | 27 +- .../kdb/ldap/ldap_util/kdb5_ldap_services.c | 22 +- .../kdb/ldap/ldap_util/kdb5_ldap_util.c | 1 - src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h | 4 + .../kdb/ldap/libkdb_ldap/ldap_create.c | 5 + src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c | 363 ++++++++++++++++-- src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h | 13 + .../kdb/ldap/libkdb_ldap/ldap_principal.c | 22 +- .../kdb/ldap/libkdb_ldap/ldap_principal.h | 9 + .../kdb/ldap/libkdb_ldap/ldap_principal2.c | 347 ++++------------- .../kdb/ldap/libkdb_ldap/ldap_pwd_policy.c | 108 ++++-- src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c | 6 + 15 files changed, 600 insertions(+), 369 deletions(-) diff --git a/src/kdc/main.c b/src/kdc/main.c index 3cd546f3a..282d418af 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -382,10 +382,13 @@ setup_signal_handlers(void) (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL); s_action.sa_handler = request_hup; (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL); + s_action.sa_handler = SIG_IGN; + (void) sigaction(SIGPIPE, &s_action, (struct sigaction *) NULL); #else /* POSIX_SIGNALS */ signal(SIGINT, request_exit); signal(SIGTERM, request_exit); signal(SIGHUP, request_hup); + signal(SIGPIPE, SIG_IGN); #endif /* POSIX_SIGNALS */ return; diff --git a/src/lib/krb5/asn.1/ldap_key_seq.c b/src/lib/krb5/asn.1/ldap_key_seq.c index c77c51c03..c25d7afe6 100644 --- a/src/lib/krb5/asn.1/ldap_key_seq.c +++ b/src/lib/krb5/asn.1/ldap_key_seq.c @@ -112,7 +112,7 @@ asn1_encode_key(asn1buf *buf, ret = asn1_make_sequence(buf, salt_len, &length); checkerr; salt_len += length; - ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, salt_len, &length); checkerr; + ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, salt_len, &length); checkerr; salt_len += length; sum += salt_len; @@ -138,6 +138,7 @@ asn1_encode_sequence_of_keys (krb5_key_data *key_data, asn1_error_code ret = 0; asn1buf *buf = NULL; unsigned int length, sum = 0; + unsigned long tmp_ul; *code = NULL; @@ -167,7 +168,8 @@ asn1_encode_sequence_of_keys (krb5_key_data *key_data, /* mkvno */ if (mkvno < 0) cleanup (ASN1_BAD_FORMAT); - ret = asn1_encode_unsigned_integer (buf, (unsigned int)mkvno, &length); checkerr; + tmp_ul = (unsigned long)mkvno; + ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length); checkerr; sum += length; ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 3, length, &length); checkerr; sum += length; @@ -175,7 +177,8 @@ asn1_encode_sequence_of_keys (krb5_key_data *key_data, /* kvno (assuming all keys in array have same version) */ if (key_data[0].key_data_kvno < 0) cleanup (ASN1_BAD_FORMAT); - ret = asn1_encode_unsigned_integer (buf, (unsigned int)key_data[0].key_data_kvno, &length); + tmp_ul = (unsigned long)key_data[0].key_data_kvno; + ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length); checkerr; sum += length; ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 2, length, &length); checkerr; @@ -202,8 +205,11 @@ asn1_encode_sequence_of_keys (krb5_key_data *key_data, last: asn1buf_destroy (&buf); - if (ret != 0 && *code != NULL) - free (*code); + if (ret != 0 && *code != NULL) { + if ((*code)->data != NULL) + free ((*code)->data); + free (*code); + } return ret; } @@ -219,7 +225,7 @@ last: asn1buf_sync((outer), (inner), 0, 0, 0, 0, 0); static asn1_error_code -decode_tagged_integer (asn1buf *buf, int expectedtag, long *val) +decode_tagged_integer (asn1buf *buf, asn1_tagnum expectedtag, long *val) { int buflen; asn1_error_code ret = 0; @@ -271,7 +277,7 @@ last: #endif static asn1_error_code -decode_tagged_octetstring (asn1buf *buf, int expectedtag, int *len, +decode_tagged_octetstring (asn1buf *buf, asn1_tagnum expectedtag, int *len, asn1_octet **val) { int buflen; @@ -449,6 +455,11 @@ krb5_error_code asn1_decode_sequence_of_keys (krb5_data *in, safe_syncbuf (&subbuf, &keyseq); } + /* + * There could be other data inside the outermost sequence ... tags we don't + * know about. So, not invoking "safe_syncbuf(&buf,&subbuf)" + */ + last: if (ret != 0) { int i; diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c index 60963d2d9..7a6c6411e 100644 --- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c +++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c @@ -52,7 +52,7 @@ static krb5_error_code init_ldap_realm (int argc, char *argv[]) { /* This operation is being performed in the context of a realm. So, * initialize the realm */ int mask = 0; - krb5_error_code retval; + krb5_error_code retval = 0; kdb5_dal_handle *dal_handle = NULL; krb5_ldap_context *ldap_context=NULL; @@ -816,18 +816,6 @@ void kdb5_ldap_list_policies(argc, argv) goto err_usage; } - /* Parse base DN argument if present */ - if (argc == 3) { - if (strcmp(argv[1], "-basedn")) - goto err_usage; - - basedn = strdup(argv[2]); - if (basedn == NULL) { - retval = ENOMEM; - goto cleanup; - } - } - if ((retval = init_ldap_realm (argc, argv))) goto cleanup; diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c index 870f2bd74..7e2c71e62 100644 --- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c +++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c @@ -343,15 +343,17 @@ void kdb5_ldap_create(argc, argv) goto err_usage; if(strncmp(argv[i], "", strlen(argv[i]))!=0) { - list = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *)); - memset(list, 0, sizeof(char*)*MAX_LIST_ENTRIES); + list = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *)); if (list == NULL) { retval = ENOMEM; goto cleanup; } - if (( retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) + if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) { + free(list); + list = NULL; goto cleanup; - + } + rparams->subtreecount=0; while(list[rparams->subtreecount]!=NULL) (rparams->subtreecount)++; @@ -886,13 +888,13 @@ void kdb5_ldap_modify(argc, argv) int argc; char *argv[]; { - krb5_error_code retval, st; + krb5_error_code retval = 0; krb5_ldap_realm_params *rparams = NULL; krb5_boolean print_usage = FALSE; krb5_boolean no_msg = FALSE; kdb5_dal_handle *dal_handle = NULL; krb5_ldap_context *ldap_context=NULL; - int i = 0, j = 0; + int i = 0; int mask = 0, rmask = 0, ret_mask = 0; char **slist = {NULL}; #ifdef HAVE_EDIRECTORY @@ -942,7 +944,6 @@ void kdb5_ldap_modify(argc, argv) if (rparams->subtree) { #ifdef HAVE_EDIRECTORY oldsubtrees = (char **) calloc(rparams->subtreecount+1, sizeof(char *)); - memset(oldsubtrees, 0, szeof(char *) * rparams->subtreecount+1); if (oldsubtrees == NULL) { retval = ENOMEM; goto cleanup; @@ -955,20 +956,22 @@ void kdb5_ldap_modify(argc, argv) } } #endif - for(k=0;ksubtreecount && rparams->subtree[k];k++) + for(k=0; ksubtreecount && rparams->subtree[k]; k++) free(rparams->subtree[k]); rparams->subtreecount=0; } } if (strncmp(argv[i] ,"", strlen(argv[i]))!=0) { slist = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *)); - memset(slist, 0, sizeof(char*)*MAX_LIST_ENTRIES); if (slist == NULL) { - retval = ENOMEM; - goto cleanup; + retval = ENOMEM; + goto cleanup; } - if (( retval = krb5_parse_list(argv[i], LIST_DELIMITER, slist))) + if (( retval = krb5_parse_list(argv[i], LIST_DELIMITER, slist))) { + free(slist); + slist = NULL; goto cleanup; + } rparams->subtreecount=0; while(slist[rparams->subtreecount]!=NULL) diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c index 783b44d68..bd64566f4 100644 --- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c +++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c @@ -383,6 +383,10 @@ void kdb5_ldap_create_service(argc, argv) if (extra_argc >= 1) { /* Set service DN as the last argument */ extra_argv[extra_argc] = strdup(srvparams->servicedn); + if (extra_argv[extra_argc] == NULL) { + retval = ENOMEM; + goto cleanup; + } extra_argc++; if ((retval = kdb5_ldap_set_service_password(extra_argc, extra_argv)) != 0) { @@ -1924,11 +1928,17 @@ kdb5_ldap_stash_service_password(argc, argv) if (argc == 4) { /* Find the stash file name */ if (strcmp (argv[1], "-f") == 0) { - file_name = strdup (argv[2]); - service_object = strdup (argv[3]); + if (((file_name = strdup (argv[2])) == NULL) || + ((service_object = strdup (argv[3])) == NULL)) { + com_err(me, ENOMEM, "while setting service object password"); + goto cleanup; + } } else if (strcmp (argv[2], "-f") == 0) { - file_name = strdup (argv[3]); - service_object = strdup (argv[1]); + if (((file_name = strdup (argv[3])) == NULL) || + ((service_object = strdup (argv[1])) == NULL)) { + com_err(me, ENOMEM, "while setting service object password"); + goto cleanup; + } } else { print_usage = TRUE; goto cleanup; @@ -1956,6 +1966,10 @@ kdb5_ldap_stash_service_password(argc, argv) if (section == NULL) { /* Stash file path neither in krb5.conf nor on command line */ file_name = strdup(DEF_SERVICE_PASSWD_FILE); + if (file_name == NULL) { + com_err(me, ENOMEM, "while setting service object password"); + goto cleanup; + } goto done; } } diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c index 3cc0f0f91..38ac03798 100644 --- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c +++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c @@ -293,7 +293,6 @@ int main(argc, argv) char *bind_dn = NULL; char *passwd = NULL; char *ldap_server = NULL; - char *ldap_port = NULL; unsigned int ldapmask = 0; unsigned int passwd_len = 0; char *prompt = NULL; diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h index 93a47acf9..97da15d21 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h +++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h @@ -68,6 +68,10 @@ extern struct timeval timelimit; #define KERBEROS_CONTAINER "cn=Kerberos,cn=Security" #endif +#if !defined(LDAP_OPT_RESULT_CODE) && defined(LDAP_OPT_ERROR_NUMBER) +#define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER +#endif + #define NEG(val) (val <0) ? abs(val) : -val ; #define MAXINTLEN 10 diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c index 3162bdc26..768ba6a59 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c @@ -28,6 +28,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #include "ldap_main.h" #include "ldap_realm.h" #include "ldap_principal.h" diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c index 1d0a32036..d6b479aa0 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c @@ -27,11 +27,19 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ #include #include #include "kdb_ldap.h" #include "ldap_misc.h" +#include "ldap_handle.h" #include "ldap_err.h" +#include "ldap_principal.h" +#include "princ_xdr.h" +#include "ldap_pwd_policy.h" #ifdef NEED_STRPTIME_PROTO extern char *strptime (const char *, const char *, struct tm *); @@ -508,31 +516,34 @@ krb5_get_subtree_info(ldap_context, subtreearr, ntree) } ncount = i; - - subtree = (char **) malloc(sizeof(char *) * (ncount + 1)); - if (subtree == NULL) { - st = ENOMEM; - goto cleanup; + newsubtree = (char **) malloc(sizeof(char *) * (ncount + 1)); + if (newsubtree == NULL) { + st = ENOMEM; + goto cleanup; + } + memset(newsubtree, 0, (sizeof(char *) * (ncount+1))); + if ((st = remove_overlapping_subtrees(subtarr, newsubtree, &ncount, + search_scope)) != 0) { + goto cleanup; } - memset(subtree, 0, (sizeof(char *) * (ncount+1))); - remove_overlapping_subtrees(subtarr, &subtree, &ncount, search_scope); *ntree = ncount; - *subtreearr = subtree; + *subtreearr = newsubtree; cleanup: - if (subtarr!=NULL) { - for (i=0; subtarr[i]!=NULL; i++) + if (subtarr != NULL) { + for (i=0; subtarr[i] != NULL; i++) free(subtarr[i]); free(subtarr); } - if (newsubtree!=NULL) { - for (i=0; newsubtree[i]!=NULL; i++) - free(newsubtree[i]); - free(newsubtree); + if (st != 0) { + if (newsubtree != NULL) { + for (i=0; newsubtree[i] != NULL; i++) + free(newsubtree[i]); + free(newsubtree); + } } - return st; } @@ -1283,9 +1294,9 @@ krb5_ldap_get_strings(ld, ent, attribute, retarr, attr_present) char ***retarr; krb5_boolean *attr_present; { - char **values=NULL; - krb5_error_code st=0; - int i=0, count=0; + char **values=NULL; + krb5_error_code st=0; + unsigned int i=0, count=0; *retarr = NULL; if (attr_present != NULL) @@ -1586,8 +1597,10 @@ krb5_ldap_release_errcode_string(krb5_context kcontext, const char *msg) */ krb5_error_code krb5_ldap_get_reference_count (krb5_context context, char *dn, char *refattr, - int *count, LDAP *ld) { - int i, ntrees, st = 0, tempst = 0, gothandle = 0; + int *count, LDAP *ld) +{ + int i, st = 0, tempst = 0, gothandle = 0; + unsigned int ntrees; char *refcntattr[2]; char *filter = NULL; char **subtree = NULL, *ptr = NULL; @@ -1810,11 +1823,12 @@ cleanup: } /* remove overlapping and repeated subtree entries from the list of subtrees */ -krb5_error_code remove_overlapping_subtrees(char **listin, char ***listop, int *subtcount, int sscope) +krb5_error_code +remove_overlapping_subtrees(char **listin, char **listop, int *subtcount, int sscope) { int slen=0, k=0, j=0, lendiff=0; int count = *subtcount; - char **subtree = *listop; + char **subtree = listop; slen = count-1; for (k=0; k<=slen && listin[k]!=NULL ; k++) { @@ -1870,6 +1884,311 @@ krb5_error_code remove_overlapping_subtrees(char **listin, char ***listop, int * return 0; } +/* + * Fill out a krb5_db_entry princ entry struct given a LDAP message containing + * the results of a principal search of the directory. + */ +krb5_error_code +populate_krb5_db_entry (krb5_context context, + krb5_ldap_context *ldap_context, + LDAP *ld, + LDAPMessage *ent, + krb5_const_principal princ, + krb5_db_entry *entry) +{ + krb5_error_code st = 0; + unsigned int mask = 0; + krb5_boolean attr_present = FALSE; + char **values = NULL, *policydn = NULL, *pwdpolicydn = NULL; + char *polname = NULL, *tktpolname = NULL; + struct berval **bvalues = NULL; + krb5_tl_data userinfo_tl_data = {0}; + char **link_references = NULL; + krb5_ui_2 entry_len; + char *DN = NULL; + + if (princ == NULL) { + /* XXX WAF probably should just extract princ from ldap result */ + st = EINVAL; + goto cleanup; + } else { + if ((st=krb5_copy_principal(context, princ, &(entry->princ))) != 0) + goto cleanup; + } + /* get the associated directory user information */ + if ((values = ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { + int i, pcount=0, kerberos_principal_object_type=0; + char *user; + + if ((st=krb5_unparse_name(context, princ, &user)) != 0) + goto cleanup; + + for (i=0; values[i] != NULL; ++i) { + if (strcasecmp(values[i], user) == 0) { + pcount = ldap_count_values(values); + break; + } + } + ldap_value_free(values); + free(user); + + if ((DN = ldap_get_dn(ld, ent)) == NULL) { + ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &st); + st = set_ldap_error(context, st, 0); + goto cleanup; + } + + if ((values=ldap_get_values(ld, ent, "objectclass")) != NULL) { + for (i=0; values[i] != NULL; ++i) + if (strcasecmp(values[i], "krbprincipal") == 0) { + kerberos_principal_object_type = KDB_STANDALONE_PRINCIPAL_OBJECT; + if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCTYPE, + &kerberos_principal_object_type)) != 0) + goto cleanup; + break; + } + ldap_value_free(values); + } + + /* add principalcount, DN and principaltype user information to tl_data */ + if (((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCCOUNT, &pcount)) != 0) || + ((st=store_tl_data(&userinfo_tl_data, KDB_TL_USERDN, DN)) != 0)) + goto cleanup; + } + + /* read all the kerberos attributes */ + + /* KRBLASTSUCCESSFULAUTH */ + if ((st=krb5_ldap_get_time(ld, ent, "krbLastSuccessfulAuth", + &(entry->last_success), &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) + mask |= KDB_LAST_SUCCESS; + + /* KRBLASTFAILEDAUTH */ + if ((st=krb5_ldap_get_time(ld, ent, "krbLastFailedAuth", + &(entry->last_failed), &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) + mask |= KDB_LAST_FAILED; + + /* KRBLOGINFAILEDCOUNT */ + if (krb5_ldap_get_value(ld, ent, "krbLoginFailedCount", + &(entry->fail_auth_count)) == 0) + mask |= KDB_FAIL_AUTH_COUNT; + + /* KRBMAXTICKETLIFE */ + if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", &(entry->max_life)) == 0) + mask |= KDB_MAX_LIFE_ATTR; + + /* KRBMAXRENEWABLEAGE */ + if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", + &(entry->max_renewable_life)) == 0) + mask |= KDB_MAX_RLIFE_ATTR; + + /* KRBTICKETFLAGS */ + if (krb5_ldap_get_value(ld, ent, "krbticketflags", &(entry->attributes)) == 0) + mask |= KDB_TKT_FLAGS_ATTR; + + /* PRINCIPAL EXPIRATION TIME */ + if ((st=krb5_ldap_get_time(ld, ent, "krbprincipalexpiration", &(entry->expiration), + &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) + mask |= KDB_PRINC_EXPIRE_TIME_ATTR; + + /* PASSWORD EXPIRATION TIME */ + if ((st=krb5_ldap_get_time(ld, ent, "krbpasswordexpiration", &(entry->pw_expiration), + &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) + mask |= KDB_PWD_EXPIRE_TIME_ATTR; + + /* KRBPOLICYREFERENCE */ + + if ((st=krb5_ldap_get_string(ld, ent, "krbticketpolicyreference", &policydn, + &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) { + /* Ensure that the policy is inside the realm container */ + if ((st = krb5_ldap_policydn_to_name (context, policydn, &tktpolname)) != 0) + goto cleanup; + } + + /* KRBPWDPOLICYREFERENCE */ + if ((st=krb5_ldap_get_string(ld, ent, "krbpwdpolicyreference", &pwdpolicydn, + &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) { + krb5_tl_data kadm_tl_data; + + mask |= KDB_PWD_POL_REF_ATTR; + + /* Ensure that the policy is inside the realm container */ + if ((st = krb5_ldap_policydn_to_name (context, pwdpolicydn, &polname)) != 0) + goto cleanup; + + if ((st = krb5_update_tl_kadm_data(polname, &kadm_tl_data)) != 0) { + goto cleanup; + } + krb5_dbe_update_tl_data(context, entry, &kadm_tl_data); + } + + /* KRBSECRETKEY */ + if ((bvalues=ldap_get_values_len(ld, ent, "krbprincipalkey")) != NULL) { + mask |= KDB_SECRET_KEY; + if ((st=krb5_decode_krbsecretkey(context, entry, bvalues, &userinfo_tl_data)) != 0) + goto cleanup; + } + + /* LAST PASSWORD CHANGE */ + { + krb5_timestamp lstpwdchng=0; + if ((st=krb5_ldap_get_time(ld, ent, "krbLastPwdChange", + &lstpwdchng, &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) { + if ((st=krb5_dbe_update_last_pwd_change(context, entry, + lstpwdchng))) + goto cleanup; + mask |= KDB_LAST_PWD_CHANGE_ATTR; + } + } + + /* KRBOBJECTREFERENCES */ + { + int i=0; + + if ((st = krb5_ldap_get_strings(ld, ent, "krbobjectreferences", + &link_references, &attr_present)) != 0) + goto cleanup; + if (link_references != NULL) { + for (i=0; link_references[i] != NULL; ++i) { + if ((st = store_tl_data(&userinfo_tl_data, KDB_TL_LINKDN, + link_references[i])) != 0) + goto cleanup; + } + } + } + + /* Set tl_data */ + { + int i; + struct berval **ber_tl_data = NULL; + krb5_tl_data *ptr = NULL; + + if ((ber_tl_data = ldap_get_values_len (ld, ent, "krbExtraData")) != NULL) { + for (i = 0; ber_tl_data[i] != NULL; i++) { + if ((st = berval2tl_data (ber_tl_data[i] , &ptr)) != 0) + break; + if ((st = krb5_dbe_update_tl_data(context, entry, ptr)) != 0) + break; + } + ldap_value_free_len (ber_tl_data); + if (st != 0) + goto cleanup; + mask |= KDB_EXTRA_DATA; + } + } + + /* update the mask of attributes present on the directory object to the tl_data */ + if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_MASK, &mask)) != 0) + goto cleanup; + if ((st=krb5_dbe_update_tl_data(context, entry, &userinfo_tl_data)) != 0) + goto cleanup; + +#ifdef HAVE_EDIRECTORY + { + krb5_timestamp expiretime=0; + char *is_login_disabled=NULL; + + /* LOGIN EXPIRATION TIME */ + if ((st=krb5_ldap_get_time(ld, ent, "loginexpirationtime", &expiretime, + &attr_present)) != 0) + goto cleanup; + + if (attr_present == TRUE) { + if ((mask & KDB_PRINC_EXPIRE_TIME_ATTR) == 1) { + if (expiretime < entry->expiration) + entry->expiration = expiretime; + } else { + entry->expiration = expiretime; + } + } + + /* LOGIN DISABLED */ + if ((st=krb5_ldap_get_string(ld, ent, "logindisabled", &is_login_disabled, + &attr_present)) != 0) + goto cleanup; + if (attr_present == TRUE) { + if (strcasecmp(is_login_disabled, "TRUE")== 0) + entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX; + free (is_login_disabled); + } + } +#endif + + if ((st=krb5_read_tkt_policy (context, ldap_context, entry, tktpolname)) !=0) + goto cleanup; + + /* We already know that the policy is inside the realm container. */ + if (polname) { + osa_policy_ent_t pwdpol; + int cnt=0; + krb5_timestamp last_pw_changed; + krb5_ui_4 pw_max_life; + + memset(&pwdpol, 0, sizeof(pwdpol)); + + if ((st=krb5_ldap_get_password_policy(context, polname, &pwdpol, &cnt)) != 0) + goto cleanup; + pw_max_life = pwdpol->pw_max_life; + free (pwdpol); + + if (pw_max_life > 0) { + if ((st=krb5_dbe_lookup_last_pwd_change(context, entry, &last_pw_changed)) != 0) + goto cleanup; + + if ((mask & KDB_PWD_EXPIRE_TIME_ATTR) == 1) { + if ((last_pw_changed + pw_max_life) < entry->pw_expiration) + entry->pw_expiration = last_pw_changed + pw_max_life; + } else + entry->pw_expiration = last_pw_changed + pw_max_life; + } + } + /* XXX so krb5_encode_princ_contents() will be happy */ + entry->len = KRB5_KDB_V1_BASE_LENGTH; + +cleanup: + + if (DN != NULL) + ldap_memfree(DN); + + if (userinfo_tl_data.tl_data_contents != NULL) + free(userinfo_tl_data.tl_data_contents); + + if (pwdpolicydn != NULL) + free(pwdpolicydn); + + if (polname != NULL) + free(polname); + + if (tktpolname != NULL) + free (tktpolname); + + if (policydn != NULL) + free(policydn); + + if (link_references) { + int i; + for (i=0; link_references[i] != NULL; ++i) + free (link_references[i]); + free (link_references); + } + + return (st); +} + /* * Solaris libldap does not provide the following functions which are in * OpenLDAP. diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h index ce9250d5c..5fc969f46 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h @@ -28,6 +28,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #ifndef _HAVE_LDAP_MISC_H #define _HAVE_LDAP_MISC_H 1 @@ -137,4 +142,12 @@ krb5_ldap_name_to_policydn (krb5_context, char *, char **); krb5_error_code krb5_ldap_get_db_opt(char *, char **, char **); +krb5_error_code +populate_krb5_db_entry(krb5_context context, + krb5_ldap_context *ldap_context, + LDAP *ld, + LDAPMessage *ent, + krb5_const_principal princ, + krb5_db_entry *entry); + #endif diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c index 3ace96cba..28507a9f7 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c @@ -27,6 +27,10 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ #include "ldap_main.h" #include "kdb_ldap.h" @@ -130,7 +134,6 @@ krb5_ldap_free_principal(kcontext , entries, nentries) return 0; } - krb5_error_code krb5_ldap_iterate(context, match_expr, func, func_arg) krb5_context context; @@ -141,7 +144,6 @@ krb5_ldap_iterate(context, match_expr, func, func_arg) krb5_db_entry entry; krb5_principal principal; char **subtree=NULL, *princ_name=NULL, *realm=NULL, **values=NULL, *filter=NULL; - char *krbprincipal_attr[] = { "krbPrincipalName", NULL }; unsigned int filterlen=0, tree=0, ntree=1, i=0; krb5_error_code st=0, tempst=0; LDAP *ld=NULL; @@ -184,21 +186,29 @@ krb5_ldap_iterate(context, match_expr, func, func_arg) GET_HANDLE(); - for (tree=0; treelrparams->search_scope, filter, krbprincipal_attr); + LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes); for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) { if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { for (i=0; values[i] != NULL; ++i) { + if (values[i]) if (krb5_ldap_parse_principal_name(values[i], &princ_name) != 0) continue; if (krb5_parse_name(context, princ_name, &principal) != 0) continue; if (is_principal_in_realm(ldap_context, principal) == 0) { - entry.princ = principal; + if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, principal, + &entry)) != 0) + goto cleanup; (*func)(func_arg, &entry); + krb5_dbe_free_contents(context, &entry); + (void) krb5_free_principal(context, principal); + if (princ_name) + free(princ_name); + break; } - krb5_free_principal(context, principal); + (void) krb5_free_principal(context, principal); if (princ_name) free(princ_name); } diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h index c4f5e93b7..7d3734bd4 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h @@ -129,4 +129,13 @@ krb5_ldap_unparse_principal_name(char *); krb5_error_code krb5_ldap_parse_principal_name(char *, char **); +krb5_error_code +krb5_decode_krbsecretkey(krb5_context, krb5_db_entry *, struct berval **, + krb5_tl_data *); + +krb5_error_code +berval2tl_data(struct berval *in, krb5_tl_data **out); + +krb5_error_code +krb5_read_tkt_policy (krb5_context, krb5_ldap_context *, krb5_db_entry *, char *); #endif diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c index 9ba4cb6d9..71200eb9e 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c @@ -27,6 +27,10 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ #include #include "ldap_main.h" @@ -40,20 +44,13 @@ extern char* principal_attributes[]; extern char* max_pwd_life_attr[]; -#if !defined(LDAP_OPT_RESULT_CODE) && defined(LDAP_OPT_ERROR_NUMBER) -#define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER -#endif - -static krb5_error_code -krb5_decode_krbsecretkey(krb5_context, krb5_db_entry *, struct berval **, krb5_tl_data *); - -static krb5_error_code -krb5_read_tkt_policy (krb5_context, krb5_ldap_context *, krb5_db_entry *, char *); static char * getstringtime(krb5_timestamp); -static krb5_error_code berval2tl_data (struct berval *in, krb5_tl_data **out) { +krb5_error_code +berval2tl_data(struct berval *in, krb5_tl_data **out) +{ *out = (krb5_tl_data *) malloc (sizeof (krb5_tl_data)); if (*out == NULL) return ENOMEM; @@ -84,21 +81,15 @@ krb5_ldap_get_principal(context, searchfor, entries, nentries, more) int *nentries; /* how much room/how many found */ krb5_boolean *more; /* are there more? */ { - char *user=NULL, *DN=NULL, *filter=NULL, **subtree=NULL; - unsigned int tree=0, ntrees=1, mask=0, princlen=0; + char *user=NULL, *filter=NULL, **subtree=NULL; + unsigned int tree=0, ntrees=1, princlen=0; krb5_error_code tempst=0, st=0; - char **values=NULL, *policydn=NULL, *pwdpolicydn=NULL; - char *polname = NULL, *tktpolname = NULL; - char **link_references=NULL; - krb5_tl_data userinfo_tl_data={0}; - struct berval **bvalues=NULL; + char **values=NULL; LDAP *ld=NULL; LDAPMessage *result=NULL, *ent=NULL; krb5_ldap_context *ldap_context=NULL; kdb5_dal_handle *dal_handle=NULL; krb5_ldap_server_handle *ldap_server_handle=NULL; - krb5_principal parsed_mod_name=NULL; - krb5_boolean attr_present=FALSE; /* Clear the global error string */ krb5_clear_error_message(context); @@ -129,7 +120,7 @@ krb5_ldap_get_principal(context, searchfor, entries, nentries, more) goto cleanup; princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */ - if ((filter=malloc(princlen)) == NULL) { + if ((filter = malloc(princlen)) == NULL) { st = ENOMEM; goto cleanup; } @@ -139,14 +130,14 @@ krb5_ldap_get_principal(context, searchfor, entries, nentries, more) goto cleanup; GET_HANDLE(); - for (tree=0; treelrparams->search_scope, filter, principal_attributes); for (ent=ldap_first_entry(ld, result); ent != NULL && *nentries == 0; ent=ldap_next_entry(ld, ent)) { /* get the associated directory user information */ if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { - int i=0, pcount=0, kerberos_principal_object_type=0; + int i; /* a wild-card in a principal name can return a list of kerberos principals. * Make sure that the correct principal is returned. @@ -155,7 +146,6 @@ krb5_ldap_get_principal(context, searchfor, entries, nentries, more) for (i=0; values[i] != NULL; ++i) { if (strcasecmp(values[i], user) == 0) { *nentries = 1; - pcount = ldap_count_values(values); break; } } @@ -163,198 +153,11 @@ krb5_ldap_get_principal(context, searchfor, entries, nentries, more) if (*nentries == 0) /* no matching principal found */ continue; - - if ((DN = ldap_get_dn(ld, ent)) == NULL) { - ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st); - st = set_ldap_error (context, st, 0); - goto cleanup; - } - - if ((values=ldap_get_values(ld, ent, "objectclass")) != NULL) { - for (i=0; values[i] != NULL; ++i) - if (strcasecmp(values[i], "krbprincipal") == 0) { - kerberos_principal_object_type = KDB_STANDALONE_PRINCIPAL_OBJECT; - if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCTYPE, &kerberos_principal_object_type)) != 0) - goto cleanup; - break; - } - ldap_value_free(values); - } - - /* add principalcount, DN and principaltype user information to tl_data */ - if (((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCCOUNT, &pcount)) != 0) || - ((st=store_tl_data(&userinfo_tl_data, KDB_TL_USERDN, DN)) != 0)) - goto cleanup; - } - - /* populate entries->princ with searchfor value */ - if ((st=krb5_copy_principal(context, searchfor, &(entries->princ))) != 0) - goto cleanup; - - /* read all the kerberos attributes */ - -#ifdef KRBCONF_KDC_MODIFIES_KDB - /* KRBLASTSUCCESSFULAUTH */ - if ((st=krb5_ldap_get_time(ld, ent, "krbLastSuccessfulAuth", &(entries->last_success),&attr_present)) != 0) - goto cleanup; - if (attr_present == TRUE) - mask |= KDB_LAST_SUCCESS; - - /* KRBLASTFAILEDAUTH */ - if ((st=krb5_ldap_get_time(ld, ent, "krbLastFailedAuth", &(entries->last_failed),&attr_present)) != 0) - goto cleanup; - if (attr_present == TRUE) - mask |= KDB_LAST_FAILED; - - /* KRBLOGINFAILEDCOUNT */ - if (krb5_ldap_get_value(ld, ent, "krbLoginFailedCount", &(entries->fail_auth_count)) == 0) - mask |= KDB_FAIL_AUTH_COUNT; -#endif - - /* KRBMAXTICKETLIFE */ - if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", &(entries->max_life)) == 0) - mask |= KDB_MAX_LIFE_ATTR; - - /* KRBMAXRENEWABLEAGE */ - if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &(entries->max_renewable_life)) == 0) - mask |= KDB_MAX_RLIFE_ATTR; - - /* KRBTICKETFLAGS */ - if (krb5_ldap_get_value(ld, ent, "krbticketflags", &(entries->attributes)) == 0) - mask |= KDB_TKT_FLAGS_ATTR; - - /* PRINCIPAL EXPIRATION TIME */ - if ((st=krb5_ldap_get_time(ld, ent, "krbprincipalexpiration", &(entries->expiration), - &attr_present)) != 0) - goto cleanup; - if (attr_present == TRUE) - mask |= KDB_PRINC_EXPIRE_TIME_ATTR; - - /* PASSWORD EXPIRATION TIME */ - if ((st=krb5_ldap_get_time(ld, ent, "krbpasswordexpiration", &(entries->pw_expiration), - &attr_present)) != 0) - goto cleanup; - if (attr_present == TRUE) - mask |= KDB_PWD_EXPIRE_TIME_ATTR; - - /* KRBPOLICYREFERENCE */ - - if ((st=krb5_ldap_get_string(ld, ent, "krbticketpolicyreference", &policydn, &attr_present)) != 0) - goto cleanup; - - if (attr_present == TRUE) { - /* Ensure that the policy is inside the realm container */ - if ((st = krb5_ldap_policydn_to_name (context, policydn, &tktpolname)) != 0) - goto cleanup; - } - - /* KRBPWDPOLICYREFERENCE */ - if ((st=krb5_ldap_get_string(ld, ent, "krbpwdpolicyreference", &pwdpolicydn, &attr_present)) != 0) - goto cleanup; - if (attr_present == TRUE) { - krb5_tl_data kadm_tl_data; - - mask |= KDB_PWD_POL_REF_ATTR; - - /* Ensure that the policy is inside the realm container */ - if ((st = krb5_ldap_policydn_to_name (context, pwdpolicydn, &polname)) != 0) - goto cleanup; - - if ((st = krb5_update_tl_kadm_data(polname, &kadm_tl_data)) != 0) { - goto cleanup; - } - krb5_dbe_update_tl_data(context, entries, &kadm_tl_data); - } - - /* KRBSECRETKEY */ - if ((bvalues=ldap_get_values_len(ld, ent, "krbprincipalkey")) != NULL) { - mask |= KDB_SECRET_KEY; - if ((st=krb5_decode_krbsecretkey(context, entries, bvalues, &userinfo_tl_data)) != 0) - goto cleanup; - } - - /* LAST PASSWORD CHANGE */ - { - krb5_timestamp lstpwdchng=0; - if ((st=krb5_ldap_get_time(ld, ent, "krbLastPwdChange", - &lstpwdchng, &attr_present)) != 0) - goto cleanup; - if (attr_present == TRUE) { - if ((st=krb5_dbe_update_last_pwd_change(context, entries, - lstpwdchng))) - goto cleanup; - mask |= KDB_LAST_PWD_CHANGE_ATTR; - } - } - - /* KRBOBJECTREFERENCES */ - { - int i=0; - if ((st=krb5_ldap_get_strings(ld, ent, "krbobjectreferences", &link_references, &attr_present)) != 0) - goto cleanup; - if (link_references != NULL) { - for (i=0; link_references[i] != NULL; ++i) { - if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_LINKDN, link_references[i])) != 0) - goto cleanup; - } - } } - /* Set tl_data */ - { - int i; - struct berval **ber_tl_data = NULL; - krb5_tl_data *ptr = NULL; - - if ((ber_tl_data = ldap_get_values_len (ld, ent, "krbExtraData")) != NULL) { - for (i = 0; ber_tl_data[i] != NULL; i++) { - if ((st = berval2tl_data (ber_tl_data[i] , &ptr)) != 0) - break; - if ((st = krb5_dbe_update_tl_data(context, entries, ptr)) != 0) - break; - } - ldap_value_free_len (ber_tl_data); - if (st != 0) - goto cleanup; - mask |= KDB_EXTRA_DATA; - } - } - - /* update the mask of attributes present on the directory object to the tl_data */ - if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_MASK, &mask)) != 0) - goto cleanup; - if ((st=krb5_dbe_update_tl_data(context, entries, &userinfo_tl_data)) != 0) + if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, searchfor, + entries)) != 0) goto cleanup; - -#ifdef HAVE_EDIRECTORY - { - krb5_timestamp expiretime=0; - char *is_login_disabled=NULL; - - /* LOGIN EXPIRATION TIME */ - if ((st=krb5_ldap_get_time(ld, ent, "loginexpirationtime", &expiretime, - &attr_present)) != 0) - goto cleanup; - - if (attr_present == TRUE) { - if ((mask & KDB_PRINC_EXPIRE_TIME_ATTR) == 1) { - if (expiretime < entries->expiration) - entries->expiration = expiretime; - } else { - entries->expiration = expiretime; - } - } - - /* LOGIN DISABLED */ - if ((st=krb5_ldap_get_string(ld, ent, "logindisabled", &is_login_disabled, &attr_present)) != 0) - goto cleanup; - if (attr_present == TRUE) { - if (strcasecmp(is_login_disabled,"TRUE")== 0) - entries->attributes |= KRB5_KDB_DISALLOW_ALL_TIX; - free (is_login_disabled); - } - } -#endif } ldap_msgfree(result); result = NULL; @@ -364,39 +167,6 @@ krb5_ldap_get_principal(context, searchfor, entries, nentries, more) krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); ldap_server_handle = NULL; - /* if principal not found */ - if (*nentries == 0) - goto cleanup; - - if ((st=krb5_read_tkt_policy (context, ldap_context, entries, tktpolname)) !=0) - goto cleanup; - - /* We already know that the policy is inside the realm container. */ - if (polname) { - osa_policy_ent_t pwdpol; - int cnt=0; - krb5_timestamp last_pw_changed; - krb5_ui_4 pw_max_life; - - memset(&pwdpol, 0, sizeof(pwdpol)); - - if ((st=krb5_ldap_get_password_policy(context, polname, &pwdpol, &cnt)) != 0) - goto cleanup; - pw_max_life = pwdpol->pw_max_life; - free (pwdpol); - - if (pw_max_life > 0) { - if ((st=krb5_dbe_lookup_last_pwd_change(context, entries, &last_pw_changed)) != 0) - goto cleanup; - - if ((mask & KDB_PWD_EXPIRE_TIME_ATTR) == 1) { - if ((last_pw_changed + pw_max_life) < entries->pw_expiration) - entries->pw_expiration = last_pw_changed + pw_max_life; - } else - entries->pw_expiration = last_pw_changed + pw_max_life; - } - } - cleanup: ldap_msgfree(result); @@ -406,9 +176,6 @@ cleanup: if (filter) free (filter); - if (DN) - ldap_memfree (DN); - if (subtree) { for (; ntrees; --ntrees) if (subtree[ntrees-1]) @@ -416,30 +183,12 @@ cleanup: free (subtree); } - if (userinfo_tl_data.tl_data_contents) - free(userinfo_tl_data.tl_data_contents); - if (ldap_server_handle) krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); if (user) free(user); - if (parsed_mod_name) - krb5_free_principal(context, parsed_mod_name); - - if (pwdpolicydn) - free(pwdpolicydn); - - if (polname != NULL) - free(polname); - - if (tktpolname != NULL) - free (tktpolname); - - if (policydn) - free(policydn); - return st; } @@ -725,9 +474,10 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) if ((st=process_db_args(context, db_args, &xargs, optype)) != 0) goto cleanup; - if (entries->mask & KADM5_LOAD && principal_dn == NULL) { + if (entries->mask & KADM5_LOAD) { int tree = 0, ntrees = 0, princlen = 0, numlentries = 0; char **subtreelist = NULL, *filter = NULL; + krb5_boolean found_entry = FALSE; /* A load operation is special, will do a mix-in (add krbprinc * attrs to a non-krb object entry) if an object exists with a * matching krbprincipalname attribute so try to find existing @@ -753,7 +503,7 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) goto cleanup; /* search for entry with matching krbprincipalname attribute */ - for (tree = 0; principal_dn == NULL && tree < ntrees; ++tree) { + for (tree = 0; found_entry == FALSE && tree < ntrees; ++tree) { result = NULL; LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS); if (st == LDAP_SUCCESS) { @@ -767,15 +517,18 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) user); goto cleanup; } else if (numlentries == 1) { - ent = ldap_first_entry(ld, result); - if (ent != NULL) { - /* setting principal_dn will cause that entry to be modified further down */ - if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) { - ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st); - st = set_ldap_error (context, st, 0); - ldap_msgfree(result); - free(filter); - goto cleanup; + found_entry = TRUE; + if (principal_dn == NULL) { + ent = ldap_first_entry(ld, result); + if (ent != NULL) { + /* setting principal_dn will cause that entry to be modified further down */ + if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) { + ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st); + st = set_ldap_error (context, st, 0); + ldap_msgfree(result); + free(filter); + goto cleanup; + } } } } @@ -792,7 +545,14 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) * be created. */ } /* end for (tree = 0; principal_dn == ... */ + free(filter); + + if (found_entry == FALSE) { + create_standalone_prinicipal = TRUE; + standalone_principal_dn = strdup(principal_dn); + CHECK_NULL(standalone_principal_dn); + } } /* end if (entries->mask & KADM5_LOAD && principal_dn == NULL */ /* time to generate the DN information with the help of @@ -967,10 +727,36 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) krb5_set_error_message(context, st, "%s", errbuf); goto cleanup; } + /* + * Check the link information. If there is already a link + * existing then this operation is not allowed. + */ + { + char **linkdns=NULL; + int j=0; + + if ((st=krb5_get_linkdn(context, entries, &linkdns)) != 0) { + snprintf(errbuf, sizeof(errbuf), + "Failed getting object references"); + krb5_set_error_message(context, st, "%s", errbuf); + goto cleanup; + } + if (linkdns != NULL) { + st = EINVAL; + snprintf(errbuf, sizeof(errbuf), + "kerberos principal is already linked " + "to a ldap object"); + krb5_set_error_message(context, st, "%s", errbuf); + for (j=0; linkdns[j] != NULL; ++j) + free (linkdns[j]); + free (linkdns); + goto cleanup; + } + } + establish_links = TRUE; } -#ifdef KRBCONF_KDC_MODIFIES_KDB if ((entries->last_success)!=0) { memset(strval, 0, sizeof(strval)); if ((strval[0]=getstringtime(entries->last_success)) == NULL) @@ -997,7 +783,6 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_REPLACE, entries->fail_auth_count)) !=0) goto cleanup; } -#endif if (entries->mask & KDB_MAX_LIFE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entries->max_life)) != 0) @@ -1320,7 +1105,7 @@ cleanup: return(st); } -static krb5_error_code +krb5_error_code krb5_read_tkt_policy (context, ldap_context, entries, policy) krb5_context context; krb5_ldap_context *ldap_context; @@ -1378,7 +1163,7 @@ cleanup: return st; } -static krb5_error_code +krb5_error_code krb5_decode_krbsecretkey(context, entries, bvalues, userinfo_tl_data) krb5_context context; krb5_db_entry *entries; diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c index c4b085011..ba77b8f23 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c @@ -27,13 +27,17 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ #include "ldap_main.h" #include "kdb_ldap.h" #include "ldap_pwd_policy.h" #include "ldap_err.h" -static char *password_policy_attributes[] = { "krbmaxpwdlife", "krbminpwdlife", +static char *password_policy_attributes[] = { "cn", "krbmaxpwdlife", "krbminpwdlife", "krbpwdmindiffchars", "krbpwdminlength", "krbpwdhistorylength", NULL }; @@ -176,11 +180,38 @@ cleanup: } krb5_error_code -krb5_ldap_get_password_policy_from_dn (context, name, policy, cnt) - krb5_context context; - char *name; - osa_policy_ent_t *policy; - int *cnt; +populate_policy(krb5_context context, + LDAP *ld, + LDAPMessage *ent, + char *pol_name, + osa_policy_ent_t pol_entry) +{ + int st = 0; + + pol_entry->name = strdup(pol_name); + CHECK_NULL(pol_entry->name); + pol_entry->version = 1; + + krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &(pol_entry->pw_max_life)); + krb5_ldap_get_value(ld, ent, "krbminpwdlife", &(pol_entry->pw_min_life)); + krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &(pol_entry->pw_min_classes)); + krb5_ldap_get_value(ld, ent, "krbpwdminlength", &(pol_entry->pw_min_length)); + krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &(pol_entry->pw_history_num)); + + /* Get the reference count */ + st = krb5_ldap_get_reference_count (context, pol_name, "krbPwdPolicyReference", + &(pol_entry->policy_refcnt), ld); + +cleanup: + return st; +} + +krb5_error_code +krb5_ldap_get_password_policy_from_dn (krb5_context context, + char *pol_name, + char *pol_dn, + osa_policy_ent_t *policy, + int *cnt) { krb5_error_code st=0, tempst=0; LDAP *ld=NULL; @@ -193,9 +224,10 @@ krb5_ldap_get_password_policy_from_dn (context, name, policy, cnt) krb5_clear_error_message(context); /* validate the input parameters */ - if (name == NULL) + if (pol_dn == NULL) return EINVAL; + *policy = NULL; SETUP_CONTEXT(); GET_HANDLE(); @@ -207,13 +239,19 @@ krb5_ldap_get_password_policy_from_dn (context, name, policy, cnt) } memset(*policy, 0, sizeof(osa_policy_ent_rec)); - LDAP_SEARCH(name, LDAP_SCOPE_BASE, "(objectclass=krbPwdPolicy)", password_policy_attributes); + LDAP_SEARCH(pol_dn, LDAP_SCOPE_BASE, "(objectclass=krbPwdPolicy)", password_policy_attributes); *cnt = 1; - (*policy)->name = name; +#if 0 /************** Begin IFDEF'ed OUT *******************************/ + (*policy)->name = strdup(name); + CHECK_NULL((*policy)->name); (*policy)->version = 1; +#endif /**************** END IFDEF'ed OUT *******************************/ ent=ldap_first_entry(ld, result); if (ent != NULL) { + if ((st = populate_policy(context, ld, ent, pol_name, *policy)) != 0) + goto cleanup; +#if 0 /************** Begin IFDEF'ed OUT *******************************/ krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &((*policy)->pw_max_life)); krb5_ldap_get_value(ld, ent, "krbminpwdlife", &((*policy)->pw_min_life)); krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &((*policy)->pw_min_classes)); @@ -226,13 +264,14 @@ krb5_ldap_get_password_policy_from_dn (context, name, policy, cnt) "krbPwdPolicyReference", &(*policy)->policy_refcnt, ld); +#endif /**************** END IFDEF'ed OUT *******************************/ } cleanup: ldap_msgfree(result); if (st != 0) { if (*policy != NULL) { - free (*policy); + krb5_ldap_free_password_policy(context, *policy); *policy = NULL; } } @@ -264,16 +303,15 @@ krb5_ldap_get_password_policy (context, name, policy, cnt) goto cleanup; } - st = krb5_ldap_name_to_policydn (context, name, &policy_dn); + st = krb5_ldap_name_to_policydn(context, name, &policy_dn); if (st != 0) goto cleanup; - st = krb5_ldap_get_password_policy_from_dn (context, policy_dn, policy, cnt); - free (policy_dn); - if (st == 0) - (*policy)->name = name; + st = krb5_ldap_get_password_policy_from_dn(context, name, policy_dn, policy, cnt); cleanup: + if (policy_dn != NULL) + free (policy_dn); return st; } @@ -324,7 +362,7 @@ krb5_ldap_iterate_password_policy(context, match_expr, func, func_arg) krb5_pointer func_arg; { osa_policy_ent_rec *entry=NULL; - char *attrs[] = { "cn", NULL }, *policy=NULL; + char *policy=NULL; krb5_error_code st=0, tempst=0; LDAP *ld=NULL; LDAPMessage *result=NULL, *ent=NULL; @@ -338,16 +376,12 @@ krb5_ldap_iterate_password_policy(context, match_expr, func, func_arg) SETUP_CONTEXT(); GET_HANDLE(); - entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)); - CHECK_NULL(entry); - memset(entry, 0, sizeof(osa_policy_ent_rec)); - if (ldap_context->lrparams->realmdn == NULL) { st = EINVAL; goto cleanup; } - LDAP_SEARCH(ldap_context->lrparams->realmdn, LDAP_SCOPE_ONELEVEL, "(objectclass=krbpwdpolicy)", attrs); + LDAP_SEARCH(ldap_context->lrparams->realmdn, LDAP_SCOPE_ONELEVEL, "(objectclass=krbpwdpolicy)", password_policy_attributes); for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) { krb5_boolean attr_present; @@ -356,9 +390,34 @@ krb5_ldap_iterate_password_policy(context, match_expr, func, func_arg) goto cleanup; if (attr_present == FALSE) continue; + + entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)); + CHECK_NULL(entry); + memset(entry, 0, sizeof(osa_policy_ent_rec)); + if ((st = populate_policy(context, ld, ent, policy, entry)) != 0) + goto cleanup; +#if 0 /************** Begin IFDEF'ed OUT *******************************/ entry->name = policy; + entry->version = 1; + + krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &(entry->pw_max_life)); + krb5_ldap_get_value(ld, ent, "krbminpwdlife", &(entry->pw_min_life)); + krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &(entry->pw_min_classes)); + krb5_ldap_get_value(ld, ent, "krbpwdminlength", &(entry->pw_min_length)); + krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &(entry->pw_history_num)); + + /* Get the reference count */ + st = krb5_ldap_get_reference_count (context, + policy, + "krbPwdPolicyReference", + &(entry->policy_refcnt), + ld); +#endif /**************** END IFDEF'ed OUT *******************************/ + (*func)(func_arg, entry); - ldap_memfree(policy); + /* XXX this will free policy so don't free it */ + krb5_ldap_free_password_policy(context, entry); + entry = NULL; } ldap_msgfree(result); @@ -375,7 +434,10 @@ krb5_ldap_free_password_policy (context, entry) krb5_context context; osa_policy_ent_t entry; { - if (entry) + if (entry) { + if (entry->name) + free(entry->name); free(entry); + } return; } diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c index dee22cccd..3013838ea 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c @@ -28,9 +28,15 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #include "ldap_main.h" #include "ldap_realm.h" #include "ldap_principal.h" +#include "ldap_pwd_policy.h" #include "ldap_err.h" #define END_OF_LIST -1 -- 2.26.2