s4:kdc Only get the lp_ctx once for a LDB_fetch()
[samba.git] / source4 / kdc / hdb-samba4.c
index eda7867bb5ea1a135829ffaa23acfdac8ecc1909..367eee5f14be0fed79c173c1d733da3abca16afe 100644 (file)
@@ -485,6 +485,7 @@ out:
  * Construct an hdb_entry from a directory entry.
  */
 static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, 
+                                        struct loadparm_context *lp_ctx, 
                                         TALLOC_CTX *mem_ctx, krb5_const_principal principal,
                                         enum hdb_ldb_ent_type ent_type,
                                         struct ldb_dn *realm_dn,
@@ -495,7 +496,6 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
        int i;
        krb5_error_code ret = 0;
        krb5_boolean is_computer = FALSE;
-       struct loadparm_context *lp_ctx = ldb_get_opaque((struct ldb_context *)db->hdb_db, "loadparm");
        char *realm = strupper_talloc(mem_ctx, lp_realm(lp_ctx));
 
        struct hdb_ldb_private *p;
@@ -909,73 +909,6 @@ out:
 
 }
 
-static krb5_error_code LDB_lookup_principal(krb5_context context, struct ldb_context *ldb_ctx,                                         
-                                           TALLOC_CTX *mem_ctx,
-                                           krb5_const_principal principal,
-                                           enum hdb_ldb_ent_type ent_type,
-                                           struct ldb_dn *realm_dn,
-                                           struct ldb_message **pmsg)
-{
-       krb5_error_code ret;
-       int lret;
-       char *filter = NULL;
-       const char * const *princ_attrs = user_attrs;
-       char *short_princ;
-       char *short_princ_talloc;
-
-       ret = krb5_unparse_name_flags(context, principal,  KRB5_PRINCIPAL_UNPARSE_NO_REALM, &short_princ);
-
-       if (ret != 0) {
-               krb5_set_error_message(context, ret, "LDB_lookup_principal: could not parse principal");
-               krb5_warnx(context, "LDB_lookup_principal: could not parse principal");
-               return ret;
-       }
-
-       short_princ_talloc = talloc_strdup(mem_ctx, short_princ);
-       free(short_princ);
-       if (!short_princ_talloc) {
-               ret = ENOMEM;
-               krb5_set_error_message(context, ret, "LDB_lookup_principal: talloc_strdup() failed!");
-               return ret;
-       }
-
-       switch (ent_type) {
-       case HDB_SAMBA4_ENT_TYPE_CLIENT:
-       case HDB_SAMBA4_ENT_TYPE_TRUST:
-       case HDB_SAMBA4_ENT_TYPE_ANY:
-               /* Can't happen */
-               return EINVAL;
-       case HDB_SAMBA4_ENT_TYPE_KRBTGT:
-               filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(samAccountName=%s))", 
-                                        KRB5_TGS_NAME);
-               break;
-       case HDB_SAMBA4_ENT_TYPE_SERVER:
-               filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(samAccountName=%s))", 
-                                        short_princ_talloc);
-               break;
-       }
-
-       if (!filter) {
-               ret = ENOMEM;
-               krb5_set_error_message(context, ret, "talloc_asprintf: out of memory");
-               return ret;
-       }
-
-       lret = gendb_search_single_extended_dn(ldb_ctx, mem_ctx, 
-                                              realm_dn, LDB_SCOPE_SUBTREE,
-                                              pmsg, princ_attrs, "%s", filter);
-       if (lret == LDB_ERR_NO_SUCH_OBJECT) {
-               DEBUG(3, ("Failed find a entry for %s\n", filter));
-               return HDB_ERR_NOENTRY;
-       }
-       if (lret != LDB_SUCCESS) {
-               DEBUG(3, ("Failed single search for for %s - %s\n", 
-                         filter, ldb_errstring(ldb_ctx)));
-               return HDB_ERR_NOENTRY;
-       }
-       return 0;
-}
-
 static krb5_error_code LDB_lookup_trust(krb5_context context, struct ldb_context *ldb_ctx,                                     
                                        TALLOC_CTX *mem_ctx,
                                        const char *realm,
@@ -1046,6 +979,7 @@ static krb5_error_code LDB_rename(krb5_context context, HDB *db, const char *new
 }
 
 static krb5_error_code LDB_fetch_client(krb5_context context, HDB *db, 
+                                       struct loadparm_context *lp_ctx, 
                                        TALLOC_CTX *mem_ctx, 
                                        krb5_const_principal principal,
                                        unsigned flags,
@@ -1074,13 +1008,14 @@ static krb5_error_code LDB_fetch_client(krb5_context context, HDB *db,
                return EINVAL;
        }
        
-       ret = LDB_message2entry(context, db, mem_ctx, 
+       ret = LDB_message2entry(context, db, lp_ctx, mem_ctx, 
                                principal, HDB_SAMBA4_ENT_TYPE_CLIENT,
                                realm_dn, msg, entry_ex);
        return ret;
 }
 
 static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, 
+                                       struct loadparm_context *lp_ctx, 
                                        TALLOC_CTX *mem_ctx, 
                                        krb5_const_principal principal,
                                        unsigned flags,
@@ -1090,7 +1025,6 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
        struct ldb_message *msg = NULL;
        struct ldb_dn *realm_dn = ldb_get_default_basedn(db->hdb_db);
        const char *realm;
-       struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(db->hdb_db, "loadparm"), struct loadparm_context);
 
        krb5_principal alloc_principal = NULL;
        if (principal->name.name_string.len != 2
@@ -1107,8 +1041,26 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
                /* Cludge, cludge cludge.  If the realm part of krbtgt/realm,
                 * is in our db, then direct the caller at our primary
                 * krbtgt */
+
+               int lret;
+               char *realm_fixed;
+               const char * const *princ_attrs = user_attrs;
                
-               char *realm_fixed = strupper_talloc(mem_ctx, lp_realm(lp_ctx));
+               lret = gendb_search_single_extended_dn(db->hdb_db, mem_ctx, 
+                                                      realm_dn, LDB_SCOPE_SUBTREE,
+                                                      &msg, princ_attrs, 
+                                                      "(&(objectClass=user)(samAccountName=krbtgt))"); 
+               if (lret == LDB_ERR_NO_SUCH_OBJECT) {
+                       krb5_warnx(context, "LDB_fetch: could not find own KRBTGT in DB!");
+                       krb5_set_error_message(context, HDB_ERR_NOENTRY, "LDB_fetch: could not find own KRBTGT in DB!");
+                       return HDB_ERR_NOENTRY;
+               } else if (lret != LDB_SUCCESS) {
+                       krb5_warnx(context, "LDB_fetch: could not find own KRBTGT in DB: %s", ldb_errstring(db->hdb_db));
+                       krb5_set_error_message(context, HDB_ERR_NOENTRY, "LDB_fetch: could not find own KRBTGT in DB: %s", ldb_errstring(db->hdb_db));
+                       return HDB_ERR_NOENTRY;
+               }
+               
+               realm_fixed = strupper_talloc(mem_ctx, lp_realm(lp_ctx));
                if (!realm_fixed) {
                        ret = ENOMEM;
                        krb5_set_error_message(context, ret, "strupper_talloc: out of memory");
@@ -1130,17 +1082,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
                }
                principal = alloc_principal;
 
-               ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, 
-                                          mem_ctx, 
-                                          principal, HDB_SAMBA4_ENT_TYPE_KRBTGT, realm_dn, &msg);
-               
-               if (ret != 0) {
-                       krb5_warnx(context, "LDB_fetch: could not find principal in DB");
-                       krb5_set_error_message(context, ret, "LDB_fetch: could not find principal in DB");
-                       return ret;
-               }
-               
-               ret = LDB_message2entry(context, db, mem_ctx, 
+               ret = LDB_message2entry(context, db, lp_ctx, mem_ctx, 
                                        principal, HDB_SAMBA4_ENT_TYPE_KRBTGT, 
                                        realm_dn, msg, entry_ex);
                if (ret != 0) {
@@ -1193,6 +1135,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
 }
 
 static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, 
+                                       struct loadparm_context *lp_ctx,
                                        TALLOC_CTX *mem_ctx, 
                                        krb5_const_principal principal,
                                        unsigned flags,
@@ -1238,22 +1181,41 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db,
                }
                
        } else {
+               int lret;
+               char *filter = NULL;
+               const char * const *princ_attrs = user_attrs;
+               char *short_princ;
                /* server as client principal case, but we must not lookup userPrincipalNames */
-               realm_dn = ldb_get_default_basedn((struct ldb_context *)db->hdb_db);
+               realm_dn = ldb_get_default_basedn(db->hdb_db);
                realm = krb5_principal_get_realm(context, principal);
                
-               /* Check if it is our realm, otherwise give referall */
-
-               ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, 
-                                          mem_ctx, 
-                                          principal, HDB_SAMBA4_ENT_TYPE_SERVER, realm_dn, &msg);
+               /* TODO: Check if it is our realm, otherwise give referall */
+               
+               ret = krb5_unparse_name_flags(context, principal,  KRB5_PRINCIPAL_UNPARSE_NO_REALM, &short_princ);
                
                if (ret != 0) {
+                       krb5_set_error_message(context, ret, "LDB_lookup_principal: could not parse principal");
+                       krb5_warnx(context, "LDB_lookup_principal: could not parse principal");
                        return ret;
                }
