r11995: A big kerberos-related update.
authorAndrew Bartlett <abartlet@samba.org>
Thu, 1 Dec 2005 05:20:39 +0000 (05:20 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:46:56 +0000 (13:46 -0500)
This merges Samba4 up to current lorikeet-heimdal, which includes a
replacement for some Samba-specific hacks.

In particular, the credentials system now supplies GSS client and
server credentials.  These are imported into GSS with
gss_krb5_import_creds().  Unfortunetly this can't take an MEMORY
keytab, so we now create a FILE based keytab as provision and join
time.

Because the keytab is now created in advance, we don't spend .4s at
negprot doing sha1 s2k calls.  Also, because the keytab is read in
real time, any change in the server key will be correctly picked up by
the the krb5 code.

To mark entries in the secrets which should be exported to a keytab,
there is a new kerberosSecret objectClass.  The new routine
cli_credentials_update_all_keytabs() searches for these, and updates
the keytabs.

This is called in the provision.js via the ejs wrapper
credentials_update_all_keytabs().

We can now (in theory) use a system-provided /etc/krb5.keytab, if

krb5Keytab: FILE:/etc/krb5.keytab

is added to the secrets.ldb record.  By default the attribute

privateKeytab: secrets.keytab

is set, pointing to allow the whole private directory to be moved
without breaking the internal links.

27 files changed:
source/auth/credentials/credentials.c
source/auth/credentials/credentials.h
source/auth/credentials/credentials_files.c
source/auth/credentials/credentials_krb5.c
source/auth/gensec/gensec_gssapi.c
source/heimdal/kdc/kerberos5.c
source/heimdal/lib/gssapi/accept_sec_context.c
source/heimdal/lib/gssapi/acquire_cred.c
source/heimdal/lib/gssapi/arcfour.c
source/heimdal/lib/gssapi/copy_ccache.c
source/heimdal/lib/gssapi/gssapi.h
source/heimdal/lib/gssapi/gssapi_locl.h
source/heimdal/lib/gssapi/init_sec_context.c
source/heimdal/lib/gssapi/release_cred.c
source/heimdal/lib/hdb/db.c
source/heimdal/lib/hdb/hdb-protos.h
source/heimdal/lib/hdb/ndbm.c
source/heimdal/lib/krb5/cache.c
source/heimdal/lib/krb5/get_for_creds.c
source/heimdal/lib/krb5/keytab.c
source/heimdal/lib/krb5/krb5-private.h
source/heimdal/lib/krb5/krb5-protos.h
source/heimdal/lib/krb5/rd_cred.c
source/libnet/libnet_join.c
source/scripting/ejs/smbcalls_creds.c
source/scripting/libjs/provision.js
source/setup/secrets.ldif

index 86a3df0077e155534fba6a3e6491332abb722fb5..75c6795e732d99e7478bf034af25ba09852ac643 100644 (file)
@@ -46,7 +46,8 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
        cred->domain_obtained = CRED_UNINITIALISED;
        cred->realm_obtained = CRED_UNINITIALISED;
        cred->ccache_obtained = CRED_UNINITIALISED;
-       cred->gss_creds_obtained = CRED_UNINITIALISED;
+       cred->client_gss_creds_obtained = CRED_UNINITIALISED;
+       cred->server_gss_creds_obtained = CRED_UNINITIALISED;
        cred->keytab_obtained = CRED_UNINITIALISED;
        cred->principal_obtained = CRED_UNINITIALISED;
 
@@ -148,6 +149,9 @@ BOOL cli_credentials_set_principal(struct cli_credentials *cred,
        return False;
 }
 
+/* Set a callback to get the principal.  This could be a popup dialog,
+ * a terminal prompt or similar.  */
+
 BOOL cli_credentials_set_principal_callback(struct cli_credentials *cred,
                                  const char *(*principal_cb) (struct cli_credentials *))
 {
@@ -160,6 +164,10 @@ BOOL cli_credentials_set_principal_callback(struct cli_credentials *cred,
        return False;
 }
 
+/* Some of our tools are 'anonymous by default'.  This is a single
+ * function to determine if authentication has been explicitly
+ * requested */
+
 BOOL cli_credentials_authentication_requested(struct cli_credentials *cred) 
 {
        if (cred->principal_obtained >= CRED_SPECIFIED) {
@@ -190,6 +198,9 @@ const char *cli_credentials_get_password(struct cli_credentials *cred)
        return cred->password;
 }
 
+/* Set a password on the credentials context, including an indication
+ * of 'how' the password was obtained */
+
 BOOL cli_credentials_set_password(struct cli_credentials *cred, 
                                  const char *val, 
                                  enum credentials_obtained obtained)
@@ -240,7 +251,11 @@ BOOL cli_credentials_set_old_password(struct cli_credentials *cred,
 }
 
 /**
- * Obtain the password for this credentials context.
+ * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
+ *
+ * Sometimes we only have this much of the password, while the rest of
+ * the time this call avoids calling E_md4hash themselves.
+ *
  * @param cred credentials context
  * @retval If set, the cleartext password, otherwise NULL
  */
@@ -566,7 +581,13 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred)
 
 BOOL cli_credentials_is_anonymous(struct cli_credentials *cred)
 {
-       const char *username = cli_credentials_get_username(cred);
+       const char *username;
+       
+       if (cred->machine_account_pending) {
+               cli_credentials_set_machine_account(cred);
+       }
+
+       username = cli_credentials_get_username(cred);
        
        /* Yes, it is deliberate that we die if we have a NULL pointer
         * here - anonymous is "", not NULL, which is 'never specified,
index 3e84db52a57a2738ec553b16f1b90ee87c74956f..81773aa70a56977475d1890fbdc454a75f3af92f 100644 (file)
@@ -47,9 +47,10 @@ struct cli_credentials {
        enum credentials_obtained domain_obtained;
        enum credentials_obtained realm_obtained;
        enum credentials_obtained ccache_obtained;
-       enum credentials_obtained gss_creds_obtained;
+       enum credentials_obtained client_gss_creds_obtained;
        enum credentials_obtained principal_obtained;
        enum credentials_obtained keytab_obtained;
+       enum credentials_obtained server_gss_creds_obtained;
 
        const char *workstation;
        const char *username;
@@ -63,8 +64,9 @@ struct cli_credentials {
        struct samr_Password *nt_hash;
 
        struct ccache_container *ccache;
-       struct gssapi_creds_container *gssapi_creds;
+       struct gssapi_creds_container *client_gss_creds;
        struct keytab_container *keytab;
+       struct gssapi_creds_container *server_gss_creds;
 
        const char *(*workstation_cb) (struct cli_credentials *);
        const char *(*password_cb) (struct cli_credentials *);
index 35bbc43b343802c395654907814c3187e92f7e73..6b3c77c4e3aa160169b572f97f9f030ee9e11a98 100644 (file)
@@ -164,9 +164,9 @@ BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file,
  * @param cred Credentials structure to fill in
  * @retval NTSTATUS error detailing any failure
  */
-static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, 
-                                           const char *base,
-                                           const char *filter)
+NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, 
+                                    const char *base,
+                                    const char *filter)
 {
        TALLOC_CTX *mem_ctx;
        
@@ -183,6 +183,8 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
                "ntPwdHash",
                "msDS-KeyVersionNumber",
                "saltPrincipal",
+               "privateKeytab",
+               "krb5Keytab",
                NULL
        };
        
@@ -193,6 +195,7 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
        const char *realm;
        enum netr_SchannelType sct;
        const char *salt_principal;
+       const char *keytab;
        
        /* ok, we are going to get it now, don't recurse back here */
        cred->machine_account_pending = False;
@@ -201,6 +204,7 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
        cred->machine_account = True;
 
        mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password");
+
        /* Local secrets are stored in secrets.ldb */
        ldb = secrets_db_connect(mem_ctx);
        if (!ldb) {
@@ -279,7 +283,22 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
        }
 
        cli_credentials_set_kvno(cred, ldb_msg_find_int(msgs[0], "msDS-KeyVersionNumber", 0));
-       
+
+       /* If there was an external keytab specified by reference in
+        * the LDB, then use this.  Otherwise we will make one up
+        * (chewing CPU time) from the password */
+       keytab = ldb_msg_find_string(msgs[0], "krb5Keytab", NULL);
+       if (keytab) {
+               cli_credentials_set_keytab(cred, keytab, CRED_SPECIFIED);
+       } else {
+               keytab = ldb_msg_find_string(msgs[0], "privateKeytab", NULL);
+               if (keytab) {
+                       keytab = talloc_asprintf(mem_ctx, "FILE:%s", private_path(mem_ctx, keytab));
+                       if (keytab) {
+                               cli_credentials_set_keytab(cred, keytab, CRED_SPECIFIED);
+                       }
+               }
+       }
        talloc_free(mem_ctx);
        
        return NT_STATUS_OK;
@@ -345,3 +364,68 @@ void cli_credentials_set_machine_account_pending(struct cli_credentials *cred)
        cred->machine_account_pending = True;
 }
 
