enabling LDAP mix-in support for kdb5_util load
authorWill Fiveash <will.fiveash@oracle.com>
Sat, 21 Oct 2006 00:33:24 +0000 (00:33 +0000)
committerWill Fiveash <will.fiveash@oracle.com>
Sat, 21 Oct 2006 00:33:24 +0000 (00:33 +0000)
I now have mix-in working for the kdb5_util load.  If the krbSubTrees
realm attr contains a base DN where non-krb entries live the
load/krb5_ldap_put_principal() code will modify those entries whose
krbPrincipalName attr matches that of the dump princ record being loaded
otherwise a standalone krbprinc entry will be created under the realm
container.

I also fixed a small bug in krb5_ldap_policydn_to_name() for the version
that uses ldap_explode_dn().

ticket: new

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18729 dc483132-0cff-0310-8789-dd5450dbe970

src/kadmin/dbutil/dump.c
src/lib/kadm5/admin.h
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c
src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h
src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c

index e1f1d8848fdfad26faf5a7a6d7ea8254590eb101..314156ea0e2425c615168477cc6e7d18b790a995 100644 (file)
@@ -1608,7 +1608,7 @@ process_k5beta_record(fname, kcontext, filep, verbose, linenop)
                                     && (akey->key_data_length[1] == 0))
                                dbent.n_key_data--;
 
-                           dbent.mask = KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
+                           dbent.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
                                KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_KEY_DATA |
                                KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS |
                                KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT;
@@ -1762,7 +1762,7 @@ process_k5beta6_record(fname, kcontext, filep, verbose, linenop)
                    dbentry.last_success = (krb5_timestamp) t7;
                    dbentry.last_failed = (krb5_timestamp) t8;
                    dbentry.fail_auth_count = (krb5_kvno) t9;
-                   dbentry.mask = KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
+                   dbentry.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
                        KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
                        KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS |
                        KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT;
