diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Projects/gssapi_krb5.pbexp Kerberos/KerberosFramework/Kerberos5/Projects/gssapi_krb5.pbexp --- Kerberos.orig/KerberosFramework/Kerberos5/Projects/gssapi_krb5.pbexp 2007-03-28 13:06:58.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Projects/gssapi_krb5.pbexp 2007-08-14 17:14:38.000000000 -0700 @@ -101,3 +101,9 @@ _gss_krb5_set_allowable_enctypes _gss_krb5_export_lucid_sec_context _gss_krb5_free_lucid_sec_context +# +# Apple authdata if relevant +# + _apple_gss_krb5_export_authdata_if_relevant_context + _apple_gss_krb5_free_authdata_if_relevant +# diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/accept_sec_context.c Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/accept_sec_context.c --- Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/accept_sec_context.c 2007-03-28 13:07:44.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/accept_sec_context.c 2007-08-14 17:14:38.000000000 -0700 @@ -640,6 +640,11 @@ goto fail; } + if ((code = krb5_copy_authdata(context, ticket->enc_part2->authorization_data, &ctx->apple_authdata_if_relevant))) { + major_status = GSS_S_FAILURE; + goto fail; + } + if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) { major_status = GSS_S_FAILURE; goto fail; diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/delete_sec_context.c Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/delete_sec_context.c --- Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/delete_sec_context.c 2007-03-28 13:07:44.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/delete_sec_context.c 2007-08-14 17:14:38.000000000 -0700 @@ -93,6 +93,9 @@ if (ctx->acceptor_subkey) krb5_free_keyblock(context, ctx->acceptor_subkey); + if (ctx->apple_authdata_if_relevant) + krb5_free_authdata(context, ctx->apple_authdata_if_relevant); + if (ctx->auth_context) { if (ctx->cred_rcache) (void)krb5_auth_con_setrcache(context, ctx->auth_context, NULL); diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapiP_krb5.h Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapiP_krb5.h --- Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapiP_krb5.h 2007-03-28 13:07:44.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapiP_krb5.h 2007-08-14 17:14:38.000000000 -0700 @@ -207,6 +207,7 @@ krb5_keyblock *acceptor_subkey; /* CFX only */ krb5_cksumtype acceptor_subkey_cksumtype; int cred_rcache; /* did we get rcache from creds? */ + krb5_authdata **apple_authdata_if_relevant; /* added by Apple for pac information */ } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; extern g_set kg_vdb; @@ -675,6 +676,11 @@ gss_ctx_id_t *context_handle, OM_uint32 version, void **kctx); +OM_uint32 KRB5_CALLCONV +apple_gss_krb5int_export_authdata_if_relevant_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx); extern k5_mutex_t kg_kdc_flag_mutex; diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_err_krb5.et Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_err_krb5.et --- Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_err_krb5.et 2007-03-28 13:07:44.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_err_krb5.et 2007-08-14 17:14:38.000000000 -0700 @@ -37,4 +37,5 @@ error_code KG_EMPTY_CCACHE, "Credential cache is empty" error_code KG_NO_CTYPES, "Acceptor and Initiator share no checksum types" error_code KG_LUCID_VERSION, "Requested lucid context version not supported" +error_code APPLE_KG_AUTHDATA_VERSION, "Requested authdata context version not supported" end diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_krb5.hin Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_krb5.hin --- Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_krb5.hin 2007-03-28 13:07:44.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/gssapi_krb5.hin 2007-08-14 17:14:38.000000000 -0700 @@ -152,6 +152,11 @@ } gss_krb5_lucid_context_version_t; +typedef struct apple_gss_krb5_authdata_if_relevant_key { +OM_uint32 type; /* key encryption type */ +OM_uint32 length; /* length of key data */ +void * data; /* actual key data */ +} apple_gss_krb5_authdata_if_relevant; /* Alias for Heimdal compat. */ @@ -256,6 +261,52 @@ OM_uint32 version, void **kctx); + + +/* + * Returns a non-opaque (lucid) version of the internal context + * information. + * + * Note that context_handle must not be used again by the caller + * after this call. The GSS implementation is free to release any + * resources associated with the original context. It is up to the + * GSS implementation whether it returns pointers to existing data, + * or copies of the data. The caller should treat the returned + * lucid context as read-only. + * + * The caller must call gss_krb5_free_lucid_context() to free + * the context and allocated resources when it is finished with it. + * + * 'version' is an integer indicating the highest version of lucid + * context understood by the caller. The highest version + * understood by both the caller and the GSS implementation must + * be returned. The caller can determine which version of the + * structure was actually returned by examining the version field + * of the returned structure. gss_krb5_lucid_context_version_t + * may be used as a mask to examine the returned structure version. + * + * If there are no common versions, an error should be returned. + * (XXX Need error definition(s)) + * + * + */ + +OM_uint32 KRB5_CALLCONV +apple_gss_krb5_export_authdata_if_relevant_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx); + +/* +* Frees the allocated storage associated with an +* exported struct apple_gss_krb5_authdata_if_relevant. +*/ +OM_uint32 KRB5_CALLCONV +apple_gss_krb5_free_authdata_if_relevant(OM_uint32 *minor_status, +void *kctx); + + + /* * Frees the allocated storage associated with an * exported struct gss_krb5_lucid_context. diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/krb5_gss_glue.c Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/krb5_gss_glue.c --- Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/krb5_gss_glue.c 2007-08-14 17:14:13.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/krb5_gss_glue.c 2007-08-14 17:14:38.000000000 -0700 @@ -1105,6 +1105,27 @@ return (major); } +/* XXX need to delete mechglue ctx too */ +OM_uint32 KRB5_CALLCONV +apple_gss_krb5_export_authdata_if_relevant_context( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx) +{ + gss_union_ctx_id_t uctx; + + uctx = (gss_union_ctx_id_t)*context_handle; + /* + if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type) && + !g_OID_equal(uctx->mech_type, &krb5_mechanism_old.mech_type)) + return GSS_S_BAD_MECH; + */ + return apple_gss_krb5int_export_authdata_if_relevant_context(minor_status, + &uctx->internal_ctx_id, + version, kctx); + } + OM_uint32 KRB5_CALLCONV gss_krb5_set_allowable_enctypes( OM_uint32 *minor_status, diff -uNr -x '\*.orig\' -x '\*.rej\' -x '\*~\' Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/lucid_context.c Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/lucid_context.c --- Kerberos.orig/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/lucid_context.c 2007-03-28 13:07:44.000000000 -0700 +++ Kerberos/KerberosFramework/Kerberos5/Sources/lib/gssapi/krb5/lucid_context.c 2007-08-14 17:42:19.000000000 -0700 @@ -54,6 +54,20 @@ unsigned int version, void **out_ptr); +static krb5_error_code +apple_make_external_authdata_if_relevant( + krb5_gss_ctx_id_rec * gctx, + unsigned int version, + void **out_ptr); + +static krb5_error_code +apple_copy_authdata_if_relevant_to_authdata_if_relevant_key( + krb5_authdata *k5data, + apple_gss_krb5_authdata_if_relevant **ldata); + +static void +apple_gss_free_authdata_if_relevant(apple_gss_krb5_authdata_if_relevant *key); + /* * Exported routines @@ -130,6 +144,115 @@ return(retval); } + +OM_uint32 KRB5_CALLCONV +apple_gss_krb5int_export_authdata_if_relevant_context( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx) +{ + krb5_error_code kret = 0; + OM_uint32 retval; + krb5_gss_ctx_id_t ctx; + void *lctx = NULL; + + /* Assume failure */ + retval = GSS_S_FAILURE; + *minor_status = 0; + + if (kctx) + *kctx = NULL; + else { + kret = EINVAL; + goto error_out; + } + + if (!kg_validate_ctx_id(*context_handle)) { + kret = (OM_uint32) G_VALIDATE_FAILED; + retval = GSS_S_NO_CONTEXT; + goto error_out; + } + + ctx = (krb5_gss_ctx_id_t) *context_handle; + if (kret) + goto error_out; + + /* Externalize a structure of the right version */ + switch (version) { + case 1: + kret = apple_make_external_authdata_if_relevant((krb5_pointer)ctx, + version, &lctx); + break; + default: + kret = (OM_uint32) APPLE_KG_AUTHDATA_VERSION; + break; + } + + if (kret) + goto error_out; + + /* Success! Record the context and return the buffer */ + if (! kg_save_lucidctx_id((void *)lctx)) { + kret = G_VALIDATE_FAILED; + goto error_out; + } + *kctx = lctx; + *minor_status = 0; + retval = GSS_S_COMPLETE; + return (retval); + +error_out: + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + if(kret == ENODATA) + retval = GSS_S_COMPLETE; + return(retval); +} + +/* + * Frees the storage associated with an + * exported lucid context structure. + */ +OM_uint32 KRB5_CALLCONV +apple_gss_krb5_free_authdata_if_relevant( + OM_uint32 *minor_status, + void *kctx) +{ + OM_uint32 retval; + krb5_error_code kret = 0; + + /* Assume failure */ + retval = GSS_S_FAILURE; + *minor_status = 0; + + if (!kctx) { + kret = EINVAL; + goto error_out; + } + + /* Verify pointer is valid lucid context */ + if (! kg_validate_lucidctx_id(kctx)) { + kret = G_VALIDATE_FAILED; + goto error_out; + } + + apple_gss_free_authdata_if_relevant((apple_gss_krb5_authdata_if_relevant*)kctx); + + /* Success! */ + (void)kg_delete_lucidctx_id(kctx); + *minor_status = 0; + retval = GSS_S_COMPLETE; + + return (retval); + +error_out: + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + return(retval); +} + + /* * Frees the storage associated with an * exported lucid context structure. @@ -253,6 +376,72 @@ } +static krb5_error_code +apple_make_external_authdata_if_relevant( + krb5_gss_ctx_id_rec * gctx, + unsigned int version, + void **out_ptr) +{ + apple_gss_krb5_authdata_if_relevant *lctx = NULL; + krb5_error_code retval; + + if((gctx->apple_authdata_if_relevant != NULL) && (*(gctx->apple_authdata_if_relevant) != NULL)) { + if((retval = apple_copy_authdata_if_relevant_to_authdata_if_relevant_key(*(gctx->apple_authdata_if_relevant),&lctx))) + goto error_out; + } + else { + retval = ENODATA; + goto error_out; /* XXX better error code? */ + } + /* Success! */ + *out_ptr = lctx; + + return 0; + +error_out: + if (lctx != NULL) { + apple_gss_free_authdata_if_relevant(lctx); + } + return retval; + +} + + +/* Copy the contents of a krb5_authdata to a apple_gss_krb5_authdata_if_relevant structure */ +static krb5_error_code +apple_copy_authdata_if_relevant_to_authdata_if_relevant_key( + krb5_authdata *k5data, + apple_gss_krb5_authdata_if_relevant **ldata) +{ + if(*ldata != NULL) { + apple_gss_free_authdata_if_relevant(*ldata); + *ldata = NULL; + } + + if (!k5data || !k5data->contents || k5data->length == 0) + return ENODATA; + + unsigned int bufsize = sizeof(apple_gss_krb5_authdata_if_relevant); + apple_gss_krb5_authdata_if_relevant *authdataptr = NULL; + + /* Allocate the structure */ + if ((authdataptr = xmalloc(bufsize)) == NULL) { + return ENOMEM; + } + memset(authdataptr, 0, sizeof(apple_gss_krb5_authdata_if_relevant)); + + if ((authdataptr->data = xmalloc(k5data->length)) == NULL) { + return ENOMEM; + } + memcpy(authdataptr->data,k5data->contents,k5data->length); + authdataptr->type = k5data->ad_type; + authdataptr->length = k5data->length; + + *ldata = authdataptr; + return 0; +} + + /* Copy the contents of a krb5_keyblock to a gss_krb5_lucid_key_t structure */ static krb5_error_code copy_keyblock_to_lucid_key( @@ -307,3 +496,17 @@ ctx = NULL; } } + +/* Free any storage associated with a authdata_if_relevant structure */ +static void +apple_gss_free_authdata_if_relevant(apple_gss_krb5_authdata_if_relevant *key) +{ + if (key!= NULL) { + if ((key->data!= NULL) && (key->length > 0)) { + memset(key->data, 0, key->length); + memset(key, 0, sizeof(apple_gss_krb5_authdata_if_relevant)); + } + if(key->data != NULL) + xfree(key->data); + } +}