s4-kdc Add common setup, handle RODC setup case
authorAndrew Bartlett <abartlet@samba.org>
Tue, 28 Sep 2010 03:05:37 +0000 (13:05 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 28 Sep 2010 18:23:07 +0000 (04:23 +1000)
This means we just set up the system_session etc in one place
and don't diverge between the MIT and Heimdal plugins.

We also now determine if we are an RODC and store some details
that we will need later.

Andrew Bartlett

source4/kdc/db-glue.c
source4/kdc/db-glue.h
source4/kdc/hdb-samba4.c
source4/kdc/mit_samba.c
source4/kdc/samba_kdc.h

index bad32535029db775a48c6cead47655cc2f3b63da..2cda04bca8fcc143f57ca48d44a53a92a4616b3b 100644 (file)
@@ -1565,3 +1565,138 @@ samba_kdc_check_pkinit_ms_upn_match(krb5_context context,
        return ret;
 }
 
+NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_context *base_ctx,
+                               struct samba_kdc_db_context **kdc_db_ctx_out)
+{
+       NTSTATUS nt_status;
+       int ldb_ret;
+       struct ldb_message *msg;
+       struct auth_session_info *session_info;
+       struct samba_kdc_db_context *kdc_db_ctx;
+       /* The idea here is very simple.  Using Kerberos to
+        * authenticate the KDC to the LDAP server is higly likely to
+        * be circular.
+        *
+        * In future we may set this up to use EXERNAL and SSL
+        * certificates, for now it will almost certainly be NTLMSSP_SET_USERNAME
+       */
+
+       kdc_db_ctx = talloc_zero(mem_ctx, struct samba_kdc_db_context);
+       if (kdc_db_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       kdc_db_ctx->ev_ctx = base_ctx->ev_ctx;
+       kdc_db_ctx->lp_ctx = base_ctx->lp_ctx;
+
+#if 1
+       /* we would prefer to use system_session(), as that would
+        * allow us to share the samdb backend context with other parts of the
+        * system. For now we can't as we need to override the
+        * credentials to set CRED_DONT_USE_KERBEROS, which would
+        * break other users of the system_session */
+       DEBUG(0,("FIXME: Using new system session for hdb\n"));
+       nt_status = auth_system_session_info(kdc_db_ctx, base_ctx->lp_ctx, &session_info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+              return nt_status;
+       }
+#else
+       session_info = system_session(kdc_db_ctx->lp_ctx);
+       if (session_info == NULL) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+#endif
+
+       cli_credentials_set_kerberos_state(session_info->credentials,
+                                          CRED_DONT_USE_KERBEROS);
+
+       /* Setup the link to LDB */
+       kdc_db_ctx->samdb = samdb_connect(kdc_db_ctx, base_ctx->ev_ctx,
+                                         base_ctx->lp_ctx, session_info);
+       if (kdc_db_ctx->samdb == NULL) {
+               DEBUG(1, ("hdb_samba4_create: Cannot open samdb for KDC backend!"));
+               talloc_free(kdc_db_ctx);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+
+       /* Find out our own krbtgt kvno */
+       ldb_ret = samdb_rodc(kdc_db_ctx->samdb, &kdc_db_ctx->rodc);
+       if (ldb_ret != LDB_SUCCESS) {
+               DEBUG(1, ("hdb_samba4_create: Cannot determine if we are an RODC in KDC backend: %s\n",
+                         ldb_errstring(kdc_db_ctx->samdb)));
+               talloc_free(kdc_db_ctx);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+       if (kdc_db_ctx->rodc) {
+               int my_krbtgt_number;
+               const char *secondary_keytab[] = { "msDS-SecondaryKrbTgtNumber", NULL };
+               struct ldb_dn *account_dn;
+               struct ldb_dn *server_dn = samdb_server_dn(kdc_db_ctx->samdb, kdc_db_ctx);
+               if (!server_dn) {
+                       DEBUG(1, ("hdb_samba4_create: Cannot determine server DN in KDC backend: %s\n",
+                                 ldb_errstring(kdc_db_ctx->samdb)));
+                       talloc_free(kdc_db_ctx);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+
+               ldb_ret = samdb_reference_dn(kdc_db_ctx->samdb, kdc_db_ctx, server_dn,
+                                            "serverReference", &account_dn);
+               if (ldb_ret != LDB_SUCCESS) {
+                       DEBUG(1, ("hdb_samba4_create: Cannot determine server account in KDC backend: %s\n",
+                                 ldb_errstring(kdc_db_ctx->samdb)));
+                       talloc_free(kdc_db_ctx);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+
+               ldb_ret = samdb_reference_dn(kdc_db_ctx->samdb, kdc_db_ctx, account_dn,
+                                            "msDS-KrbTgtLink", &kdc_db_ctx->krbtgt_dn);
+               talloc_free(account_dn);
+               if (ldb_ret != LDB_SUCCESS) {
+                       DEBUG(1, ("hdb_samba4_create: Cannot determine RODC krbtgt account in KDC backend: %s\n",
+                                 ldb_errstring(kdc_db_ctx->samdb)));
+                       talloc_free(kdc_db_ctx);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+
+               ldb_ret = dsdb_search_one(kdc_db_ctx->samdb, kdc_db_ctx,
+                                         &msg, kdc_db_ctx->krbtgt_dn, LDB_SCOPE_BASE,
+                                         secondary_keytab,
+                                         0,
+                                         "(&(objectClass=user)(msDS-SecondaryKrbTgtNumber=*))");
+               if (ldb_ret != LDB_SUCCESS) {
+                       DEBUG(1, ("hdb_samba4_create: Cannot read krbtgt account %s in KDC backend to get msDS-SecondaryKrbTgtNumber: %s: %s\n",
+                                 ldb_dn_get_linearized(kdc_db_ctx->krbtgt_dn),
+                                 ldb_errstring(kdc_db_ctx->samdb),
+                                 ldb_strerror(ldb_ret)));
+                       talloc_free(kdc_db_ctx);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+               my_krbtgt_number = ldb_msg_find_attr_as_int(msg, "msDS-SecondaryKrbTgtNumber", -1);
+               if (my_krbtgt_number == -1) {
+                       DEBUG(1, ("hdb_samba4_create: Cannot read msDS-SecondaryKrbTgtNumber from krbtgt account %s in KDC backend: got %d\n",
+                                 ldb_dn_get_linearized(kdc_db_ctx->krbtgt_dn),
+                                 my_krbtgt_number));
+                       talloc_free(kdc_db_ctx);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+               kdc_db_ctx->my_krbtgt_number = my_krbtgt_number;
+
+       } else {
+               kdc_db_ctx->my_krbtgt_number = 0;
+               ldb_ret = dsdb_search_one(kdc_db_ctx->samdb, kdc_db_ctx,
+                                         &msg, NULL, LDB_SCOPE_SUBTREE,
+                                         krbtgt_attrs,
+                                         DSDB_SEARCH_SHOW_EXTENDED_DN,
+                                         "(&(objectClass=user)(samAccountName=krbtgt))");
+
+               if (ldb_ret != LDB_SUCCESS) {
+                       DEBUG(1, ("samba_kdc_fetch: could not find own KRBTGT in DB: %s\n", ldb_errstring(kdc_db_ctx->samdb)));
+                       talloc_free(kdc_db_ctx);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+               kdc_db_ctx->krbtgt_dn = talloc_steal(kdc_db_ctx, msg->dn);
+               kdc_db_ctx->my_krbtgt_number = 0;
+               talloc_free(msg);
+       }
+       *kdc_db_ctx_out = kdc_db_ctx;
+       return NT_STATUS_OK;
+}
index 33ba7078224459c754ae173de9790c36d3e50faf..5f9c39dfb686038e9e6e57d39fe81cf20814eb9c 100644 (file)
@@ -46,3 +46,6 @@ samba_kdc_check_pkinit_ms_upn_match(krb5_context context,
                                    struct samba_kdc_db_context *kdc_db_ctx,
                                    hdb_entry_ex *entry,
                                    krb5_const_principal certificate_principal);
+
+NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_context *base_ctx,
+                               struct samba_kdc_db_context **kdc_db_ctx_out);
index 6534dbd27a0ef68327e3011fda49cf706821a473..cbc00df0aef6ceba55da0a26d08b9ea15c40fc9c 100644 (file)
@@ -162,7 +162,6 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
                               krb5_context context, struct HDB **db)
 {
        struct samba_kdc_db_context *kdc_db_ctx;
-       struct auth_session_info *session_info;
        NTSTATUS nt_status;
 
        *db = talloc(base_ctx, HDB);
@@ -175,50 +174,11 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
        (*db)->hdb_db = NULL;
        (*db)->hdb_capability_flags = 0;
 
-#if 1
-       /* we would prefer to use system_session(), as that would
-        * allow us to share the samdb backend context with other parts of the
-        * system. For now we can't as we need to override the
-        * credentials to set CRED_DONT_USE_KERBEROS, which would
-        * break other users of the system_session */
-       DEBUG(0,("FIXME: Using new system session for hdb\n"));
-       nt_status = auth_system_session_info(*db, base_ctx->lp_ctx, &session_info);
+       nt_status = samba_kdc_setup_db_ctx(*db, base_ctx, &kdc_db_ctx);
        if (!NT_STATUS_IS_OK(nt_status)) {
-              return nt_status;
+               talloc_free(*db);
+               return nt_status;
        }
-#else
-       session_info = system_session(kdc_db_ctx->lp_ctx);
-       if (session_info == NULL) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-#endif
-
-       /* The idea here is very simple.  Using Kerberos to
-        * authenticate the KDC to the LDAP server is higly likely to
-        * be circular.
-        *
-        * In future we may set this up to use EXERNAL and SSL
-        * certificates, for now it will almost certainly be NTLMSSP_SET_USERNAME
-       */
-
-       cli_credentials_set_kerberos_state(session_info->credentials,
-                                          CRED_DONT_USE_KERBEROS);
-
-       kdc_db_ctx = talloc_zero(*db, struct samba_kdc_db_context);
-       if (kdc_db_ctx == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       kdc_db_ctx->ev_ctx = base_ctx->ev_ctx;
-       kdc_db_ctx->lp_ctx = base_ctx->lp_ctx;
-
-       /* Setup the link to LDB */
-       kdc_db_ctx->samdb = samdb_connect(kdc_db_ctx, base_ctx->ev_ctx,
-                                         base_ctx->lp_ctx, session_info);
-       if (kdc_db_ctx->samdb == NULL) {
-               DEBUG(1, ("hdb_samba4_create: Cannot open samdb for KDC backend!"));
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-
        (*db)->hdb_db = kdc_db_ctx;
 
        (*db)->hdb_dbc = NULL;
index 58ab1673ff8bd4bf51c40481946cd1c857747f0d..217f0983ae413a2701f9e59a240152dc09b2e624 100644 (file)
@@ -53,10 +53,11 @@ static void mit_samba_context_free(struct mit_samba_context *ctx)
 
 static int mit_samba_context_init(struct mit_samba_context **_ctx)
 {
+       NTSTATUS status;
        struct mit_samba_context *ctx;
        const char *s4_conf_file;
        int ret;
-
+       struct samba_kdc_base_context base_ctx;
 
        ctx = talloc(NULL, struct mit_samba_context);
        if (!ctx) {
@@ -64,46 +65,27 @@ static int mit_samba_context_init(struct mit_samba_context **_ctx)
                goto done;
        }
 
-       ctx->db_ctx = talloc_zero(ctx, struct samba_kdc_db_context);
-       if (!ctx->db_ctx) {
-               ret = ENOMEM;
-               goto done;
-       }
-
-       ctx->db_ctx->ev_ctx = tevent_context_init(ctx);
-       if (!ctx->db_ctx->ev_ctx) {
+       base_ctx.ev_ctx = tevent_context_init(ctx);
+       if (!base_ctx.ev_ctx) {
                ret = ENOMEM;
                goto done;
        }
-       ctx->db_ctx->lp_ctx = loadparm_init(ctx);
-       if (!ctx->db_ctx->lp_ctx) {
+       base_ctx.lp_ctx = loadparm_init(ctx);
+       if (!base_ctx.lp_ctx) {
                ret = ENOMEM;
                goto done;
        }
-
        /* init s4 configuration */
-       s4_conf_file = lpcfg_configfile(ctx->db_ctx->lp_ctx);
+       s4_conf_file = lpcfg_configfile(base_ctx.lp_ctx);
        if (s4_conf_file) {
-               lpcfg_load(ctx->db_ctx->lp_ctx, s4_conf_file);
+               lpcfg_load(base_ctx.lp_ctx, s4_conf_file);
        } else {
-               lpcfg_load_default(ctx->db_ctx->lp_ctx);
+               lpcfg_load_default(base_ctx.lp_ctx);
        }
 
-       ctx->session_info = system_session(ctx->db_ctx->lp_ctx);
-       if (!ctx->session_info) {
-               ret = EFAULT;
-               goto done;
-       }
-
-       cli_credentials_set_kerberos_state(ctx->session_info->credentials,
-                                          CRED_DONT_USE_KERBEROS);
-
-       ctx->db_ctx->samdb = samdb_connect(ctx->db_ctx,
-                                          ctx->db_ctx->ev_ctx,
-                                          ctx->db_ctx->lp_ctx,
-                                          ctx->session_info);
-       if (!ctx->db_ctx->samdb) {
-               ret = EFAULT;
+       status = samba_kdc_setup_db_ctx(ctx, &base_ctx, &ctx->db_ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = EINVAL;
                goto done;
        }
 
index bfa868f422282e700dea13ea57cdf15bea41b735..72b5cc42e4ac9df700cdb691c75466ab345138e9 100644 (file)
@@ -33,6 +33,9 @@ struct samba_kdc_db_context {
        struct loadparm_context *lp_ctx;
        struct ldb_context *samdb;
        struct samba_kdc_seq *seq_ctx;
+       bool rodc;
+       unsigned int my_krbtgt_number;
+       struct ldb_dn *krbtgt_dn;
 };
 
 struct samba_kdc_entry {