@@ -2294,8 +2294,19 @@ load_db(argc, argv)
      */
     if (!update) {
        if((kret = krb5_db_create(kcontext, db5util_db_args))) {
-           fprintf(stderr, dbcreaterr_fmt,
-                   programname, dbname, error_message(kret));
+           const char *emsg = krb5_get_error_message(kcontext, kret);
+           /* 
+            * See if something (like DAL KDB plugin) has set a specific error
+            * message and use that otherwise use default.
+            */
+
+           if (emsg != NULL) {
+               fprintf(stderr, "%s: %s\n", programname, emsg);
+               krb5_free_error_message (kcontext, emsg);
+           } else {
+               fprintf(stderr, dbcreaterr_fmt,
+                       programname, dbname, error_message(kret));
+           }
            exit_status++;
            kadm5_free_config_params(kcontext, &newparams);
            if (dumpfile) fclose(f);
@@ -2307,9 +2318,20 @@ load_db(argc, argv)
             * Initialize the database.
             */
            if ((kret = krb5_db_open(kcontext, db5util_db_args, 
-                                    KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_OTHER))) {
-               fprintf(stderr, dbinit_err_fmt,
-                       programname, error_message(kret));
+                                    KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) {
+               const char *emsg = krb5_get_error_message(kcontext, kret);
+               /* 
+                * See if something (like DAL KDB plugin) has set a specific
+                * error message and use that otherwise use default.
+                */
+
+               if (emsg != NULL) {
+                   fprintf(stderr, "%s: %s\n", programname, emsg);
+                   krb5_free_error_message (kcontext, emsg);
+               } else {
+                   fprintf(stderr, dbinit_err_fmt,
+                           programname, error_message(kret));
+               }
                exit_status++;
                goto error;
            }
index b64e9e7fc2d271f2c67d4873c04e2d8d9ea81c32..99d18d4e295d1c9bcc49a59ca68196b127652090 100644 (file)
@@ -92,9 +92,12 @@ typedef long         kadm5_ret_t;
 #define KADM5_CPW_FUNCTION      0x080000
 #define KADM5_RANDKEY_USED      0x100000
 #endif
+#define KADM5_LOAD             0x200000
+
 /* all but KEY_DATA and TL_DATA */
 #define KADM5_PRINCIPAL_NORMAL_MASK 0x01ffff
 
+
 /* kadm5_policy_ent_t */
 #define KADM5_PW_MAX_LIFE      0x004000
 #define KADM5_PW_MIN_LIFE      0x008000
index 5aed962373dbe5edc6452c426c4884526aed6ca8..e5bf6c11d7d6234afba778d04259a7994f814722 100644 (file)
@@ -374,13 +374,20 @@ krb5_error_code krb5_ldap_open(krb5_context context,
                sprintf(ldap_context->root_certificate_file,"%s %s", oldstr, val);
                free (oldstr);
            }
-       } else if (opt && !strcmp(opt, "temporary")) {
-           /* ignore temporary argument, it is a kdb5_util arg meant for db2 */
        } else {
            /* ignore hash argument. Might have been passed from create */
            status = EINVAL;
-           krb5_set_error_message (context, status, "unknown option \'%s\'",
-                                   opt?opt:val);
+           if (opt && !strcmp(opt, "temporary")) {
+               /* 
+                * temporary is passed in when kdb5_util load without -update is done.
+                * This is unsupported by the LDAP plugin.
+                */
+               krb5_set_error_message (context, status,
+                                       "open of LDAP directory aborted, plugin requires -update argument");
+           } else {
+               krb5_set_error_message (context, status, "unknown option \'%s\'",
+                                       opt?opt:val);
+           }
            free(opt);
            free(val);
            goto clean_n_exit;
index 54f0576ae7dcec203971b19a3781212e338b8b8e..3162bdc26caefaea86eb3951338ac63284320d8b 100644 (file)
@@ -54,6 +54,7 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
     krb5_ldap_context *ldap_context=NULL;
     krb5_boolean realm_obj_created = FALSE;
     krb5_boolean krbcontainer_obj_created = FALSE;
+    krb5_ldap_krbcontainer_params kparams = {0};
     int srv_cnt = 0;
     int mask = 0;
 #ifdef HAVE_EDIRECTORY
@@ -218,13 +219,20 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
                sprintf(ldap_context->root_certificate_file,"%s %s", oldstr, val);
                free (oldstr);
            }
-       } else if (opt && !strcmp(opt, "temporary")) {
-            /* ignore temporary argument, it is a kdb5_util arg meant for db2 */
        } else {
        /* ignore hash argument. Might have been passed from create */
            status = EINVAL;
-           krb5_set_error_message (context, status, "unknown option \'%s\'",
-                                   opt?opt:val);
+           if (opt && !strcmp(opt, "temporary")) {
+               /* 
+                * temporary is passed in when kdb5_util load without -update is done.
+                * This is unsupported by the LDAP plugin.
+                */
+               krb5_set_error_message (context, status,
+                   "creation of LDAP entries aborted, plugin requires -update argument");
+           } else {
+               krb5_set_error_message (context, status, "unknown option \'%s\'",
+                                       opt?opt:val);
+           }
            free(opt);
            free(val);
            goto cleanup;
@@ -252,10 +260,6 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
     /* read the kerberos container */
     if ((status = krb5_ldap_read_krbcontainer_params(context,
                            &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {
-       krb5_ldap_krbcontainer_params kparams;
-
-       /* The kerberos container does not exist so try to create. */
-       memset(&kparams, 0, sizeof(kparams));
 
        /* Read the kerberos container location from configuration file */
        if (ldap_context->conf_section) {
@@ -289,6 +293,7 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
            krb5_set_error_message(context, status, "while reading kerberos container information");
            goto cleanup;
        }
+
     } else if (status) {
        krb5_set_error_message(context, status, "while reading kerberos container information");
        goto cleanup;
@@ -333,8 +338,8 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
        if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
            for (i=0; (rparams->kdcservers[i] != NULL); i++) {
                if ((status=krb5_ldap_add_service_rights(context,
-                                                        LDAP_KDC_SERVICE, rparams->kdcservers[i],
-                                                        rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+                                    LDAP_KDC_SERVICE, rparams->kdcservers[i],
+                                    rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
                    goto cleanup;
                }
            }
@@ -346,8 +351,8 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
        if ((rparams != NULL) && (rparams->adminservers != NULL)) {
            for (i=0; (rparams->adminservers[i] != NULL); i++) {
                if ((status=krb5_ldap_add_service_rights(context,
-                                                        LDAP_ADMIN_SERVICE, rparams->adminservers[i],
-                                                        rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+                                    LDAP_ADMIN_SERVICE, rparams->adminservers[i],
+                                    rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
                    goto cleanup;
                }
            }
@@ -359,8 +364,8 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
        if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
            for (i=0; (rparams->passwdservers[i] != NULL); i++) {
                if ((status=krb5_ldap_add_service_rights(context,
-                                                        LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
-                                                        rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+                                    LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
+                                    rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
                    goto cleanup;
                }
            }
@@ -369,12 +374,19 @@ krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
 #endif
 
 cleanup:
-#if 0 /************** Begin IFDEF'ed OUT *******************************/
+
     /* If the krbcontainer/realm creation is not complete, do the roll-back here */
-    if ((krbcontainer_obj_created) && (!realm_obj_created))
-       /* XXX WAF this needs to be created !!! */
-       krb5_ldap_delete_krbcontainer(context);
-#endif /**************** END IFDEF'ed OUT *******************************/
+    if ((krbcontainer_obj_created) && (!realm_obj_created)) {
+       int rc;
+       rc = krb5_ldap_delete_krbcontainer(context,
+                   ((kparams.DN != NULL) ? &kparams : NULL));
+       krb5_set_error_message(context, rc,
+           "could not complete roll-back, error deleting Kerberos Container");
+    }
+
+    /* should call krb5_ldap_free_krbcontainer_params() but can't */
+    if (kparams.DN != NULL)
+       krb5_xfree(kparams.DN);
 
     if (rparams)
        krb5_ldap_free_realm_params(rparams);
index 7dfc2a55d8e6c413bf07f42b91e8c52348a558d1..f4510d69c6826a13007147bb2c4ec4eed7ea3205 100644 (file)
@@ -53,4 +53,8 @@ krb5_ldap_read_krbcontainer_params(krb5_context , krb5_ldap_krbcontainer_params
 krb5_error_code
 krb5_ldap_create_krbcontainer(krb5_context, const krb5_ldap_krbcontainer_params *);
 
+krb5_error_code
+krb5_ldap_delete_krbcontainer(krb5_context,
+    const krb5_ldap_krbcontainer_params *);
+
 #endif
index aa9388adc07c030983bfe8231aa251d5d4f3bef9..1d0a3203667ac3f83b9dbce4843bc1bcdc44e1ed 100644 (file)
@@ -1730,21 +1730,16 @@ krb5_error_code krb5_ldap_policydn_to_name (context, policy_dn, name)
     }
 #elif defined HAVE_LDAP_EXPLODE_DN
     {
-       char *parsed_dn;
+       char **parsed_dn;
 
-       parsed_dn = ldap_explode_dn(policy_dn, 0);
+       /* 1 = return DN components without type prefix */
+       parsed_dn = ldap_explode_dn(policy_dn, 1);
        if (parsed_dn == NULL) {
            st = EINVAL;
-       }
-       else {
-           if (strncasecmp(parsed_dn[0], "cn=", 3) != 0) {
+       } else {
+           *name = strdup(parsed_dn[0]);
+           if (*name == NULL)
                st = EINVAL;
-           }
-           else {
-               *name = strdup(parsed_dn[0]);
-               if (*name == NULL)
-                   st = EINVAL;
-           }
 
            ldap_value_free(parsed_dn);
        }
index 2a28a4e0e1db9dbe6aa6a40cd3873bbf37cff1f0..9ba4cb6d9e12ade1eda7cd0e1346125099bf3612 100644 (file)
@@ -36,6 +36,7 @@
 #include "ldap_tkt_policy.h"
 #include "ldap_pwd_policy.h"
 #include "ldap_err.h"
+#include <kadm5/admin.h>
 
 extern char* principal_attributes[];
 extern char* max_pwd_life_attr[];
@@ -662,7 +663,7 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
     register int               *nentries;         /* number of entry structs to update */
     char                       **db_args;
 {
-    int                        i=0, l=0, plen=0, kerberos_principal_object_type=0;
+    int                        i=0, l=0, kerberos_principal_object_type=0;
     krb5_error_code            st=0, tempst=0;
     LDAP                       *ld=NULL;
     LDAPMessage                 *result=NULL, *ent=NULL;
@@ -670,7 +671,7 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
     char                        **values=NULL, *strval[10]={NULL}, errbuf[1024];
     struct berval              **bersecretkey=NULL;
     LDAPMod                    **mods=NULL;
-    krb5_boolean                tktpolicy_set=FALSE, create_standalone_prinicipal=FALSE;
+    krb5_boolean                create_standalone_prinicipal=FALSE;
     krb5_boolean                krb_identity_exists=FALSE, establish_links=FALSE;
     char                        *standalone_principal_dn=NULL;
     krb5_tl_data                *tl_data=NULL;
@@ -679,7 +680,7 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
     krb5_ldap_context           *ldap_context=NULL;
     krb5_ldap_server_handle     *ldap_server_handle=NULL;
     osa_princ_ent_rec          princ_ent;
-    xargs_t                     xargs={0};
+    xargs_t                     xargs = {0};
     char                        *polname = NULL;
     OPERATION optype;
 
@@ -702,10 +703,9 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
 
        /* get the principal information to act on */
        if (entries->princ) {
-           if (((st=krb5_unparse_name(context,entries->princ, &user)) !=0) ||
+           if (((st=krb5_unparse_name(context, entries->princ, &user)) != 0) ||
                ((st=krb5_ldap_unparse_principal_name(user)) != 0))
                goto cleanup;
-           plen = strlen(user);
        }
 
        /* Identity the type of operation, it can be
@@ -725,11 +725,81 @@ 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) {
+           int              tree = 0, ntrees = 0, princlen = 0, numlentries = 0;
+           char             **subtreelist = NULL, *filter = NULL;
+           /*  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
+            *  object and set principal_dn.  This assumes that the
+            *  krbprincipalname attribute is unique (only one object entry has
+            *  a particular krbprincipalname attribute).
+            */
+           if (user == NULL) {
+               /* must have principal name for search */
+               st = EINVAL;
+               krb5_set_error_message(context, st, "operation can not continue, principal name not found");
+               goto cleanup;
+           }   
+           princlen = strlen(FILTER) + strlen(user) + 2 + 1;      /* 2 for closing brackets */
+           if ((filter = malloc(princlen)) == NULL) {
+               st = ENOMEM;
+               goto cleanup;
+           }
+           snprintf(filter, princlen, FILTER"%s))", user);
+
+           /* get the current subtree list */
+           if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0)
+               goto cleanup;
+
+           /* search for entry with matching krbprincipalname attribute */
+           for (tree = 0; principal_dn == NULL && tree < ntrees; ++tree) {
+               result = NULL;
+               LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS);
+               if (st == LDAP_SUCCESS) {
+                   numlentries = ldap_count_entries(ld, result);
+                   if (numlentries > 1) {
+                       ldap_msgfree(result);
+                       free(filter);
+                       st = EINVAL;
+                       krb5_set_error_message(context, st,
+                           "operation can not continue, more than one entry with principal name \"%s\" found",
+                           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;
+                           }
+                       }
+                   }
+                   if (result)
+                       ldap_msgfree(result);
+               } else {
+                   /* could not perform search, return with failure */
+                   st = set_ldap_error (context, st, 0);
+                   free(filter);
+                   goto cleanup;
+               }
+               /* 
+                * If it isn't found then assume a standalone princ entry is to
+                * be created.
+                */
+           } /* end for (tree = 0; principal_dn == ... */
+           free(filter);
+       } /* end if (entries->mask & KADM5_LOAD && principal_dn == NULL */
+
        /* time to generate the DN information with the help of
         * containerdn, principalcontainerreference or
         * realmcontainerdn information
         */
-       if (principal_dn ==NULL && xargs.dn == NULL) { /* creation of standalone principal */
+       if (principal_dn == NULL && xargs.dn == NULL) { /* creation of standalone principal */
            /* get the subtree information */
            if (entries->princ->length == 2 && entries->princ->data[0].length == strlen("krbtgt") &&
                strncmp(entries->princ->data[0].data, "krbtgt", entries->princ->data[0].length) == 0) {
@@ -768,7 +838,6 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
            create_standalone_prinicipal = TRUE;
            free(subtree);
            subtree = NULL;
-
        }
 
        /*
@@ -844,12 +913,11 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
                 */
                char  *attributes[]={"krbticketpolicyreference", "krbprincipalname", NULL};
 
-               LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes,IGNORE_STATUS);
+               LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS);
                if (st == LDAP_SUCCESS) {
                    ent = ldap_first_entry(ld, result);
                    if (ent != NULL) {
                        if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) {
-                           tktpolicy_set = TRUE;
                            ldap_value_free(values);
                        }
 
@@ -894,7 +962,8 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
            if (optype == MODIFY_PRINCIPAL &&
                kerberos_principal_object_type != KDB_STANDALONE_PRINCIPAL_OBJECT) {
                st = EINVAL;
-               snprintf(errbuf, sizeof(errbuf), "link information can't be set/updated as the kerberos principal belongs to an ldap object");
+               snprintf(errbuf, sizeof(errbuf),
+                   "link information can not be set/updated as the kerberos principal belongs to an ldap object");
                krb5_set_error_message(context, st, "%s", errbuf);
                goto cleanup;
            }
@@ -950,7 +1019,7 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
        if (entries->mask & KDB_PRINCIPAL) {
            memset(strval, 0, sizeof(strval));
            strval[0] = user;
-           if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_ADD, strval)) != 0)
+           if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_REPLACE, strval)) != 0)
                goto cleanup;
        }
 
@@ -979,9 +1048,9 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
        }
 
        if (entries->mask & KDB_POLICY) {
+           memset(&princ_ent, 0, sizeof(princ_ent));
            for (tl_data=entries->tl_data; tl_data; tl_data=tl_data->tl_data_next) {
                if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) {
-                   memset(&princ_ent, 0, sizeof(princ_ent));
                    /* FIX ME: I guess the princ_ent should be freed after this call */
                    if ((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) {
                        goto cleanup;
@@ -1001,6 +1070,13 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
                krb5_set_error_message(context, st, "Password policy value null");
                goto cleanup;
            }
+       } else if (entries->mask & KADM5_LOAD && principal_dn != NULL) {
+           /* 
+            * a load is special in that existing entries must have attrs that
+            * removed.
+            */
+           if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, NULL)) != 0)
+               goto cleanup;
        }
 
        if (entries->mask & KDB_POLICY_CLR) {
@@ -1121,7 +1197,6 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
 
        }
 
-
        if (establish_links == TRUE) {
            memset(strval, 0, sizeof(strval));
            strval[0] = xargs.linkdn;
@@ -1133,7 +1208,7 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
         * in case mods is NULL then return
         * not sure but can happen in a modprinc
         * so no need to return an error
-        * addprinc will atleast have the principal name
+        * addprinc will at least have the principal name
         * and the keys passed in
         */
        if (mods == NULL)
@@ -1148,7 +1223,20 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
            if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
                goto cleanup;
 
-           st=ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL);
+           st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL);
+           if (st == LDAP_ALREADY_EXISTS && entries->mask & KADM5_LOAD) {
+               /* a load operation must replace an existing entry */
+               st = ldap_delete_ext_s(ld, standalone_principal_dn, NULL, NULL);
+               if (st != LDAP_SUCCESS) {
+                   sprintf(errbuf, "Principal delete failed (trying to replace entry): %s",
+                       ldap_err2string(st));
+                   st = translate_ldap_error (st, OP_ADD);
+                   krb5_set_error_message(context, st, "%s", errbuf);
+                   goto cleanup;
+               } else {
+                   st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL);
+               }
+           }
            if (st != LDAP_SUCCESS) {
                sprintf(errbuf, "Principal add failed: %s", ldap_err2string(st));
                st = translate_ldap_error (st, OP_ADD);
@@ -1185,7 +1273,8 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
            if (xargs.dn != NULL)
                st=ldap_modify_ext_s(ld, xargs.dn, mods, NULL, NULL);
            else
-               st=ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL);
+               st = ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL);
+
            if (st != LDAP_SUCCESS) {
                sprintf(errbuf, "User modification failed: %s", ldap_err2string(st));
                st = translate_ldap_error (st, OP_MOD);
@@ -1193,7 +1282,6 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
                goto cleanup;
            }
        }
