krb5_wrap: let smb_krb5_kinit_s4u2_ccache() work if store_creds.client and server...
[samba.git] / lib / krb5_wrap / krb5_samba.c
index 28884d9044dbc1eeb310f62720fb1977d6a97c84..bb0b5dfa6209c40751aa46a94e9a40646b22d167 100644 (file)
@@ -1023,8 +1023,8 @@ krb5_error_code smb_krb5_kt_open_relative(krb5_context context,
                        goto out;
                }
 
-               if ((strncmp(keytab_name_req, "WRFILE:/", 8) == 0) ||
-                   (strncmp(keytab_name_req, "FILE:/", 6) == 0)) {
+               if ((strncmp(keytab_name_req, "WRFILE:", 7) == 0) ||
+                   (strncmp(keytab_name_req, "FILE:", 5) == 0)) {
                        tmp = keytab_name_req;
                        goto resolve;
                }
@@ -1130,12 +1130,29 @@ krb5_error_code smb_krb5_kt_open(krb5_context context,
                                 bool write_access,
                                 krb5_keytab *keytab)
 {
-       if (keytab_name_req != NULL) {
-               if (keytab_name_req[0] != '/') {
-                       return KRB5_KT_BADNAME;
-               }
+       int cmp;
+
+       if (keytab_name_req == NULL) {
+               return KRB5_KT_BADNAME;
+       }
+
+       if (keytab_name_req[0] == '/') {
+               goto open_keytab;
+       }
+
+       cmp = strncmp(keytab_name_req, "FILE:/", 6);
+       if (cmp == 0) {
+               goto open_keytab;
        }
 
+       cmp = strncmp(keytab_name_req, "WRFILE:/", 8);
+       if (cmp == 0) {
+               goto open_keytab;
+       }
+
+       return KRB5_KT_BADNAME;
+
+open_keytab:
        return smb_krb5_kt_open_relative(context,
                                         keytab_name_req,
                                         write_access,
@@ -1212,17 +1229,13 @@ krb5_error_code smb_krb5_kt_seek_and_delete_old_entries(krb5_context context,
 {
        krb5_error_code ret;
        krb5_kt_cursor cursor;
-       krb5_kt_cursor zero_csr;
        krb5_keytab_entry kt_entry;
-       krb5_keytab_entry zero_kt_entry;
        char *ktprinc = NULL;
        krb5_kvno old_kvno = kvno - 1;
        TALLOC_CTX *tmp_ctx;
 
        ZERO_STRUCT(cursor);
-       ZERO_STRUCT(zero_csr);
        ZERO_STRUCT(kt_entry);
-       ZERO_STRUCT(zero_kt_entry);
 
        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
        if (ret == KRB5_KT_END || ret == ENOENT ) {
@@ -1357,10 +1370,10 @@ krb5_error_code smb_krb5_kt_seek_and_delete_old_entries(krb5_context context,
 
 out:
        talloc_free(tmp_ctx);
-       if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
+       if (!all_zero((uint8_t *)&kt_entry, sizeof(kt_entry))) {
                smb_krb5_kt_free_entry(context, &kt_entry);
        }
-       if (memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) {
+       if (!all_zero((uint8_t *)&cursor, sizeof(cursor))) {
                krb5_kt_end_seq_get(context, keytab, &cursor);
        }
        return ret;
@@ -1929,6 +1942,7 @@ krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx,
        krb5_principal target_princ;
        krb5_ccache tmp_cc;
        const char *self_realm;
+       const char *client_realm = NULL;
        krb5_principal blacklist_principal = NULL;
        krb5_principal whitelist_principal = NULL;
 
@@ -2260,6 +2274,29 @@ krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx,
                return code;
        }
 
+       client_realm = krb5_principal_get_realm(ctx, store_creds.client);
+       if (client_realm != NULL) {
+               /*
+                * Because the CANON flag doesn't have any impact
+                * on the impersonate_principal => store_creds.client
+                * realm mapping. We need to store the credentials twice,
+                * once with the returned realm and once with the
+                * realm of impersonate_principal.
+                */
+               code = krb5_principal_set_realm(ctx, store_creds.server,
+                                               client_realm);
+               if (code != 0) {
+                       krb5_free_cred_contents(ctx, &store_creds);
+                       return code;
+               }
+
+               code = krb5_cc_store_cred(ctx, store_cc, &store_creds);
+               if (code != 0) {
+                       krb5_free_cred_contents(ctx, &store_creds);
+                       return code;
+               }
+       }
+
        if (expire_time) {
                *expire_time = (time_t) store_creds.times.endtime;
        }
@@ -2882,6 +2919,18 @@ krb5_error_code smb_krb5_cc_copy_creds(krb5_context context,
 #ifdef HAVE_KRB5_CC_COPY_CACHE /* Heimdal */
        return krb5_cc_copy_cache(context, incc, outcc);
 #elif defined(HAVE_KRB5_CC_COPY_CREDS)
+       krb5_error_code ret;
+       krb5_principal princ = NULL;
+
+       ret = krb5_cc_get_principal(context, incc, &princ);
+       if (ret != 0) {
+               return ret;
+       }
+       ret = krb5_cc_initialize(context, outcc, princ);
+       krb5_free_principal(context, princ);
+       if (ret != 0) {
+               return ret;
+       }
        return krb5_cc_copy_creds(context, incc, outcc);
 #else
 #error UNKNOWN_KRB5_CC_COPY_CACHE_OR_CREDS_FUNCTION