s4:heimdal Create a new PAC when impersonating a user with S4U2Self
authorAndrew Bartlett <abartlet@samba.org>
Mon, 29 Mar 2010 07:13:46 +0000 (18:13 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 10 Apr 2010 11:40:59 +0000 (21:40 +1000)
If we don't do this, the PAC is given for the machine accout, not the
account being impersonated.

Andrew Bartlett

source4/heimdal/kdc/krb5tgs.c

index ca650645ded4e4f48e910ee98ce6f734e7b848fa..dd14ae6513c2d0ad91c4f81d37a8fecba029476c 100644 (file)
@@ -542,9 +542,7 @@ check_s4u2self(krb5_context context,
               hdb_entry_ex *client,
               krb5_const_principal server)
 {
-    const HDB_Ext_Constrained_delegation_acl *acl;
     krb5_error_code ret;
-    int i;
 
     /* if client does a s4u2self to itself, that ok */
     if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
@@ -1446,8 +1444,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;
@@ -1811,6 +1809,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.
@@ -2048,6 +2088,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);