-
     }
 
 cleanup:
index 0d5357e00df4ba71c6ef2020f048f4c3e6084c22..dee22cccd552e7262e23b9cec14e94cda14b8c34 100644 (file)
@@ -189,7 +189,8 @@ krb5_ldap_list_realm(context, realms)
     char                        ***realms;
 {
     char                        **values = NULL;
-    unsigned int                i = 0, count = 0;
+    unsigned int                i = 0;
+    int                                count = 0;
     krb5_error_code             st = 0, tempst = 0;
     LDAP                        *ld = NULL;
     LDAPMessage                 *result = NULL, *ent = NULL;
@@ -1057,6 +1058,53 @@ cleanup:
     return(st);
 }
 
+/*
+ * Delete the Kerberos container in the Directory
+ */
+
+krb5_error_code
+krb5_ldap_delete_krbcontainer(krb5_context context,
+    const krb5_ldap_krbcontainer_params *krbcontparams)
+{
+    LDAP                        *ld=NULL;
+    char                        *kerberoscontdn=NULL;
+    krb5_error_code             st=0;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    SETUP_CONTEXT ();
+
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    if (krbcontparams != NULL && krbcontparams->DN != NULL) {
+       kerberoscontdn = krbcontparams->DN;
+    } else {
+       /* If the user has not given, use the default cn=Kerberos,cn=Security */
+#ifdef HAVE_EDIRECTORY
+       kerberoscontdn = KERBEROS_CONTAINER;
+#else
+       st = EINVAL;
+       krb5_set_error_message (context, st, "Kerberos Container information is missing");
+       goto cleanup;
+#endif
+    }
+
+    /* delete the kerberos container */
+    if ((st = ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL)) != LDAP_SUCCESS) {
+       int ost = st;
+       st = translate_ldap_error (st, OP_ADD);
+       krb5_set_error_message (context, st, "Kerberos Container delete FAILED: %s", ldap_err2string(ost));
+       goto cleanup;
+    }
+
+cleanup:
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return(st);
+}
+
 
 /*
  * Create Realm in eDirectory. This is used by kdb5_util