ticket: 6812
[idra/krb5.git] / src / lib / krb5 / krb / get_creds.c
index e28391790636a3e37b56a7a40d3689d9286a540f..ac28598603c1e4a48a4ce4abfa68f7a40e201ce4 100644 (file)
@@ -301,6 +301,8 @@ make_request_for_tgt(krb5_context context, krb5_tkt_creds_context ctx,
     if (code != 0)
         return code;
 
+    TRACE_TKT_CREDS_TGT_REQ(context, ctx->tgt_princ, ctx->cur_tgt->server);
+
     /* Construct input creds using ctx->tgt_in_creds as a container. */
     memset(&ctx->tgt_in_creds, 0, sizeof(ctx->tgt_in_creds));
     ctx->tgt_in_creds.client = ctx->client;
@@ -321,6 +323,8 @@ make_request_for_service(krb5_context context, krb5_tkt_creds_context ctx,
     krb5_error_code code;
     int extra_options;
 
+    TRACE_TKT_CREDS_SERVICE_REQ(context, ctx->server, referral);
+
     /* Include the caller-specified KDC options in service requests. */
     extra_options = ctx->req_kdcopt;
 
@@ -372,6 +376,7 @@ get_creds_from_tgs_reply(krb5_context context, krb5_tkt_creds_context ctx,
 
     /* Depending on our state, we may or may not be able to handle an error.
      * For now, store it in the context and return success. */
+    TRACE_TKT_CREDS_RESPONSE_CODE(context, code);
     ctx->reply_code = code;
     return 0;
 }
@@ -421,15 +426,15 @@ complete(krb5_context context, krb5_tkt_creds_context ctx)
 {
     krb5_error_code code;
 
+    TRACE_TKT_CREDS_COMPLETE(context, ctx->reply_creds->server);
+
     /* Note the authdata we asked for in the output creds. */
     ctx->reply_creds->authdata = ctx->authdata;
     ctx->authdata = NULL;
 
-    /* Cache the credential if desired. */
     if (!(ctx->req_options & KRB5_GC_NO_STORE)) {
-        code = krb5_cc_store_cred(context, ctx->ccache, ctx->reply_creds);
-        if (code != 0)
-            return code;
+        /* Try to cache the credential. */
+        (void) krb5_cc_store_cred(context, ctx->ccache, ctx->reply_creds);
     }
 
     /* If we were doing constrained delegation, make sure we got a forwardable
@@ -496,13 +501,16 @@ try_fallback_realm(krb5_context context, krb5_tkt_creds_context ctx)
         return code;
 
     /* Give up if the fallback realm isn't any different. */
-    if (data_eq_string(ctx->server->realm, hrealms[0]))
+    if (data_eq_string(ctx->server->realm, hrealms[0])) {
+        krb5_free_host_realm(context, hrealms);
         return ctx->reply_code;
+    }
 
     /* Rewrite server->realm to be the fallback realm. */
     krb5_free_data_contents(context, &ctx->server->realm);
     ctx->server->realm = string2data(hrealms[0]);
     free(hrealms);
+    TRACE_TKT_CREDS_FALLBACK(context, ctx->server->realm);
 
     /* Obtain a TGT for the new service realm. */
     ctx->getting_tgt_for = STATE_NON_REFERRAL;
@@ -540,17 +548,20 @@ step_referrals(krb5_context context, krb5_tkt_creds_context ctx)
                                ctx->server)) {
         /* We got the ticket we asked for... but we didn't necessarily ask for
          * it with the right enctypes.  Try a non-referral request if so. */
-        if (wrong_enctype(context, ctx->reply_creds->keyblock.enctype))
+        if (wrong_enctype(context, ctx->reply_creds->keyblock.enctype)) {
+            TRACE_TKT_CREDS_WRONG_ENCTYPE(context);
             return begin_non_referral(context, ctx);
+        }
 
-        /* Note the authdata we asked for in the output creds. */
         return complete(context, ctx);
     }
 
     /* Old versions of Active Directory can rewrite the server name instead of
      * returning a referral.  Try a non-referral query if we see this. */
-    if (!IS_TGS_PRINC(context, ctx->reply_creds->server))
+    if (!IS_TGS_PRINC(context, ctx->reply_creds->server)) {
+        TRACE_TKT_CREDS_NON_TGT(context, ctx->reply_creds->server);
         return begin_non_referral(context, ctx);
+    }
 
     if (ctx->referral_count == 1) {
         /* Cache the referral TGT only if it's from the local realm.
@@ -559,9 +570,7 @@ step_referrals(krb5_context context, krb5_tkt_creds_context ctx)
                                   &ctx->reply_creds->authdata);
         if (code != 0)
             return code;
-        code = krb5_cc_store_cred(context, ctx->ccache, ctx->reply_creds);
-        if (code != 0)
-            return code;
+        (void) krb5_cc_store_cred(context, ctx->ccache, ctx->reply_creds);
 
         /* The authdata in this TGT will be copied into subsequent TGTs or the
          * final credentials, so we don't need to request it again. */
@@ -585,6 +594,7 @@ step_referrals(krb5_context context, krb5_tkt_creds_context ctx)
     krb5_free_creds(context, ctx->cur_tgt);
     ctx->cur_tgt = ctx->reply_creds;
     ctx->reply_creds = NULL;
+    TRACE_TKT_CREDS_REFERRAL(context, ctx->cur_tgt->server);
 
     /* Rewrite the server realm to be the referral realm. */
     krb5_free_data_contents(context, &ctx->server->realm);
@@ -670,6 +680,7 @@ step_get_tgt_offpath(krb5_context context, krb5_tkt_creds_context ctx)
 
     if (data_eq(*tgt_realm, ctx->server->realm)) {
         /* We received the server realm TGT we asked for. */
+        TRACE_TKT_CREDS_TARGET_TGT_OFFPATH(context, ctx->cur_tgt->server);
         return end_get_tgt(context, ctx);
     } else if (ctx->offpath_count++ >= KRB5_REFERRAL_MAXHOPS) {
         /* Time to give up. */
@@ -731,14 +742,14 @@ get_cached_tgt(krb5_context context, krb5_tkt_creds_context ctx,
     *tgt = NULL;
 
     /* Construct the principal krbtgt/<realm>@<client realm>.  The realm
-     * won't matter unless we're getting the local TGT. */
+     * won't matter if we're getting a foreign TGT. */
     code = krb5int_tgtname(context, realm, &ctx->client->realm, &tgtname);
     if (code != 0)
         goto cleanup;
 
-    /* Match the TGT realm only if we're getting the local TGT. */
+    /* Don't match the TGT realm if we're getting a foreign TGT. */
     flags = KRB5_TC_SUPPORTED_KTYPES;
-    if (local_realm)
+    if (!local_realm)
         flags |= KRB5_TC_MATCH_SRV_NAMEONLY;
 
     /* Construct a matching cred for the ccache query. */
@@ -843,6 +854,7 @@ get_tgt_request(krb5_context context, krb5_tkt_creds_context ctx)
             return code;
         if (cached_tgt != NULL) {
             /* Advance the current realm and keep going. */
+            TRACE_TKT_CREDS_CACHED_INTERMEDIATE_TGT(context, cached_tgt);
             krb5_free_creds(context, ctx->cur_tgt);
             ctx->cur_tgt = cached_tgt;
             if (ctx->next_realm == ctx->last_realm)
@@ -872,6 +884,7 @@ step_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
              * ctx->cur_realm, so it's time to give up. */
             return ctx->reply_code;
         }
+        TRACE_TKT_CREDS_CLOSER_REALM(context, ctx->next_realm);
     } else {
         /* Verify that we got a TGT. */
         if (!IS_TGS_PRINC(context, ctx->reply_creds->server))
@@ -892,14 +905,14 @@ step_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
         path_realm = find_realm_in_path(context, ctx, tgt_realm);
         if (path_realm != NULL) {
             /* We got a realm on the expected path, so we can cache it. */
-            code = krb5_cc_store_cred(context, ctx->ccache, ctx->cur_tgt);
-            if (code != 0)
-                return code;
+            (void) krb5_cc_store_cred(context, ctx->ccache, ctx->cur_tgt);
             if (path_realm == ctx->last_realm) {
                 /* We received a TGT for the target realm. */
+                TRACE_TKT_CREDS_TARGET_TGT(context, ctx->cur_tgt->server);
                 return end_get_tgt(context, ctx);
             } else if (path_realm != NULL) {
                 /* We still have further to go; advance the traversal. */
+                TRACE_TKT_CREDS_ADVANCE(context, tgt_realm);
                 ctx->cur_realm = path_realm;
                 ctx->next_realm = ctx->last_realm;
             }
@@ -908,6 +921,7 @@ step_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
             return KRB5_KDCREP_MODIFIED;
         } else {
             /* We went off the path; start the off-path chase. */
+            TRACE_TKT_CREDS_OFFPATH(context, tgt_realm);
             return begin_get_tgt_offpath(context, ctx);
         }
     }
@@ -936,16 +950,12 @@ begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
     if (code != 0)
         return code;
     if (cached_tgt != NULL) {
+        TRACE_TKT_CREDS_CACHED_SERVICE_TGT(context, cached_tgt);
         krb5_free_creds(context, ctx->cur_tgt);
         ctx->cur_tgt = cached_tgt;
         return end_get_tgt(context, ctx);
     }
 
-    /* Initialize the realm path. */
-    code = init_realm_path(context, ctx);
-    if (code != 0)
-        return code;
-
     /* Start with the local tgt. */
     krb5_free_creds(context, ctx->cur_tgt);
     ctx->cur_tgt = NULL;
@@ -954,6 +964,12 @@ begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
         return code;
     if (ctx->cur_tgt == NULL)
         return ctx->cache_code;
+    TRACE_TKT_CREDS_LOCAL_TGT(context, ctx->cur_tgt);
+
+    /* Initialize the realm path. */
+    code = init_realm_path(context, ctx);
+    if (code != 0)
+        return code;
 
     /* Empty out the realms-seen list for loop checking. */
     krb5int_free_data_list(context, ctx->realms_seen);
@@ -1022,6 +1038,7 @@ begin(krb5_context context, krb5_tkt_creds_context ctx)
         krb5_free_data_contents(context, &ctx->server->realm);
         code = krb5int_copy_data_contents(context, &ctx->client->realm,
                                           &ctx->server->realm);
+        TRACE_TKT_CREDS_REFERRAL_REALM(context, ctx->server);
         if (code != 0)
             return code;
     }
@@ -1041,6 +1058,7 @@ krb5_tkt_creds_init(krb5_context context, krb5_ccache ccache,
     krb5_error_code code;
     krb5_tkt_creds_context ctx = NULL;
 
+    TRACE_TKT_CREDS(context, in_creds, ccache);
     ctx = k5alloc(sizeof(*ctx), &code);
     if (ctx == NULL)
         goto cleanup;
@@ -1138,9 +1156,10 @@ krb5_tkt_creds_get(krb5_context context, krb5_tkt_creds_context ctx)
         /* Get the next request and realm.  Turn on TCP if necessary. */
         code = krb5_tkt_creds_step(context, ctx, &reply, &request, &realm,
                                    &flags);
-        if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !tcp_only)
+        if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !tcp_only) {
+            TRACE_TKT_CREDS_RETRY_TCP(context);
             tcp_only = 1;
-        else if (code != 0 || !(flags & KRB5_TKT_CREDS_STEP_FLAG_CONTINUE))
+        else if (code != 0 || !(flags & KRB5_TKT_CREDS_STEP_FLAG_CONTINUE))
             break;
         krb5_free_data_contents(context, &reply);