s4:heimdal Create a new PAC when impersonating a user with S4U2Self
authorAndrew Bartlett <abartlet@samba.org>
Fri, 24 Sep 2010 23:46:38 +0000 (09:46 +1000)
committerLove Hornquist Astrand <lha@h5l.org>
Sun, 26 Sep 2010 22:15:18 +0000 (15:15 -0700)
If we don't do this, the PAC is given for the machine accout, not the
account being impersonated.

Andrew Bartlett

Signed-off-by: Love Hornquist Astrand <lha@h5l.org>
kdc/krb5tgs.c

index 30936e075392dd86627b5557461f19d46d4e38ce..877f7dc250d23d6f2004f9a9d6a3c311b73f2fd1 100644 (file)
@@ -1454,8 +1454,8 @@ tgs_build_reply(krb5_context context,
     krb5_principal cp = NULL, sp = NULL;
     krb5_principal client_principal = NULL;
     char *spn = NULL, *cpn = NULL;
-    hdb_entry_ex *server = NULL, *client = NULL;
-    HDB *clientdb;
+    hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
+    HDB *clientdb, *s4u2self_impersonated_clientdb;
     krb5_realm ref_realm = NULL;
     EncTicketPart *tgt = &ticket->ticket;
     krb5_principals spp = NULL;
@@ -1819,6 +1819,48 @@ server_lookup:
            if (ret)
                goto out;
 
+           /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */
+           if(rspac.data) {
+               krb5_pac p = NULL;
+               krb5_data_free(&rspac);
+               ret = _kdc_db_fetch(context, config, client_principal, HDB_F_GET_CLIENT | HDB_F_CANON,
+                                   &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client);
+               if (ret) {
+                   const char *msg;
+
+                   /*
+                    * If the client belongs to the same realm as our krbtgt, it
+                    * should exist in the local database.
+                    *
+                    */
+
+                   if (ret == HDB_ERR_NOENTRY)
+                       ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+                   msg = krb5_get_error_message(context, ret);
+                   kdc_log(context, config, 1, "S2U4Self principal to impersonate %s not found in database: %s", cpn, msg);
+                   krb5_free_error_message(context, msg);
+                   goto out;
+               }
+               ret = _kdc_pac_generate(context, s4u2self_impersonated_client, &p);
+               if (ret) {
+                   kdc_log(context, config, 0, "PAC generation failed for -- %s",
+                           selfcpn);
+                   goto out;
+               }
+               if (p != NULL) {
+                   ret = _krb5_pac_sign(context, p, ticket->ticket.authtime,
+                                        s4u2self_impersonated_client->entry.principal,
+                                        ekey, &tkey->key,
+                                        &rspac);
+                   krb5_pac_free(context, p);
+                   if (ret) {
+                       kdc_log(context, config, 0, "PAC signing failed for -- %s",
+                               selfcpn);
+                       goto out;
+                   }
+               }
+           }
+
            /*
             * Check that service doing the impersonating is
             * requesting a ticket to it-self.
@@ -2056,6 +2098,8 @@ out:
        _kdc_free_ent(context, server);
     if(client)
        _kdc_free_ent(context, client);
+    if(s4u2self_impersonated_client)
+       _kdc_free_ent(context, s4u2self_impersonated_client);
 
     if (client_principal && client_principal != cp)
        krb5_free_principal(context, client_principal);