+
+NTSTATUS cli_credentials_update_all_keytabs(TALLOC_CTX *parent_ctx)
+{
+       TALLOC_CTX *mem_ctx;
+       int ldb_ret;
+       struct ldb_context *ldb;
+       struct ldb_message **msgs;
+       const char *attrs[] = { NULL };
+       struct cli_credentials *creds;
+       const char *filter;
+       NTSTATUS status;
+       int i, ret;
+
+       mem_ctx = talloc_new(parent_ctx);
+       if (!mem_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* Local secrets are stored in secrets.ldb */
+       ldb = secrets_db_connect(mem_ctx);
+       if (!ldb) {
+               DEBUG(1, ("Could not open secrets.ldb\n"));
+               talloc_free(mem_ctx);
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* search for the secret record */
+       ldb_ret = gendb_search(ldb,
+                              mem_ctx, NULL,
+                              &msgs, attrs,
+                              "objectClass=kerberosSecret");
+       if (ldb_ret == -1) {
+               DEBUG(1, ("Error looking for kerberos type secrets to push into a keytab"));
+               talloc_free(mem_ctx);
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       for (i=0; i < ldb_ret; i++) {
+               /* Make a credentials structure from it */
+               creds = cli_credentials_init(mem_ctx);
+               if (!creds) {
+                       DEBUG(1, ("cli_credentials_init failed!"));
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               cli_credentials_set_conf(creds);
+               filter = talloc_asprintf(mem_ctx, "dn=%s", ldb_dn_linearize(mem_ctx, msgs[i]->dn));
+               status = cli_credentials_set_secrets(creds, NULL, filter);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(1, ("Failed to read secrets for keytab update for %s\n", 
+                                 filter));
+                       talloc_free(mem_ctx);
+                       return status;
+               } 
+               ret = cli_credentials_update_keytab(creds);
+               if (ret != 0) {
+                       DEBUG(1, ("Failed to update keytab for %s\n", 
+                                 filter));
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+       return NT_STATUS_OK;
+}
+
index a3761e8359782987bda8a38bb13522ab8a30ad87..173739e9b868089ca63335173e6f235cdb92fe5d 100644 (file)
@@ -52,6 +52,10 @@ int cli_credentials_set_from_ccache(struct cli_credentials *cred,
        char *name;
        char **realm;
 
+       if (cred->ccache_obtained > obtained) {
+               return 0;
+       }
+
        ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context, 
                                    cred->ccache->ccache, &princ);
 
@@ -107,7 +111,12 @@ int cli_credentials_set_ccache(struct cli_credentials *cred,
 {
        krb5_error_code ret;
        krb5_principal princ;
-       struct ccache_container *ccc = talloc(cred, struct ccache_container);
+       struct ccache_container *ccc;
+       if (cred->ccache_obtained > obtained) {
+               return 0;
+       }
+
+       ccc = talloc(cred, struct ccache_container);
        if (!ccc) {
                return ENOMEM;
        }
@@ -265,10 +274,10 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
        OM_uint32 maj_stat, min_stat;
        struct gssapi_creds_container *gcc;
        struct ccache_container *ccache;
-       if (cred->gss_creds_obtained >= (MAX(cred->ccache_obtained, 
+       if (cred->client_gss_creds_obtained >= (MAX(cred->ccache_obtained, 
                                             MAX(cred->principal_obtained, 
                                                 cred->username_obtained)))) {
-               *_gcc = cred->gssapi_creds;
+               *_gcc = cred->client_gss_creds;
                return 0;
        }
        ret = cli_credentials_get_ccache(cred, 
@@ -283,8 +292,8 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
                return ENOMEM;
        }
 
-       maj_stat = gss_krb5_import_ccache(&min_stat, ccache->ccache
-                                          &gcc->creds);
+       maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL
+                                       &gcc->creds);
        if (maj_stat) {
                if (min_stat) {
                        ret = min_stat;
@@ -293,20 +302,20 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
                }
        }
        if (ret == 0) {
-               cred->gss_creds_obtained = cred->ccache_obtained;
+               cred->client_gss_creds_obtained = cred->ccache_obtained;
                talloc_set_destructor(gcc, free_gssapi_creds);
-               cred->gssapi_creds = gcc;
+               cred->client_gss_creds = gcc;
                *_gcc = gcc;
        }
        return ret;
 }
 
 /**
-   Set a gssapi cred_id_t into the credentails system.
+   Set a gssapi cred_id_t into the credentails system. (Client case)
 
    This grabs the credentials both 'intact' and getting the krb5
    ccache out of it.  This routine can be generalised in future for
-   the case where we deal with GSSAPI mechs other than krb5.
+   the case where we deal with GSSAPI mechs other than krb5.  
 
    On sucess, the caller must not free gssapi_cred, as it now belongs
    to the credentials system.
@@ -319,7 +328,12 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
        int ret;
        OM_uint32 maj_stat, min_stat;
        struct ccache_container *ccc;
-       struct gssapi_creds_container *gcc = talloc(cred, struct gssapi_creds_container);
+       struct gssapi_creds_container *gcc;
+       if (cred->client_gss_creds_obtained > obtained) {
+               return 0;
+       }
+
+       gcc = talloc(cred, struct gssapi_creds_container);
        if (!gcc) {
                return ENOMEM;
        }
@@ -346,18 +360,23 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
                gcc->creds = gssapi_cred;
                talloc_set_destructor(gcc, free_gssapi_creds);
                
-               cred->gss_creds_obtained = obtained;
-               cred->gssapi_creds = gcc;
+               cred->client_gss_creds_obtained = obtained;
+               cred->client_gss_creds = gcc;
        }
        return ret;
 }
 
+/* Get the keytab (actually, a container containing the krb5_keytab)
+ * attached to this context.  If this hasn't been done or set before,
+ * it will be generated from the password.
+ */
 int cli_credentials_get_keytab(struct cli_credentials *cred, 
                               struct keytab_container **_ktc)
 {
        krb5_error_code ret;
        struct keytab_container *ktc;
        struct smb_krb5_context *smb_krb5_context;
+       TALLOC_CTX *mem_ctx;
 
        if (cred->keytab_obtained >= (MAX(cred->principal_obtained, 
                                          cred->username_obtained))) {
@@ -374,16 +393,180 @@ int cli_credentials_get_keytab(struct cli_credentials *cred,
                return ret;
        }
 
-       ret = create_memory_keytab(cred, cred, smb_krb5_context, &ktc);
+       mem_ctx = talloc_new(cred);
+       if (!mem_ctx) {
+               return ENOMEM;
+       }
+
+       ret = create_memory_keytab(mem_ctx, cred, smb_krb5_context, &ktc);
        if (ret) {
+               talloc_free(mem_ctx);
                return ret;
        }
 
        cred->keytab_obtained = (MAX(cred->principal_obtained, 
                                     cred->username_obtained));
 
+       talloc_steal(cred, ktc);
        cred->keytab = ktc;
        *_ktc = cred->keytab;
+       talloc_free(mem_ctx);
+       return ret;
+}
+
+/* Given the name of a keytab (presumably in the format
+ * FILE:/etc/krb5.keytab), open it and attach it */
+
+int cli_credentials_set_keytab(struct cli_credentials *cred, 
+                              const char *keytab_name, 
+                              enum credentials_obtained obtained) 
+{
+       krb5_error_code ret;
+       struct keytab_container *ktc;
+       struct smb_krb5_context *smb_krb5_context;
+       krb5_keytab keytab;
+       TALLOC_CTX *mem_ctx;
+
+       if (cred->keytab_obtained >= obtained) {
+               return 0;
+       }
+
+       ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
+       if (ret) {
+               return ret;
+       }
+
+       mem_ctx = talloc_new(cred);
+       if (!mem_ctx) {
+               return ENOMEM;
+       }
+
+       ret = krb5_kt_resolve(smb_krb5_context->krb5_context, keytab_name, &keytab);
+       if (ret) {
+               DEBUG(1,("failed to open krb5 keytab: %s\n", 
+                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
+                                                   ret, mem_ctx)));
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       ktc = talloc(mem_ctx, struct keytab_container);
+       if (!ktc) {
+               talloc_free(mem_ctx);
+               return ENOMEM;
+       }
+
+       ktc->smb_krb5_context = talloc_reference(ktc, smb_krb5_context);
+       ktc->keytab = keytab;
+
+       cred->keytab_obtained = obtained;
+
+       talloc_steal(cred, ktc);
+       cred->keytab = ktc;
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
+int cli_credentials_update_keytab(struct cli_credentials *cred) 
+{
+       krb5_error_code ret;
+       struct keytab_container *ktc;
+       struct smb_krb5_context *smb_krb5_context;
+       TALLOC_CTX *mem_ctx;
+       
+       mem_ctx = talloc_new(cred);
+       if (!mem_ctx) {
+               return ENOMEM;
+       }
+
+       ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
+       if (ret) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       ret = cli_credentials_get_keytab(cred, &ktc);
+       if (ret != 0) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       ret = update_keytab(mem_ctx, cred, smb_krb5_context, ktc);
+
+       talloc_free(mem_ctx);
+       return ret;
+}
+
+/* Get server gss credentials (in gsskrb5, this means the keytab) */
+
+int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, 
+                                        struct gssapi_creds_container **_gcc) 
+{
+       int ret = 0;
+       OM_uint32 maj_stat, min_stat;
+       struct gssapi_creds_container *gcc;
+       struct keytab_container *ktc;
+       struct smb_krb5_context *smb_krb5_context;
+       TALLOC_CTX *mem_ctx;
+       krb5_principal princ;
+
+       if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained, 
+                                                   MAX(cred->principal_obtained, 
+                                                       cred->username_obtained)))) {
+               *_gcc = cred->server_gss_creds;
+               return 0;
+       }
+
+       ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
+       if (ret) {
+               return ret;
+       }
+
+       ret = cli_credentials_get_keytab(cred, 
+                                        &ktc);
+       if (ret) {
+               DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
+               return ret;
+       }
+
+       mem_ctx = talloc_new(cred);
+       if (!mem_ctx) {
+               return ENOMEM;
+       }
+
+       ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ);
+       if (ret) {
+               DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
+                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
+                                                   ret, mem_ctx)));
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       gcc = talloc(cred, struct gssapi_creds_container);
+       if (!gcc) {
+               talloc_free(mem_ctx);
+               return ENOMEM;
+       }
+
+       /* This creates a GSSAPI cred_id_t with the principal and keytab set */
+       maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab, 
+                                       &gcc->creds);
+       if (maj_stat) {
+               if (min_stat) {
+                       ret = min_stat;
+               } else {
+                       ret = EINVAL;
+               }
+       }
+       if (ret == 0) {
+               cred->server_gss_creds_obtained = cred->keytab_obtained;
+               talloc_set_destructor(gcc, free_gssapi_creds);
+               cred->server_gss_creds = gcc;
+               *_gcc = gcc;
+       }
+       talloc_free(mem_ctx);
        return ret;
 }
 
@@ -415,3 +598,5 @@ void cli_credentials_set_salt_principal(struct cli_credentials *cred, const char
 {
        cred->salt_principal = talloc_strdup(cred, principal);
 }
+
+
index b5a2dadd3533c3cebf8b817695290ae695044245..68da2567da6cd3979a0a243dfef2be63213bca1f 100644 (file)
@@ -41,12 +41,9 @@ struct gensec_gssapi_state {
        DATA_BLOB pac;
 
        struct smb_krb5_context *smb_krb5_context;
-       krb5_ccache ccache;
-       const char *ccache_name;
-       struct keytab_container *keytab;
        struct gssapi_creds_container *client_cred;
+       struct gssapi_creds_container *server_cred;
 
-       gss_cred_id_t cred;
        gss_cred_id_t delegated_cred_handle;
 };
 
@@ -81,10 +78,6 @@ static int gensec_gssapi_destory(void *ptr)
        struct gensec_gssapi_state *gensec_gssapi_state = ptr;
        OM_uint32 maj_stat, min_stat;
        
-       if (gensec_gssapi_state->cred != GSS_C_NO_CREDENTIAL) {
-               maj_stat = gss_release_cred(&min_stat, 
-                                           &gensec_gssapi_state->cred);
-       }
        if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
                maj_stat = gss_release_cred(&min_stat, 
                                            &gensec_gssapi_state->delegated_cred_handle);
@@ -137,7 +130,6 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
        gensec_gssapi_state->session_key = data_blob(NULL, 0);
        gensec_gssapi_state->pac = data_blob(NULL, 0);
 
-       gensec_gssapi_state->cred = GSS_C_NO_CREDENTIAL;
        gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
 
        talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destory); 
@@ -167,11 +159,10 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
 {
        NTSTATUS nt_status;
-       OM_uint32 maj_stat, min_stat;
        int ret;
-       const char *principal;
        struct gensec_gssapi_state *gensec_gssapi_state;
        struct cli_credentials *machine_account;
+       struct gssapi_creds_container *gcc;
 
        nt_status = gensec_gssapi_start(gensec_security);
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -186,53 +177,15 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
                DEBUG(3, ("No machine account credentials specified\n"));
                return NT_STATUS_INVALID_PARAMETER;
        } else {
-               ret = cli_credentials_get_keytab(machine_account, &gensec_gssapi_state->keytab);
+               ret = cli_credentials_get_server_gss_creds(machine_account, &gcc);
                if (ret) {
-                       DEBUG(3, ("Could not create memory keytab!\n"));
+                       DEBUG(1, ("Aquiring acceptor credentials failed: %s\n", 
+                                 error_message(ret)));
                        return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
                }
        }
 
-       principal = cli_credentials_get_principal(machine_account, 
-                                                 machine_account);
-
-       /* This might have been explicity set to NULL, ie use what the client calls us */
-       if (principal) {
-               gss_buffer_desc name_token;
-
-               name_token.value  = discard_const_p(uint8_t, principal);
-               name_token.length = strlen(principal);
-               
-               maj_stat = gss_import_name (&min_stat,
-                                           &name_token,
-                                           GSS_C_NT_USER_NAME,
-                                           &gensec_gssapi_state->server_name);
-
-               if (maj_stat) {
-                       DEBUG(2, ("GSS Import name of %s failed: %s\n",
-                                 (char *)name_token.value,
-                                 gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
-                       return NT_STATUS_UNSUCCESSFUL;
-               }
-       } else {
-               gensec_gssapi_state->server_name = GSS_C_NO_NAME;
-       }
-
-       maj_stat = gsskrb5_acquire_cred(&min_stat, 
-                                       gensec_gssapi_state->keytab->keytab, 
-                                       gensec_gssapi_state->server_name,
-                                       GSS_C_INDEFINITE,
-                                       GSS_C_NULL_OID_SET,
-                                       GSS_C_ACCEPT,
-                                       &gensec_gssapi_state->cred,
-                                       NULL, 
-                                       NULL);
-       if (maj_stat) {
-               DEBUG(1, ("Aquiring acceptor credentails failed: %s\n", 
-                         gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-
+       gensec_gssapi_state->server_cred = gcc;
        return NT_STATUS_OK;
 
 }
@@ -382,7 +335,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
        {
                maj_stat = gss_accept_sec_context(&min_stat, 
                                                  &gensec_gssapi_state->gssapi_context, 
-                                                 gensec_gssapi_state->cred,
+                                                 gensec_gssapi_state->server_cred->creds,
                                                  &input_token, 
                                                  gensec_gssapi_state->input_chan_bindings,
                                                  &gensec_gssapi_state->client_name, 
index 565c7478f9ac7c6c219b72784183a246b3446cf2..6f6203a92cd51dc95589b82471762e258253bbd9 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "kdc_locl.h"
 
-RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
+RCSID("$Id: kerberos5.c,v 1.198 2005/11/28 20:33:57 lha Exp $");
 
 #define MAX_TIME ((time_t)((1U << 31) - 1))
 
@@ -666,8 +666,7 @@ _kdc_check_flags(krb5_context context,
                             starttime_str, sizeof(starttime_str), TRUE); 
            kdc_log(context, config, 0,
                    "Client not yet valid until %s -- %s", 
-                   starttime_str, 
-                   client_name);
+                   starttime_str, client_name);
            return KRB5KDC_ERR_CLIENT_NOTYET;
        }
        
@@ -676,7 +675,8 @@ _kdc_check_flags(krb5_context context,
            krb5_format_time(context, *client->valid_end, 
                             endtime_str, sizeof(endtime_str), TRUE); 
            kdc_log(context, config, 0,
-                   "Client expired at %s -- %s", endtime_str, client_name);
+                   "Client expired at %s -- %s",
+                   endtime_str, client_name);
            return KRB5KDC_ERR_NAME_EXP;
        }
        
@@ -686,7 +686,8 @@ _kdc_check_flags(krb5_context context,
            krb5_format_time(context, *client->pw_end, 
                             pwend_str, sizeof(pwend_str), TRUE); 
            kdc_log(context, config, 0,
-                   "Client's key has expired at %s -- %s", pwend_str, client_name);
+                   "Client's key has expired at %s -- %s", 
+                   pwend_str, client_name);
            return KRB5KDC_ERR_KEY_EXPIRED;
        }
     }
@@ -717,7 +718,8 @@ _kdc_check_flags(krb5_context context,
            krb5_format_time(context, *server->valid_start, 
                             starttime_str, sizeof(starttime_str), TRUE); 
            kdc_log(context, config, 0,
-                   "Server not yet valid until %s -- %s", server_name);
+                   "Server not yet valid until %s -- %s",
+                   starttime_str, server_name);
            return KRB5KDC_ERR_SERVICE_NOTYET;
        }
 
@@ -1099,11 +1101,12 @@ _kdc_as_rep(krb5_context context,
        pa->padata_value.data   = NULL;
 #endif
 
-       /* RFC4120 requires:
-            - If the client only knows about old enctypes, then send both info replies
-              (we send 'info' first in the list).
-            - If the client is 'modern', because it knows about 'new' enc types, then 
-              only send the 'info2' reply.
+       /* 
+        * RFC4120 requires: 
+        * - If the client only knows about old enctypes, then send
+        *   both info replies (we send 'info' first in the list).
+        * - If the client is 'modern', because it knows about 'new'
+        *   enctype types, then only send the 'info2' reply.
        */
        /* XXX check ret */
        if (only_older_enctype_p(req))
index 5d43cdcb436441250888ed5d2e37836e943b7507..9ca60a6cddc9c5add5c71a8affcaa8e56080825d 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gssapi_locl.h"
 
-RCSID("$Id: accept_sec_context.c,v 1.53 2005/05/29 15:12:41 lha Exp $");
+RCSID("$Id: accept_sec_context.c,v 1.55 2005/11/25 15:57:35 lha Exp $");
 
 HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER;
 krb5_keytab gssapi_krb5_keytab;
@@ -125,66 +125,24 @@ gsskrb5_accept_delegated_token
     krb5_principal principal = (*context_handle)->source;
     krb5_ccache ccache = NULL;
     krb5_error_code kret;
-    int32_t ac_flags, ret;
-    gss_cred_id_t handle = NULL;
+    int32_t ac_flags, ret = GSS_S_COMPLETE;
       
-    if (delegated_cred_handle == NULL) {
-       /* XXX Create a new delegated_cred_handle? */
-
-       ret = 0;
+    *minor_status = 0;
 
+    /* XXX Create a new delegated_cred_handle? */
+    if (delegated_cred_handle == NULL)
        kret = krb5_cc_default (gssapi_krb5_context, &ccache);
-       if (kret) {
-           *flags &= ~GSS_C_DELEG_FLAG;
-           goto end_fwd;
-       }
-    } else {
-
-       *delegated_cred_handle = NULL;
-       
-       handle = calloc(1, sizeof(*handle));
-       if (handle == NULL) {
-           ret = GSS_S_FAILURE;
-           *minor_status = ENOMEM;
-           krb5_set_error_string(gssapi_krb5_context, "out of memory");
-           gssapi_krb5_set_error_string();
-           *flags &= ~GSS_C_DELEG_FLAG;
-           goto end_fwd;
-       }
-       if ((ret = gss_duplicate_name(minor_status, principal,
-                                     &handle->principal)) != 0) {
-           *flags &= ~GSS_C_DELEG_FLAG;
-           ret = 0;
-           goto end_fwd;
-       }
-       kret = krb5_cc_gen_new (gssapi_krb5_context,
-                               &krb5_mcc_ops,
-                               &handle->ccache);
-       if (kret) {
-           *flags &= ~GSS_C_DELEG_FLAG;
-           ret = 0;
-           goto end_fwd;
-       }
-       ccache = handle->ccache;
-
-       ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
-       if (ret) {
-           *flags &= ~GSS_C_DELEG_FLAG;
-           goto end_fwd;
-       }
-       ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
-                                    &handle->mechanisms);
-       if (ret) {
-           *flags &= ~GSS_C_DELEG_FLAG;
-           goto end_fwd;
-       }
+    else
+       kret = krb5_cc_gen_new (gssapi_krb5_context, &krb5_mcc_ops, &ccache);
+    if (kret) {
+       *flags &= ~GSS_C_DELEG_FLAG;
+       goto out;
     }
 
     kret = krb5_cc_initialize(gssapi_krb5_context, ccache, principal);
     if (kret) {
        *flags &= ~GSS_C_DELEG_FLAG;
-       ret = 0;
-       goto end_fwd;
+       goto out;
     }
       
     krb5_auth_con_removeflags(gssapi_krb5_context,
@@ -204,29 +162,29 @@ gsskrb5_accept_delegated_token
        *flags &= ~GSS_C_DELEG_FLAG;
        ret = GSS_S_FAILURE;
        *minor_status = kret;
-       goto end_fwd;
+       goto out;
     }
- end_fwd:
-    /* if there was some kind of failure, clean up internal structures */
-    if ((*flags & GSS_C_DELEG_FLAG) == 0) {
-       if (handle) {
-           if (handle->principal)
-               gss_release_name(minor_status, &handle->principal);
-           if (handle->mechanisms)
-               gss_release_oid_set(NULL, &handle->mechanisms);
-           if (handle->ccache)
-               krb5_cc_destroy(gssapi_krb5_context, handle->ccache);
-           free(handle);
-           handle = NULL;
-       }
+
+    if (delegated_cred_handle) {
+       ret = gss_krb5_import_cred(minor_status,
+                                  ccache,
+                                  NULL,
+                                  NULL,
+                                  delegated_cred_handle);
+       if (ret != GSS_S_COMPLETE)
+           goto out;
+
+       (*delegated_cred_handle)->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
+       ccache = NULL;
     }
-    if (delegated_cred_handle == NULL) {
-       if (ccache)
+
+out:
+    if (ccache) {
+       if (delegated_cred_handle == NULL)
            krb5_cc_close(gssapi_krb5_context, ccache);
+       else
+           krb5_cc_destroy(gssapi_krb5_context, ccache);
     }
-    if (handle)
-       *delegated_cred_handle = handle;
-
     return ret;
 }
 
@@ -1054,7 +1012,7 @@ spnego_accept_sec_context
     if(len > data.length - taglen)
        return ASN1_OVERRUN;
 
-    ret = decode_NegTokenInit((const char *)data.data + taglen, len,
+    ret = decode_NegTokenInit((const unsigned char *)data.data + taglen, len,
                              &ni, &ni_len);
     if (ret)
        return GSS_S_DEFECTIVE_TOKEN;
@@ -1065,7 +1023,7 @@ spnego_accept_sec_context
     }
 
     for (i = 0; !found && i < ni.mechTypes->len; ++i) {
-       char mechbuf[17];
+       unsigned char mechbuf[17];
        size_t mech_len;
 
        ret = der_put_oid (mechbuf + sizeof(mechbuf) - 1,
index d67b4009202c46c76c480d2d3e2a226f69570445..44dbef3c4820847e7d03f76ded20eb401f263973 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gssapi_locl.h"
 
-RCSID("$Id: acquire_cred.c,v 1.24 2005/10/26 11:25:16 lha Exp $");
+RCSID("$Id: acquire_cred.c,v 1.25 2005/11/02 08:56:25 lha Exp $");
 
 OM_uint32
 _gssapi_krb5_ccache_lifetime(OM_uint32 *minor_status,
@@ -106,7 +106,6 @@ get_keytab(krb5_context context, krb5_keytab *keytab)
 static OM_uint32 acquire_initiator_cred
                  (OM_uint32 * minor_status,
                   krb5_context context,
-                  krb5_keytab keytab,
                   const gss_name_t desired_name,
                   OM_uint32 time_req,
                   const gss_OID_set desired_mechs,
@@ -122,7 +121,7 @@ static OM_uint32 acquire_initiator_cred
     krb5_get_init_creds_opt *opt;
     krb5_ccache ccache;
     krb5_error_code kret;
-    krb5_boolean made_keytab = FALSE;
+    krb5_keytab keytab;
 
     ccache = NULL;
     def_princ = NULL;
@@ -214,7 +213,7 @@ end:
        krb5_free_cred_contents(context, &cred);
     if (def_princ != NULL)
        krb5_free_principal(context, def_princ);
-    if (made_keytab)
+    if (keytab != NULL)
        krb5_kt_close(context, keytab);
     if (ret != GSS_S_COMPLETE) {
        if (ccache != NULL)
@@ -230,7 +229,6 @@ end:
 static OM_uint32 acquire_acceptor_cred
                  (OM_uint32 * minor_status,
                   krb5_context context,
-                  krb5_keytab keytab,
                   OM_uint32 time_req,
                   const gss_OID_set desired_mechs,
                   gss_cred_usage_t cred_usage,
@@ -244,21 +242,14 @@ static OM_uint32 acquire_acceptor_cred
 
     kret = 0;
     ret = GSS_S_FAILURE;
-    if (keytab == NULL) {
-        kret = get_keytab(context, &handle->keytab);
-       if (kret)
-               goto end;
-       handle->made_keytab = TRUE;
-    } else {
-       handle->keytab = keytab;
-       handle->made_keytab = FALSE;
-    }
+    kret = get_keytab(context, &handle->keytab);
+    if (kret)
+       goto end;
     ret = GSS_S_COMPLETE;
  
 end:
     if (ret != GSS_S_COMPLETE) {
-       if (handle->made_keytab)
-           krb5_kt_close(context, handle->keytab);
+       krb5_kt_close(context, handle->keytab);
        if (kret != 0) {
            *minor_status = kret;
            gssapi_krb5_set_error_string ();
@@ -267,9 +258,8 @@ end:
     return (ret);
 }
 
-OM_uint32 gsskrb5_acquire_cred
+OM_uint32 gss_acquire_cred
            (OM_uint32 * minor_status,
-           struct krb5_keytab_data *keytab,
             const gss_name_t desired_name,
             OM_uint32 time_req,
             const gss_OID_set desired_mechs,
@@ -328,7 +318,6 @@ OM_uint32 gsskrb5_acquire_cred
     }
     if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) {
        ret = acquire_initiator_cred(minor_status, gssapi_krb5_context, 
-                                    keytab, 
                                     desired_name, time_req,
                                     desired_mechs, cred_usage, 
                                     handle, actual_mechs, time_rec);
@@ -341,7 +330,7 @@ OM_uint32 gsskrb5_acquire_cred
     }
     if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) {
        ret = acquire_acceptor_cred(minor_status, gssapi_krb5_context, 
-                                   keytab, time_req,
+                                   time_req,
                                    desired_mechs, cred_usage, 
                                    handle, actual_mechs, time_rec);
        if (ret != GSS_S_COMPLETE) {
@@ -381,24 +370,3 @@ OM_uint32 gsskrb5_acquire_cred
     return (GSS_S_COMPLETE);
 }
 
-OM_uint32 gss_acquire_cred
-           (OM_uint32 * minor_status,
-            const gss_name_t desired_name,
-            OM_uint32 time_req,
-            const gss_OID_set desired_mechs,
-            gss_cred_usage_t cred_usage,
-            gss_cred_id_t * output_cred_handle,
-            gss_OID_set * actual_mechs,
-            OM_uint32 * time_rec
-           )
-{
-       return gsskrb5_acquire_cred(minor_status,
-                                   NULL, 
-                                   desired_name,
-                                   time_req,
-                                   desired_mechs,
-                                   cred_usage,
-                                   output_cred_handle,
-                                   actual_mechs,
-                                   time_rec);
-}
index 52bb2ecf1b99491e7483cffb88b24ba5b11bd9c5..01c6c75ecc2b0f7d4f6541d53eb86d33ddd9fcc2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 - 2004 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden). 
  * All rights reserved. 
  *
@@ -33,7 +33,7 @@
 
 #include "gssapi_locl.h"
 
-RCSID("$Id: arcfour.c,v 1.17 2005/05/06 07:13:32 lha Exp $");
+RCSID("$Id: arcfour.c,v 1.18 2005/11/01 06:55:55 lha Exp $");
 
 /*
  * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
@@ -105,7 +105,7 @@ arcfour_mic_key(krb5_context context, krb5_keyblock *key,
 static krb5_error_code
 arcfour_mic_cksum(krb5_keyblock *key, unsigned usage,
                  u_char *sgn_cksum, size_t sgn_cksum_sz,
-                 const char *v1, size_t l1,
+                 const u_char *v1, size_t l1,
                  const void *v2, size_t l2,
                  const void *v3, size_t l3)
 {
@@ -256,7 +256,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
     p = token_buffer->value;
     omret = gssapi_krb5_verify_header (&p,
                                       token_buffer->length,
-                                      type,
+                                      (u_char *)type,
                                       GSS_KRB5_MECHANISM);
     if (omret)
        return omret;
index 0f2f155870164c541a6b0a1594902e581c530715..782b701e4473b809e10a26b305d03e2ba534e9c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 - 2001, 2003 Kungliga Tekniska Högskolan
+ * Copyright (c) 2000 - 2001, 2003 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden). 
  * All rights reserved. 
  *
@@ -33,7 +33,7 @@
 
 #include "gssapi_locl.h"
 
-RCSID("$Id: copy_ccache.c,v 1.9 2005/10/31 16:02:08 lha Exp $");
+RCSID("$Id: copy_ccache.c,v 1.13 2005/11/28 23:05:44 lha Exp $");
 
 OM_uint32
 gss_krb5_copy_ccache(OM_uint32 *minor_status,
@@ -63,9 +63,11 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status,
 
 
 OM_uint32
-gss_krb5_import_ccache(OM_uint32 *minor_status,
-                      krb5_ccache in,
-                      gss_cred_id_t *cred)
+gss_krb5_import_cred(OM_uint32 *minor_status,
+                    krb5_ccache id,
+                    krb5_principal keytab_principal,
+                    krb5_keytab keytab,
+                    gss_cred_id_t *cred)
 {
     krb5_error_code kret;
     gss_cred_id_t handle;
@@ -83,57 +85,94 @@ gss_krb5_import_ccache(OM_uint32 *minor_status,
     }
     HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
 
-    handle->usage = GSS_C_INITIATE;
+    handle->usage = 0;
 
-    kret = krb5_cc_get_principal(gssapi_krb5_context, in, &handle->principal);
-    if (kret) {
-       free(handle);
-       gssapi_krb5_set_error_string ();
-       *minor_status = kret;
-       return GSS_S_FAILURE;
-    }
+    if (id) {
+       char *str;
 
-    ret = _gssapi_krb5_ccache_lifetime(minor_status,
-                                      in,
-                                      handle->principal,
-                                      &handle->lifetime);
-    if (ret != GSS_S_COMPLETE) {
-       krb5_free_principal(gssapi_krb5_context, handle->principal);
-       free(handle);
-       return ret;
-    }
+       handle->usage |= GSS_C_INITIATE;
 
-    ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
-    if (ret == GSS_S_COMPLETE)
-       ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
-                                    &handle->mechanisms);
-    if (ret != GSS_S_COMPLETE) {
-       krb5_free_principal(gssapi_krb5_context, handle->principal);
-       free(handle);
-       *minor_status = kret;
-       return GSS_S_FAILURE;
+       kret = krb5_cc_get_principal(gssapi_krb5_context, id,
+                                    &handle->principal);
+       if (kret) {
+           free(handle);
+           gssapi_krb5_set_error_string ();
+           *minor_status = kret;
+           return GSS_S_FAILURE;
+       }
+       
+       if (keytab_principal) {
+           krb5_boolean match;
+
+           match = krb5_principal_compare(gssapi_krb5_context,
+                                          handle->principal,
+                                          keytab_principal);
+           if (match == FALSE) {
+               krb5_free_principal(gssapi_krb5_context, handle->principal);
+               free(handle);
+               gssapi_krb5_clear_status ();
+               *minor_status = EINVAL;
+               return GSS_S_FAILURE;
+           }
+       }
+
+       ret = _gssapi_krb5_ccache_lifetime(minor_status,
+                                          id,
+                                          handle->principal,
+                                          &handle->lifetime);
+       if (ret != GSS_S_COMPLETE) {
+           krb5_free_principal(gssapi_krb5_context, handle->principal);
+           free(handle);
+           return ret;
+       }
+
+
+       kret = krb5_cc_get_full_name(gssapi_krb5_context, id, &str);
+       if (kret)
+           goto out;
+
+       kret = krb5_cc_resolve(gssapi_krb5_context, str, &handle->ccache);
+       free(str);
+       if (kret)
+           goto out;
     }
 
-    {
-       const char *type, *name;
+
+    if (keytab) {
        char *str;
 
-       type = krb5_cc_get_type(gssapi_krb5_context, in);
-       name = krb5_cc_get_name(gssapi_krb5_context, in);
-       
-       if (asprintf(&str, "%s:%s", type, name) == -1) {
-           krb5_set_error_string(gssapi_krb5_context,
-                                 "malloc - out of memory");
-           kret = ENOMEM;
-           goto out;
+       handle->usage |= GSS_C_ACCEPT;
+
+       if (keytab_principal && handle->principal == NULL) {
+           kret = krb5_copy_principal(gssapi_krb5_context, 
+                                      keytab_principal, 
+                                      &handle->principal);
+           if (kret)
+               goto out;
        }
 
-       kret = krb5_cc_resolve(gssapi_krb5_context, str, &handle->ccache);
+       kret = krb5_kt_get_full_name(gssapi_krb5_context, keytab, &str);
+       if (kret)
+           goto out;
+
+       kret = krb5_kt_resolve(gssapi_krb5_context, str, &handle->keytab);
        free(str);
        if (kret)
            goto out;
     }
 
+
+    if (id || keytab) {
+       ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
+       if (ret == GSS_S_COMPLETE)
+           ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
+                                        &handle->mechanisms);
+       if (ret != GSS_S_COMPLETE) {
+           kret = *minor_status;
+           goto out;
+       }
+    }
+
     *minor_status = 0;
     *cred = handle;
     return GSS_S_COMPLETE;
index 64a31d1eeec0e3218411123a0073609da6dd5e4b..20700dc826e38f78c035877acd65088a49db9d4f 100644 (file)
@@ -775,18 +775,6 @@ OM_uint32 gss_unseal
  * kerberos mechanism specific functions
  */
 
-OM_uint32 gsskrb5_acquire_cred
-           (OM_uint32 * minor_status,
-           struct krb5_keytab_data *keytab,
-            const gss_name_t desired_name,
-            OM_uint32 time_req,
-            const gss_OID_set desired_mechs,
-            gss_cred_usage_t cred_usage,
-            gss_cred_id_t * output_cred_handle,
-            gss_OID_set * actual_mechs,
-            OM_uint32 * time_rec
-                  );
-
 OM_uint32
 gss_krb5_ccache_name(OM_uint32 * /*minor_status*/, 
                     const char * /*name */,
@@ -805,10 +793,11 @@ OM_uint32 gss_krb5_copy_service_keyblock
         gss_ctx_id_t context_handle,
         struct EncryptionKey **out);
 
-OM_uint32
-gss_krb5_import_ccache(OM_uint32 */*minor*/,
-                      struct krb5_ccache_data * /*in*/,
-                      gss_cred_id_t */*out*/);
+OM_uint32 gss_krb5_import_cred(OM_uint32 *minor_status,
+                              struct krb5_ccache_data * /* id */,
+                              struct Principal * /* keytab_principal */,
+                              struct krb5_keytab_data * /* keytab */,
+                              gss_cred_id_t */* cred */);
 
 OM_uint32 gss_krb5_get_tkt_flags
        (OM_uint32 */*minor*/,
index ae291d15a9a5a99ec2a0600daf2896450ae9367d..b9bea7db2e6fb0d32683ebb7d4edd6ae80c8cbf2 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE. 
  */
 
-/* $Id: gssapi_locl.h,v 1.42 2005/10/26 11:23:48 lha Exp $ */
+/* $Id: gssapi_locl.h,v 1.43 2005/11/02 08:51:17 lha Exp $ */
 
 #ifndef GSSAPI_LOCL_H
 #define GSSAPI_LOCL_H
index e7e8f5153e8ea3a3f8562ac914f4dc217a9e5e78..61c020b800ec31f78eef090035adca9ca225481d 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gssapi_locl.h"
 
-RCSID("$Id: init_sec_context.c,v 1.60 2005/10/12 07:25:18 lha Exp $");
+RCSID("$Id: init_sec_context.c,v 1.61 2005/11/02 11:52:49 lha Exp $");
 
 /*
  * copy the addresses from `input_chan_bindings' (if any) to
index ddd80c144b8695a609b891ace8f0df99911cc45d..cca3dfe37995114d9164301c6dc82da643bc4692 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gssapi_locl.h"
 
-RCSID("$Id: release_cred.c,v 1.10 2003/10/07 00:51:46 lha Exp $");
+RCSID("$Id: release_cred.c,v 1.11 2005/11/02 08:57:35 lha Exp $");
 
 OM_uint32 gss_release_cred
            (OM_uint32 * minor_status,
index d7a4cf35eecfa5ae39eca0e9b5265adc399bf7f4..b9f1ab47e1e41d8cff6507f35bfcc85b53242c05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden). 
  * All rights reserved. 
  *
@@ -33,7 +33,7 @@
 
 #include "hdb_locl.h"
 
-RCSID("$Id: db.c,v 1.32 2005/06/23 13:34:17 lha Exp $");
+RCSID("$Id: db.c,v 1.33 2005/11/28 23:30:51 lha Exp $");
 
 #if HAVE_DB1
 
@@ -270,7 +270,7 @@ krb5_error_code
 hdb_db_create(krb5_context context, HDB **db, 
              const char *filename)
 {
-    *db = malloc(sizeof(**db));
+    *db = calloc(1, sizeof(**db));
     if (*db == NULL) {
        krb5_set_error_string(context, "malloc: out of memory");
        return ENOMEM;
index 7557b46bff6bb1280cafca35a857d3c375c14dfc..f7e0c54b7cffad533f80e4f92d981d814ffd0266 100644 (file)
@@ -120,7 +120,9 @@ hdb_free_entry (
        hdb_entry */*ent*/);
 
 void
-hdb_free_entry_ex(krb5_context context, hdb_entry_ex *ent);
+hdb_free_entry_ex (
+       krb5_context /*context*/,
+       hdb_entry_ex */*ent*/);
 
 void
 hdb_free_key (Key */*key*/);
index 588ff80728ef3d899b875a4ca36d4d61e0b576a6..dfd5bfa8f131be2e3ea772336d07314ee6958d8b 100644 (file)
@@ -339,6 +339,8 @@ hdb_ndbm_create(krb5_context context, HDB **db,
        return ENOMEM;
     }
 
+    memset(*db, '\0', sizeof(**db));
+
     (*db)->hdb_db = NULL;
     (*db)->hdb_name = strdup(filename);
     if ((*db)->hdb_name == NULL) {
index ec956409a7aca2fb0fe2f8cfdd4e5d01b1312d04..25dc2cb8c0d8df089f49555a006631a9427a199c 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: cache.c,v 1.73 2005/10/19 17:30:40 lha Exp $");
+RCSID("$Id: cache.c,v 1.74 2005/11/01 09:36:41 lha Exp $");
 
 /*
  * Add a new ccache type with operations `ops', overwriting any
@@ -222,6 +222,41 @@ krb5_cc_get_type(krb5_context context,
     return id->ops->prefix;
 }
 
+/*
+ * Return the complete resolvable name the ccache `id' in `str´.
+ * `str` should be freed with free(3).
+ * Returns 0 or an error (and then *str is set to NULL).
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_full_name(krb5_context context,
+                     krb5_ccache id,
+                     char **str)
+{
+    const char *type, *name;
+
+    *str = NULL;
+
+    type = krb5_cc_get_type(context, id);
+    if (type == NULL) {
+       krb5_set_error_string(context, "cache have no name of type");
+       return KRB5_CC_UNKNOWN_TYPE;
+    }
+
+    name = krb5_cc_get_name(context, id);
+    if (name == NULL) {
+       krb5_set_error_string(context, "cache of type %s have no name", type);
+       return KRB5_CC_BADNAME;
+    }
+    
+    if (asprintf(str, "%s:%s", type, name) == -1) {
+       krb5_set_error_string(context, "malloc - out of memory");
+       *str = NULL;
+       return ENOMEM;
+    }
+    return 0;
+}
+
 /*
  * Return krb5_cc_ops of a the ccache `id'.
  */
index 7bc8942f667750e34dbe04cbfeb11a1964e029b4..be5c1db47d1536a4befdbb9c12e5df67e184cdf0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden). 
  * All rights reserved. 
  *
@@ -33,7 +33,7 @@
 
 #include <krb5_locl.h>
 
-RCSID("$Id: get_for_creds.c,v 1.45 2005/06/15 02:44:36 lha Exp $");
+RCSID("$Id: get_for_creds.c,v 1.46 2005/11/28 20:43:02 lha Exp $");
 
 static krb5_error_code
 add_addrs(krb5_context context,
@@ -385,17 +385,13 @@ krb5_get_forwarded_creds (krb5_context        context,
        cred.enc_part.cipher.data = buf;
        cred.enc_part.cipher.length = buf_size;
     } else {
-           /* 
-            * RFC4120 claims we should use the session key, but Heimdal
-            * before 0.8 used the remote subkey if it was send in the
-            * auth_context.  
-            *
-            * Lorikeet-Heimdal is interested in windows compatiblity
-            * more than Heimdal compatability, so we must choose the
-            * session key, and break forwarding credentials to older
-            * Heimdal servers. 
-            */
-
+       /* 
+        * Here older versions then 0.7.2 of Heimdal used the local or
+        * remote subkey. That is wrong, the session key should be
+        * used. Heimdal 0.7.2 and newer have code to try both in the
+        * receiving end.
+        */
+       
        ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
        if (ret) {
            free(buf);
index 23f6685049dccaa6db4d0b031b0dbc0e1ee2b3ad..43fc21c1d1ba7572b615c48de100e7f5afc4b68e 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: keytab.c,v 1.62 2005/07/06 01:14:42 lha Exp $");
+RCSID("$Id: keytab.c,v 1.63 2005/11/25 21:46:40 lha Exp $");
 
 /*
  * Register a new keytab in `ops'
@@ -239,6 +239,40 @@ krb5_kt_get_name(krb5_context context,
     return (*keytab->get_name)(context, keytab, name, namesize);
 }
 
+/*
+ * Retrieve the full name of the keytab `keytab' and store the name in
+ * `str'. `str' needs to be freed by the caller using free(3).
+ * Returns 0 or an error. On error, *str is set to NULL.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_full_name(krb5_context context, 
+                     krb5_keytab keytab,
+                     char **str)
+{
+    char type[KRB5_KT_PREFIX_MAX_LEN];
+    char name[MAXPATHLEN];
+    krb5_error_code ret;
+             
+    *str = NULL;
+
+    ret = krb5_kt_get_type(context, keytab, type, sizeof(type));
+    if (ret)
+       return ret;
+
+    ret = krb5_kt_get_name(context, keytab, name, sizeof(name));
+    if (ret)
+       return ret;
+
+    if (asprintf(str, "%s:%s", type, name) == -1) {
+       krb5_set_error_string(context, "malloc - out of memory");
+       *str = NULL;
+       return ENOMEM;
+    }
+
+    return 0;
+}
+
 /*
  * Finish using the keytab in `id'.  All resources will be released,
  * even on errors.  Return 0 or an error.
index 2645c29fe7b0f94e6df2931c752abd7c792740b6..3602c89ec6f87cfcdfd73ad184bf9058c80f74c8 100644 (file)
@@ -77,6 +77,15 @@ _krb5_extract_ticket (
        krb5_decrypt_proc /*decrypt_proc*/,
        krb5_const_pointer /*decryptarg*/);
 
+int
+_krb5_find_type_in_ad (
+       krb5_context /*context*/,
+       int /*type*/,
+       krb5_data */*data*/,
+       krb5_boolean */*found*/,
+       krb5_keyblock */*sessionkey*/,
+       const AuthorizationData */*ad*/);
+
 void
 _krb5_free_krbhst_info (krb5_krbhst_info */*hi*/);
 
@@ -399,12 +408,4 @@ _krb5_xunlock (
        krb5_context /*context*/,
        int /*fd*/);
 
-int
-_krb5_find_type_in_ad(krb5_context context,
-                     int type, 
-                     krb5_data *data,
-                     int *found,
-                     krb5_keyblock *sessionkey,
-                     const AuthorizationData *ad);
-
 #endif /* __krb5_private_h__ */
index a46f8b8f8f418d459dcdc5f6b3900b6964adbf68..33e35ca60e45cf3ab6de2ef529cd0b91fd3bc161 100644 (file)
@@ -607,6 +607,12 @@ krb5_cc_gen_new (
        const krb5_cc_ops */*ops*/,
        krb5_ccache */*id*/);
 
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_full_name (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       char **/*str*/);
+
 const char* KRB5_LIB_FUNCTION
 krb5_cc_get_name (
        krb5_context /*context*/,
@@ -2185,6 +2191,12 @@ krb5_kt_get_entry (
        krb5_enctype /*enctype*/,
        krb5_keytab_entry */*entry*/);
 
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_full_name (
+       krb5_context /*context*/,
+       krb5_keytab /*keytab*/,
+       char **/*str*/);
+
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_kt_get_name (
        krb5_context /*context*/,
index 07f142267c012869484ffa459ef91cc8414f244c..d62adadf26990b219f5938d1187111f1461ed9db 100644 (file)
@@ -33,7 +33,7 @@
 
 #include <krb5_locl.h>
 
-RCSID("$Id: rd_cred.c,v 1.25 2005/09/23 03:37:57 lha Exp $");
+RCSID("$Id: rd_cred.c,v 1.26 2005/11/02 08:36:42 lha Exp $");
 
 static krb5_error_code
 compare_addrs(krb5_context context,
index 0eb109c2cfdc4aa1ff23fbe9972a5c9f891ca1c3..1530a9f6a8457cd89a14feffc3ebd673c6930cb1 100644 (file)
@@ -1094,6 +1094,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
        uint32_t acct_type = 0;
        const char *account_name;
        const char *netbios_name;
+       char *filter;
        
        r->out.error_string = NULL;
 
@@ -1212,6 +1213,13 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
                        talloc_free(tmp_mem);
                        return NT_STATUS_NO_MEMORY;
                }
+
+               rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain");
+               if (rtn == -1) {
+                       r->out.error_string = NULL;
+                       talloc_free(tmp_mem);
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain");
@@ -1341,6 +1349,33 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
+       if (r2->out.realm) {
+               struct cli_credentials *creds;
+               /* Make a credentials structure from it */
+               creds = cli_credentials_init(mem_ctx);
+               if (!creds) {
+                       r->out.error_string = NULL;
+                       talloc_free(tmp_mem);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               cli_credentials_set_conf(creds);
+               filter = talloc_asprintf(mem_ctx, "dn=%s", ldb_dn_linearize(mem_ctx, msg->dn));
+               status = cli_credentials_set_secrets(creds, NULL, filter);
+               if (!NT_STATUS_IS_OK(status)) {
+                       r->out.error_string = talloc_asprintf(mem_ctx, "Failed to read secrets for keytab update for %s\n", 
+                                                             filter);
+                       talloc_free(tmp_mem);
+                       return status;
+               } 
+               ret = cli_credentials_update_keytab(creds);
+               if (ret != 0) {
+                       r->out.error_string = talloc_asprintf(mem_ctx, "Failed to update keytab for %s\n", 
+                                                             filter);
+                       talloc_free(tmp_mem);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+
        /* move all out parameter to the callers TALLOC_CTX */
        r->out.error_string     = NULL;
        r->out.join_password    = r2->out.join_password;
index cc2ccf8c47455c9aa67519b01e635e6e89e1d8de..3cd554b957a8f5a20a4826b055bddf4bb27e3436 100644 (file)
@@ -240,6 +240,16 @@ int ejs_credentials_cmdline(int eid, int argc, struct MprVar **argv)
        return ejs_credentials_obj(obj, cmdline_credentials);
 }
 
+static int ejs_credentials_update_all_keytabs(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+       if (!NT_STATUS_IS_OK(cli_credentials_update_all_keytabs(mprMemCtx()))) {
+               mpr_Return(eid, mprCreateBoolVar(False));
+       } else {
+               mpr_Return(eid, mprCreateBoolVar(True));
+       }
+       return 0;
+}
+
 
 /*
   setup C functions that be called from ejs
@@ -247,4 +257,6 @@ int ejs_credentials_cmdline(int eid, int argc, struct MprVar **argv)
 void smb_setup_ejs_credentials(void)
 {
        ejsDefineCFunction(-1, "credentials_init", ejs_credentials_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+       ejsDefineCFunction(-1, "credentials_update_all_keytabs", ejs_credentials_update_all_keytabs, NULL, MPR_VAR_SCRIPT_HANDLE);
 }
+
index 513fb23cd94f2c19286da2d7df3675a172752f9b..0b6a31ae4f02a07ecd99cec7dcedbc973712808f 100644 (file)
@@ -302,6 +302,9 @@ function provision(subobj, message, blank, paths)
        setup_file("provision.zone", 
                   paths.dns, 
                   subobj);
+       message("Setting up keytabs\n");
+       var keytab_ok = credentials_update_all_keytabs();
+       assert(keytab_ok);
 }
 
 /*
index c573ad3b56ae9a70221f3cd98fbd9241e0b10735..43c3f69c9d8a4d80ea9e4022e68003c680064acc 100644 (file)
@@ -26,6 +26,7 @@ cn: Primary Domains
 dn: flatname=${DOMAIN},CN=Primary Domains
 objectClass: top
 objectClass: primaryDomain
+objectClass: kerberosSecret
 flatname: ${DOMAIN}
 realm: ${REALM}
 secret: ${MACHINEPASS}
@@ -35,10 +36,12 @@ whenCreated: ${LDAPTIME}
 whenChanged: ${LDAPTIME}
 msDS-KeyVersionNumber: 1
 objectSid: ${DOMAINSID}
+privateKeytab: secrets.keytab
 
 dn: samAccountName=krbtgt,flatname=${DOMAIN},CN=Principals
 objectClass: top
 objectClass: secret
+objectClass: kerberosSecret
 flatname: ${DOMAIN}
 realm: ${REALM}
 secret: ${KRBTGTPASS}
@@ -49,3 +52,4 @@ msDS-KeyVersionNumber: 1
 objectSid: ${DOMAINSID}
 servicePrincipalName: kadmin/changepw
 saltPrincipal: krbtgt@${REALM}
+privateKeytab: secrets.keytab