s4:heimdal: import lorikeet-heimdal-200908050050 (commit 8714779fa7376fd9f7761587639e...
[samba.git] / source4 / heimdal / lib / krb5 / get_cred.c
index c19a5e4abc45d183bd4341be53bc26d2c175f1b6..10417f1a529f1bcb309a3cf4b995cc2787b46ca7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  * All rights reserved.
  *
@@ -33,8 +33,6 @@
 
 #include <krb5_locl.h>
 
-RCSID("$Id$");
-
 /*
  * Take the `body' and encode it into `padata' using the credentials
  * in `creds'.
@@ -99,7 +97,8 @@ set_auth_data (krb5_context context,
        ALLOC(req_body->enc_authorization_data, 1);
        if (req_body->enc_authorization_data == NULL) {
            free (buf);
-           krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
+           krb5_set_error_message(context, ENOMEM,
+                                  N_("malloc: out of memory", ""));
            return ENOMEM;
        }
        ret = krb5_crypto_init(context, key, 0, &crypto);
@@ -153,7 +152,8 @@ init_tgs_req (krb5_context context,
        ALLOC_SEQ(&t->req_body.etype, 1);
        if(t->req_body.etype.val == NULL) {
            ret = ENOMEM;
-           krb5_set_error_message(context, ret, "malloc: out of memory");
+           krb5_set_error_message(context, ret,
+                                  N_("malloc: out of memory", ""));
            goto fail;
        }
        t->req_body.etype.val[0] = in_creds->session.keytype;
@@ -173,7 +173,7 @@ init_tgs_req (krb5_context context,
     ALLOC(t->req_body.sname, 1);
     if (t->req_body.sname == NULL) {
        ret = ENOMEM;
-       krb5_set_error_message(context, ret, "malloc: out of memory");
+       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
        goto fail;
     }
 
@@ -189,7 +189,7 @@ init_tgs_req (krb5_context context,
     ALLOC(t->req_body.till, 1);
     if(t->req_body.till == NULL){
        ret = ENOMEM;
-       krb5_set_error_message(context, ret, "malloc: out of memory");
+       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
        goto fail;
     }
     *t->req_body.till = in_creds->times.endtime;
@@ -199,13 +199,15 @@ init_tgs_req (krb5_context context,
        ALLOC(t->req_body.additional_tickets, 1);
        if (t->req_body.additional_tickets == NULL) {
            ret = ENOMEM;
-           krb5_set_error_message(context, ret, "malloc: out of memory");
+           krb5_set_error_message(context, ret,
+                                  N_("malloc: out of memory", ""));
            goto fail;
        }
        ALLOC_SEQ(t->req_body.additional_tickets, 1);
        if (t->req_body.additional_tickets->val == NULL) {
            ret = ENOMEM;
-           krb5_set_error_message(context, ret, "malloc: out of memory");
+           krb5_set_error_message(context, ret,
+                                  N_("malloc: out of memory", ""));
            goto fail;
        }
        ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val);
@@ -215,13 +217,13 @@ init_tgs_req (krb5_context context,
     ALLOC(t->padata, 1);
     if (t->padata == NULL) {
        ret = ENOMEM;
-       krb5_set_error_message(context, ret, "malloc: out of memory");
+       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
        goto fail;
     }
     ALLOC_SEQ(t->padata, 1 + padata->len);
     if (t->padata->val == NULL) {
        ret = ENOMEM;
-       krb5_set_error_message(context, ret, "malloc: out of memory");
+       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
        goto fail;
     }
     {
@@ -229,7 +231,8 @@ init_tgs_req (krb5_context context,
        for (i = 0; i < padata->len; i++) {
            ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]);
            if (ret) {
-               krb5_set_error_message(context, ret, "malloc: out of memory");
+               krb5_set_error_message(context, ret,
+                                      N_("malloc: out of memory", ""));
                goto fail;
            }
        }
@@ -370,17 +373,18 @@ decrypt_tkt_with_subkey (krb5_context context,
     if (ret)
        return ret;
 
-    ret = krb5_decode_EncASRepPart(context,
-                                  data.data,
+    ret = decode_EncASRepPart(data.data,
+                             data.length,
+                             &dec_rep->enc_part,
+                             &size);
+    if (ret)
+       ret = decode_EncTGSRepPart(data.data,
                                   data.length,
                                   &dec_rep->enc_part,
                                   &size);
     if (ret)
-       ret = krb5_decode_EncTGSRepPart(context,
-                                       data.data,
-                                       data.length,
-                                       &dec_rep->enc_part,
-                                       &size);
+      krb5_set_error_message(context, ret, 
+                            N_("Failed to decode encpart in ticket", ""));
     krb5_data_free (&data);
     return ret;
 }
@@ -472,7 +476,7 @@ get_cred_kdc(krb5_context context,
        if (len != size)
            krb5_abortx(context, "internal asn1 error");
        
-       ret = krb5_padata_add(context, &padata, KRB5_PADATA_S4U2SELF, buf, len);
+       ret = krb5_padata_add(context, &padata, KRB5_PADATA_FOR_USER, buf, len);
        if (ret)
            goto out;
     }
@@ -556,12 +560,12 @@ get_cred_kdc(krb5_context context,
     } else if(krb5_rd_error(context, &resp, &error) == 0) {
        ret = krb5_error_from_rd_error(context, &error, in_creds);
        krb5_free_error_contents(context, &error);
-    } else if(resp.data && ((char*)resp.data)[0] == 4) {
+    } else if(resp.length > 0 && ((char*)resp.data)[0] == 4) {
        ret = KRB5KRB_AP_ERR_V4_REPLY;
-       krb5_clear_error_string(context);
+       krb5_clear_error_message(context);
     } else {
        ret = KRB5KRB_AP_ERR_MSG_TYPE;
-       krb5_clear_error_string(context);
+       krb5_clear_error_message(context);
     }
 
 out:
@@ -638,7 +642,8 @@ krb5_get_kdc_cred(krb5_context context,
 
     *out_creds = calloc(1, sizeof(**out_creds));
     if(*out_creds == NULL) {
-       krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
+       krb5_set_error_message(context, ENOMEM,
+                              N_("malloc: out of memory", ""));
        return ENOMEM;
     }
     ret = _krb5_get_krbtgt (context,
@@ -647,13 +652,16 @@ krb5_get_kdc_cred(krb5_context context,
                            &krbtgt);
     if(ret) {
        free(*out_creds);
+       *out_creds = NULL;
        return ret;
     }
     ret = get_cred_kdc(context, id, flags, addresses,
                       in_creds, krbtgt, NULL, NULL, *out_creds);
     krb5_free_creds (context, krbtgt);
-    if(ret)
+    if(ret) {
        free(*out_creds);
+       *out_creds = NULL;
+    }
     return ret;
 }
 
@@ -665,10 +673,11 @@ not_found(krb5_context context, krb5_const_principal p, krb5_error_code code)
 
     ret = krb5_unparse_name(context, p, &str);
     if(ret) {
-       krb5_clear_error_string(context);
+       krb5_clear_error_message(context);
        return code;
     }
-    krb5_set_error_message(context, code, "Matching credential (%s) not found", str);
+    krb5_set_error_message(context, code,
+                          N_("Matching credential (%s) not found", ""), str);
     free(str);
     return code;
 }
@@ -710,7 +719,8 @@ add_cred(krb5_context context, krb5_creds const *tkt, krb5_creds ***tgts)
     for(i = 0; tmp && tmp[i]; i++); /* XXX */
     tmp = realloc(tmp, (i+2)*sizeof(*tmp));
     if(tmp == NULL) {
-       krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
+       krb5_set_error_message(context, ENOMEM,
+                              N_("malloc: out of memory", ""));
        return ENOMEM;
     }
     *tgts = tmp;
@@ -747,6 +757,7 @@ get_cred_kdc_capath(krb5_context context,
     krb5_error_code ret;
     krb5_creds *tgt, tmp_creds;
     krb5_const_realm client_realm, server_realm, try_realm;
+    int ok_as_delegate = 1;
 
     *out_creds = NULL;
 
@@ -778,10 +789,14 @@ get_cred_kdc_capath(krb5_context context,
        ret = find_cred(context, ccache, tmp_creds.server,
                        *ret_tgts, &tgts);
        if(ret == 0){
+           if (try_realm != client_realm)
+               ok_as_delegate = tgts.flags.b.ok_as_delegate;
+
            *out_creds = calloc(1, sizeof(**out_creds));
            if(*out_creds == NULL) {
                ret = ENOMEM;
-               krb5_set_error_message(context, ret, "malloc: out of memory");
+               krb5_set_error_message(context, ret,
+                                      N_("malloc: out of memory", ""));
            } else {
                ret = get_cred_kdc_address(context, ccache, flags, NULL,
                                           in_creds, &tgts,
@@ -791,7 +806,8 @@ get_cred_kdc_capath(krb5_context context,
                if (ret) {
                    free (*out_creds);
                    *out_creds = NULL;
-               }
+               } else if (ok_as_delegate == 0)
+                   (*out_creds)->flags.b.ok_as_delegate = 0;
            }
            krb5_free_cred_contents(context, &tgts);
            krb5_free_principal(context, tmp_creds.server);
@@ -813,6 +829,15 @@ get_cred_kdc_capath(krb5_context context,
            krb5_free_principal(context, tmp_creds.client);
            return ret;
        }
+       /* 
+        * if either of the chain or the ok_as_delegate was stripped
+        * by the kdc, make sure we strip it too.
+        */
+       if (ok_as_delegate == 0 || tgt->flags.b.ok_as_delegate == 0) {
+           ok_as_delegate = 0;
+           tgt->flags.b.ok_as_delegate = 0;
+       }
+
        ret = add_cred(context, tgt, ret_tgts);
        if(ret) {
            krb5_free_principal(context, tmp_creds.server);
@@ -843,10 +868,10 @@ get_cred_kdc_capath(krb5_context context,
     *out_creds = calloc(1, sizeof(**out_creds));
     if(*out_creds == NULL) {
        ret = ENOMEM;
-       krb5_set_error_message(context, ret, "malloc: out of memory");
+       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
     } else {
        ret = get_cred_kdc_address (context, ccache, flags, NULL,
-                                   in_creds, tgt, impersonate_principal, 
+                                   in_creds, tgt, impersonate_principal,
                                    second_ticket, *out_creds);
        if (ret) {
            free (*out_creds);
@@ -871,6 +896,7 @@ get_cred_kdc_referral(krb5_context context,
     krb5_error_code ret;
     krb5_creds tgt, referral, ticket;
     int loop = 0;
+    int ok_as_delegate = 1;
 
     memset(&tgt, 0, sizeof(tgt));
     memset(&ticket, 0, sizeof(ticket));
@@ -943,7 +969,8 @@ get_cred_kdc_referral(krb5_context context,
            strcmp(ticket.server->name.name_string.val[0], KRB5_TGS_NAME) != 0)
        {
            krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US,
-                                  "Got back an non krbtgt ticket referrals");
+                                  N_("Got back an non krbtgt "
+                                     "ticket referrals", ""));
            krb5_free_cred_contents(context, &ticket);
            return KRB5KRB_AP_ERR_NOT_US;
        }
@@ -963,7 +990,8 @@ get_cred_kdc_referral(krb5_context context,
                                  *tickets))
            {
                krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
-                                      "Referral from %s loops back to realm %s",
+                                      N_("Referral from %s "
+                                         "loops back to realm %s", ""),
                                       tgt.server->realm,
                                       referral_realm);
                krb5_free_cred_contents(context, &ticket);
@@ -972,6 +1000,16 @@ get_cred_kdc_referral(krb5_context context,
            tickets++;
        }       
 
+       /* 
+        * if either of the chain or the ok_as_delegate was stripped
+        * by the kdc, make sure we strip it too.
+        */
+
+       if (ok_as_delegate == 0 || ticket.flags.b.ok_as_delegate == 0) {
+           ok_as_delegate = 0;
+           ticket.flags.b.ok_as_delegate = 0;
+       }
+
        ret = add_cred(context, &ticket, ret_tgts);
        if (ret) {
            krb5_free_cred_contents(context, &ticket);
@@ -979,7 +1017,7 @@ get_cred_kdc_referral(krb5_context context,
        }
 
        /* try realm in the referral */
-       ret = krb5_principal_set_realm(context, 
+       ret = krb5_principal_set_realm(context,
                                       referral.server,
                                       referral_realm);
        krb5_free_cred_contents(context, &tgt);
@@ -1003,15 +1041,15 @@ out:
  * codebase.
  */
 
-static krb5_error_code
-get_cred_kdc_any(krb5_context context,
-                krb5_kdc_flags flags,
-                krb5_ccache ccache,
-                krb5_creds *in_creds,
-                krb5_principal impersonate_principal,
-                Ticket *second_ticket,                 
-                krb5_creds **out_creds,
-                krb5_creds ***ret_tgts)
+krb5_error_code
+_krb5_get_cred_kdc_any(krb5_context context,
+                      krb5_kdc_flags flags,
+                      krb5_ccache ccache,
+                      krb5_creds *in_creds,
+                      krb5_principal impersonate_principal,
+                      Ticket *second_ticket,                   
+                      krb5_creds **out_creds,
+                      krb5_creds ***ret_tgts)
 {
     krb5_error_code ret;
 
@@ -1019,7 +1057,7 @@ get_cred_kdc_any(krb5_context context,
                                flags,
                                ccache,
                                in_creds,
-                               impersonate_principal, 
+                               impersonate_principal,
                                second_ticket,
                                out_creds,
                                ret_tgts);
@@ -1029,40 +1067,13 @@ get_cred_kdc_any(krb5_context context,
                                flags,
                                ccache,
                                in_creds,
-                               impersonate_principal, 
+                               impersonate_principal,
                                second_ticket,
                                out_creds,
                                ret_tgts);
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_cred_from_kdc_opt(krb5_context context,
-                          krb5_ccache ccache,
-                          krb5_creds *in_creds,
-                          krb5_creds **out_creds,
-                          krb5_creds ***ret_tgts,
-                          krb5_flags flags)
-{
-    krb5_kdc_flags f;
-    f.i = flags;
-    return get_cred_kdc_any(context, f, ccache,
-                           in_creds, NULL, NULL,
-                           out_creds, ret_tgts);
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_cred_from_kdc(krb5_context context,
-                      krb5_ccache ccache,
-                      krb5_creds *in_creds,
-                      krb5_creds **out_creds,
-                      krb5_creds ***ret_tgts)
-{
-    return krb5_get_cred_from_kdc_opt(context, ccache,
-                                     in_creds, out_creds, ret_tgts, 0);
-}
-
-
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_get_credentials_with_flags(krb5_context context,
                                krb5_flags options,
@@ -1079,7 +1090,8 @@ krb5_get_credentials_with_flags(krb5_context context,
     *out_creds = NULL;
     res_creds = calloc(1, sizeof(*res_creds));
     if (res_creds == NULL) {
-       krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
+       krb5_set_error_message(context, ENOMEM,
+                              N_("malloc: out of memory", ""));
        return ENOMEM;
     }
 
@@ -1130,8 +1142,8 @@ krb5_get_credentials_with_flags(krb5_context context,
        options |= KRB5_GC_NO_STORE;
 
     tgts = NULL;
-    ret = get_cred_kdc_any(context, flags, ccache,
-                          in_creds, NULL, NULL, out_creds, &tgts);
+    ret = _krb5_get_cred_kdc_any(context, flags, ccache,
+                                in_creds, NULL, NULL, out_creds, &tgts);
     for(i = 0; tgts && tgts[i]; i++) {
        krb5_cc_store_cred(context, ccache, tgts[i]);
        krb5_free_creds(context, tgts[i]);
@@ -1168,7 +1180,8 @@ krb5_get_creds_opt_alloc(krb5_context context, krb5_get_creds_opt *opt)
 {
     *opt = calloc(1, sizeof(**opt));
     if (*opt == NULL) {
-       krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
+       krb5_set_error_message(context, ENOMEM,
+                              N_("malloc: out of memory", ""));
        return ENOMEM;
     }
     return 0;
@@ -1179,6 +1192,10 @@ krb5_get_creds_opt_free(krb5_context context, krb5_get_creds_opt opt)
 {
     if (opt->self)
        krb5_free_principal(context, opt->self);
+    if (opt->ticket) {
+       free_Ticket(opt->ticket);
+       free(opt->ticket);
+    }
     memset(opt, 0, sizeof(*opt));
     free(opt);
 }
@@ -1232,14 +1249,16 @@ krb5_get_creds_opt_set_ticket(krb5_context context,
 
        opt->ticket = malloc(sizeof(*ticket));
        if (opt->ticket == NULL) {
-           krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
+           krb5_set_error_message(context, ENOMEM,
+                                  N_("malloc: out of memory", ""));
            return ENOMEM;
        }
        ret = copy_Ticket(ticket, opt->ticket);
        if (ret) {
            free(opt->ticket);
            opt->ticket = NULL;
-           krb5_set_error_message(context, ret, "malloc: out of memory");
+           krb5_set_error_message(context, ret,
+                                  N_("malloc: out of memory", ""));
            return ret;
        }
     }
@@ -1277,7 +1296,8 @@ krb5_get_creds(krb5_context context,
     res_creds = calloc(1, sizeof(*res_creds));
     if (res_creds == NULL) {
        krb5_free_principal(context, in_creds.client);
-       krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
+       krb5_set_error_message(context, ENOMEM,
+                              N_("malloc: out of memory", ""));
        return ENOMEM;
     }
 
@@ -1343,9 +1363,9 @@ krb5_get_creds(krb5_context context,
        flags.b.canonicalize = 1;
 
     tgts = NULL;
-    ret = get_cred_kdc_any(context, flags, ccache,
-                          &in_creds, opt->self, opt->ticket,
-                          out_creds, &tgts);
+    ret = _krb5_get_cred_kdc_any(context, flags, ccache,
+                                &in_creds, opt->self, opt->ticket,
+                                out_creds, &tgts);
     krb5_free_principal(context, in_creds.client);
     for(i = 0; tgts && tgts[i]; i++) {
        krb5_cc_store_cred(context, ccache, tgts[i]);