+               
+               lret = gendb_search_single_extended_dn(db->hdb_db, mem_ctx, 
+                                                      realm_dn, LDB_SCOPE_SUBTREE,
+                                                      &msg, princ_attrs, "(&(objectClass=user)(samAccountName=%s))", 
+                                                      ldb_binary_encode_string(mem_ctx, short_princ));
+               free(short_princ);
+               if (lret == LDB_ERR_NO_SUCH_OBJECT) {
+                       DEBUG(3, ("Failed find a entry for %s\n", filter));
+                       return HDB_ERR_NOENTRY;
+               }
+               if (lret != LDB_SUCCESS) {
+                       DEBUG(3, ("Failed single search for for %s - %s\n", 
+                                 filter, ldb_errstring(db->hdb_db)));
+                       return HDB_ERR_NOENTRY;
+               }
        }
 
-       ret = LDB_message2entry(context, db, mem_ctx, 
+       ret = LDB_message2entry(context, db, lp_ctx, mem_ctx, 
                                principal, HDB_SAMBA4_ENT_TYPE_SERVER,
                                realm_dn, msg, entry_ex);
        if (ret != 0) {
@@ -1269,8 +1231,8 @@ static krb5_error_code LDB_fetch(krb5_context context, HDB *db,
                                 hdb_entry_ex *entry_ex)
 {
        krb5_error_code ret = HDB_ERR_NOENTRY;
-
        TALLOC_CTX *mem_ctx = talloc_named(db, 0, "LDB_fetch context");
+       struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(db->hdb_db, "loadparm"), struct loadparm_context);
 
        if (!mem_ctx) {
                ret = ENOMEM;
@@ -1279,20 +1241,20 @@ static krb5_error_code LDB_fetch(krb5_context context, HDB *db,
        }
 
        if (flags & HDB_F_GET_CLIENT) {
-               ret = LDB_fetch_client(context, db, mem_ctx, principal, flags, entry_ex);
+               ret = LDB_fetch_client(context, db, lp_ctx, mem_ctx, principal, flags, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
        }
        if (flags & HDB_F_GET_SERVER) {
                /* krbtgt fits into this situation for trusted realms, and for resolving different versions of our own realm name */
-               ret = LDB_fetch_krbtgt(context, db, mem_ctx, principal, flags, entry_ex);
+               ret = LDB_fetch_krbtgt(context, db, lp_ctx, mem_ctx, principal, flags, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
 
                /* We return 'no entry' if it does not start with krbtgt/, so move to the common case quickly */
-               ret = LDB_fetch_server(context, db, mem_ctx, principal, flags, entry_ex);
+               ret = LDB_fetch_server(context, db, lp_ctx, mem_ctx, principal, flags, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
        }
        if (flags & HDB_F_GET_KRBTGT) {
-               ret = LDB_fetch_krbtgt(context, db, mem_ctx, principal, flags, entry_ex);
+               ret = LDB_fetch_krbtgt(context, db, lp_ctx, mem_ctx, principal, flags, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
        }
 
@@ -1313,6 +1275,7 @@ static krb5_error_code LDB_remove(krb5_context context, HDB *db, krb5_const_prin
 
 struct hdb_ldb_seq {
        struct ldb_context *ctx;
+       struct loadparm_context *lp_ctx;
        int index;
        int count;
        struct ldb_message **msgs;
@@ -1340,7 +1303,8 @@ static krb5_error_code LDB_seq(krb5_context context, HDB *db, unsigned flags, hd
        }
 
        if (priv->index < priv->count) {
-               ret = LDB_message2entry(context, db, mem_ctx, 
+               ret = LDB_message2entry(context, db, priv->lp_ctx, 
+                                       mem_ctx, 
                                        NULL, HDB_SAMBA4_ENT_TYPE_ANY, 
                                        priv->realm_dn, priv->msgs[priv->index++], entry);
        } else {
@@ -1361,6 +1325,8 @@ static krb5_error_code LDB_firstkey(krb5_context context, HDB *db, unsigned flag
                                        hdb_entry_ex *entry)
 {
        struct ldb_context *ldb_ctx = (struct ldb_context *)db->hdb_db;
+       struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(ldb_ctx, "loadparm"), 
+                                                         struct loadparm_context);
        struct hdb_ldb_seq *priv = (struct hdb_ldb_seq *)db->hdb_dbc;
        char *realm;
        struct ldb_result *res = NULL;
@@ -1381,6 +1347,7 @@ static krb5_error_code LDB_firstkey(krb5_context context, HDB *db, unsigned flag
        }
 
        priv->ctx = ldb_ctx;
+       priv->lp_ctx = lp_ctx;
        priv->index = 0;
        priv->msgs = NULL;
        priv->realm_dn = ldb_get_default_basedn(ldb_ctx);