diff options
Diffstat (limited to 'third_party/heimdal/lib/gssapi')
296 files changed, 59508 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/gssapi/ChangeLog b/third_party/heimdal/lib/gssapi/ChangeLog new file mode 100644 index 0000000..5c25d69 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ChangeLog @@ -0,0 +1,2970 @@ +2008-08-14 Love Hornquist Astrand <lha@10a140laptop.local> + + * krb5/accept_sec_context.c: If there is a initiator subkey, copy + that to acceptor subkey to match windows behavior. From Metze. + +2008-08-02 Love Hörnquist Ã…strand <lha@h5l.org> + + * ntlm/init_sec_context.c: Catch error + + * krb5/inquire_sec_context_by_oid.c: Catch store failure. + + * mech/gss_canonicalize_name.c: Not init m, return never + used (overwritten later). + +2008-07-25 Love Hörnquist Ã…strand <lha@kth.se> + + * ntlm/init_sec_context.c: Use krb5_cc_get_config. + +2008-07-25 Love Hörnquist Ã…strand <lha@kth.se> + + * krb5/init_sec_context.c: Match the orignal patch I got from + metze, seems that DCE-STYLE is even more weirer then what I though + when I merged the patch. + +2008-06-02 Love Hörnquist Ã…strand <lha@kth.se> + + * krb5/init_sec_context.c: Don't add asn1 wrapping to token when + using DCE_STYLE. Patch from Stefan Metzmacher. + +2008-05-27 Love Hörnquist Ã…strand <lha@kth.se> + + * ntlm/init_sec_context.c: use krb5_get_error_message + +2008-05-05 Love Hörnquist Ã…strand <lha@kth.se> + + * spnego/spnego_locl.h: Add back "mech/utils.h", its needed for + oid/buffer functions. + +2008-05-02 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego: Changes from doug barton to make spnego indepedant of + the heimdal version of the plugin system. + +2008-04-27 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5: use DES_set_key_unchecked() + +2008-04-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * add __declspec() for windows. + +2008-04-15 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/import_sec_context.c: Use tmp to read ac->flags value to + avoid warning. + +2008-04-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_mech_switch.c: Use unsigned where appropriate. + +2008-03-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Add test for gsskrb5_register_acceptor_identity. + +2008-03-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/init_sec_context.c (init_auth): use right variable to + detect if we want to free or not. + +2008-02-26 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: add missing \ + + * Makefile.am: reshuffle depenencies + + * Add flag to krb5 to not add GSS-API INT|CONF to the negotiation + +2008-02-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * make the SPNEGO mech store the error itself instead, works for + everything except other stackable mechs + +2008-02-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/init_sec_context.c (spnego_reply): if the reply token was + of length 0, make it the same as no token. Pointed out by Zeqing + Xia. + + * krb5/acquire_cred.c (acquire_initiator_cred): handle the + credential cache better, use destroy/close when appriate and for + all cases. Thanks to Michael Allen for point out the memory-leak + that I also fixed. + +2008-02-03 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/accept_sec_context.c: Make error reporting somewhat more + correct for SPNEGO. + +2008-01-27 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_common.c: Improve the error message. + +2008-01-24 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/accept_sec_context.c: Avoid free-ing type1 message before + its allocated. + +2008-01-13 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_ntlm.c: Test source name (and make the acceptor in ntlm gss + mech useful). + +2007-12-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/init_sec_context.c: Don't confuse target name and source + name, make regressiont tests pass again. + +2007-12-29 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm: clean up name handling + +2007-12-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/init_sec_context.c: Use credential if it was passed in. + + * ntlm/acquire_cred.c: Check if there is initial creds with + _gss_ntlm_get_user_cred(). + + * ntlm/init_sec_context.c: Add _gss_ntlm_get_user_info() that + return the user info so it can be used by external modules. + + * ntlm/inquire_cred.c: use the right error code. + + * ntlm/inquire_cred.c: Return GSS_C_NO_CREDENTIAL if there is no + credential, ntlm have (not yet) a default credential. + + * mech/gss_release_oid_set.c: Avoid trying to deref NULL, from + Phil Fisher. + +2007-12-03 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_acquire_cred.c: Always try to fetch cred (even with + GSS_C_NO_NAME). + +2007-08-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_krb5.c: Readd gss_krb5_get_tkt_flags. + +2007-08-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/compat.c (_gss_spnego_internal_delete_sec_context): + release ctx->target_name too From Rafal Malinowski. + +2007-07-26 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_mech_switch.c: Don't try to do dlopen if system doesn't + have dlopen. From Rune of Chalmers. + +2007-07-10 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_duplicate_name.c: New signature of _gss_find_mn. + + * mech/gss_init_sec_context.c: New signature of _gss_find_mn. + + * mech/gss_acquire_cred.c: New signature of _gss_find_mn. + + * mech/name.h: New signature of _gss_find_mn. + + * mech/gss_canonicalize_name.c: New signature of _gss_find_mn. + + * mech/gss_compare_name.c: New signature of _gss_find_mn. + + * mech/gss_add_cred.c: New signature of _gss_find_mn. + + * mech/gss_names.c (_gss_find_mn): Return an error code for + caller. + + * spnego/accept_sec_context.c: remove checks that are done by the + previous function. + + * Makefile.am: New library version. + +2007-07-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_oid_to_str.c: Refuse to print GSS_C_NULL_OID, from + Rafal Malinowski. + + * spnego/spnego.asn1: Indent and make NegTokenInit and + NegTokenResp extendable. + +2007-06-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/inquire_cred.c: Implement _gss_ntlm_inquire_cred. + + * mech/gss_display_status.c: Provide message for GSS_S_COMPLETE. + + * mech/context.c: If the canned string is "", its no use to the + user, make it fall back to the default error string. + +2007-06-20 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_display_name.c (gss_display_name): no name -> + fail. From Rafal Malinswski. + + * spnego/accept_sec_context.c: Wrap name in a spnego_name instead + of just a copy of the underlaying object. From Rafal Malinswski. + + * spnego/accept_sec_context.c: Handle underlaying mech not + returning mn. + + * mech/gss_accept_sec_context.c: Handle underlaying mech not + returning mn. + + * spnego/accept_sec_context.c: Make sure src_name is always set to + GSS_C_NO_NAME when returning. + + * krb5/acquire_cred.c (acquire_acceptor_cred): don't claim + everything is well on failure. From Phil Fisher. + + * mech/gss_duplicate_name.c: catch error (and ignore it) + + * ntlm/init_sec_context.c: Use heim_ntlm_calculate_ntlm2_sess. + + * mech/gss_accept_sec_context.c: Only wrap the delegated cred if + we got a delegated mech cred. From Rafal Malinowski. + + * spnego/accept_sec_context.c: Only wrap the delegated cred if we + are going to return it to the consumer. From Rafal Malinowski. + + * spnego/accept_sec_context.c: Fixed memory leak pointed out by + Rafal Malinowski, also while here moved to use NegotiationToken + for decoding. + +2007-06-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/prf.c (_gsskrb5_pseudo_random): add missing break. + + * krb5/release_name.c: Set *minor_status unconditionallty, its + done later anyway. + + * spnego/accept_sec_context.c: Init get_mic to 0. + + * mech/gss_set_cred_option.c: Free memory in failure case, found + by beam. + + * mech/gss_inquire_context.c: Handle mech_type being NULL. + + * mech/gss_inquire_cred_by_mech.c: Handle cred_name being NULL. + + * mech/gss_krb5.c: Free memory in error case, found by beam. + +2007-06-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/inquire_context.c: Use ctx->gssflags for flags. + + * krb5/display_name.c: Use KRB5_PRINCIPAL_UNPARSE_DISPLAY, this is + not ment for machine consumption. + +2007-06-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/digest.c (kdc_alloc): free memory on failure, pointed out + by Rafal Malinowski. + + * ntlm/digest.c (kdc_destroy): free context when done, pointed out + by Rafal Malinowski. + + * spnego/context_stubs.c (_gss_spnego_display_name): if input_name + is null, fail. From Rafal Malinowski. + +2007-06-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/digest.c: Free memory when done. + +2007-06-02 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_ntlm.c: Test both with and without keyex. + + * ntlm/digest.c: If we didn't set session key, don't expect one + back. + + * test_ntlm.c: Set keyex flag and calculate session key. + +2007-05-31 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/accept_sec_context.c: Use the return value before is + overwritten by later calls. From Rafal Malinowski + + * krb5/release_cred.c: Give an minor_status argument to + gss_release_oid_set. From Rafal Malinowski + +2007-05-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/accept_sec_context.c: Catch errors and return the up the + stack. + + * test_kcred.c: more testing of lifetimes + +2007-05-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: Drop the gss oid_set function for the krb5 mech, + use the mech glue versions instead. Pointed out by Rafal + Malinowski. + + * krb5: Use gss oid_set functions from mechglue + +2007-05-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/accept_sec_context.c: Set session key only if we are + returned a session key. Found by David Love. + +2007-05-13 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/prf.c: switched MIN to min to make compile on solaris, + pointed out by David Love. + +2007-05-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/inquire_cred_by_mech.c: Fill in all of the variables if + they are passed in. Pointed out by Phil Fisher. + +2007-05-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/inquire_cred.c: Fix copy and paste error, bug spotted by + from Phil Fisher. + + * mech: dont keep track of gc_usage, just figure it out at + gss_inquire_cred() time + + * mech/gss_mech_switch.c (add_builtin): ok for + __gss_mech_initialize() to return NULL + + * test_kcred.c: more correct tests + + * spnego/cred_stubs.c (gss_inquire_cred*): wrap the name with a + spnego_name. + + * ntlm/inquire_cred.c: make ntlm gss_inquire_cred fail for now, + need to find default cred and friends. + + * krb5/inquire_cred_by_mech.c: reimplement + +2007-05-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/acquire_cred.c: drop unused variable. + + * ntlm/acquire_cred.c: Reimplement. + + * Makefile.am: add ntlm/digest.c + + * ntlm: split out backend ntlm server processing + +2007-04-24 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/delete_sec_context.c (_gss_ntlm_delete_sec_context): free + credcache when done + +2007-04-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/init_sec_context.c: ntlm-key credential entry is prefix with @ + + * ntlm/init_sec_context.c (get_user_ccache): pick up the ntlm + creds from the krb5 credential cache. + +2007-04-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/delete_sec_context.c: free the key stored in the context + + * ntlm/ntlm.h: switch password for a key + + * test_oid.c: Switch oid to one that is exported. + +2007-04-20 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/init_sec_context.c: move where hash is calculated to make + it easier to add ccache support. + + * Makefile.am: Add version-script.map to EXTRA_DIST. + +2007-04-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: Unconfuse newer versions of automake that doesn't + know the diffrence between depenences and setting variables. foo: + vs foo=. + + * test_ntlm.c: delete sec context when done. + + * version-script.map: export more symbols. + + * Makefile.am: add version script if ld supports it + + * version-script.map: add version script if ld supports it + +2007-04-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: test_acquire_cred need test_common.[ch] + + * test_acquire_cred.c: add more test options. + + * krb5/external.c: add GSS_KRB5_CCACHE_NAME_X + + * gssapi/gssapi_krb5.h: add GSS_KRB5_CCACHE_NAME_X + + * krb5/set_sec_context_option.c: refactor code, implement + GSS_KRB5_CCACHE_NAME_X + + * mech/gss_krb5.c: reimplement gss_krb5_ccache_name + +2007-04-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/cred_stubs.c: Need to import spnego name before we can + use it as a gss_name_t. + + * test_acquire_cred.c: use this test as part of the regression + suite. + + * mech/gss_acquire_cred.c (gss_acquire_cred): dont init + cred->gc_mc every time in the loop. + +2007-04-15 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: add test_common.h + +2007-02-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: Add link for + gsskrb5_register_acceptor_identity. + +2007-02-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/copy_ccache.c: Try to leak less memory in the failure case. + +2007-01-31 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_display_status.c: Use right printf formater. + + * test_*.[ch]: split out the error printing function and try to + return better errors + +2007-01-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/init_sec_context.c: revert 1.75: (init_auth): only turn on + GSS_C_CONF_FLAG and GSS_C_INT_FLAG if the caller requseted it. + + This is because Kerberos always support INT|CONF, matches behavior + with MS and MIT. The creates problems for the GSS-SPNEGO mech. + +2007-01-24 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/prf.c: constrain desired_output_len + + * krb5/external.c (krb5_mech): add _gsskrb5_pseudo_random + + * mech/gss_pseudo_random.c: Catch error from underlaying mech on + failure. + + * Makefile.am: Add krb5/prf.c + + * krb5/prf.c: gss_pseudo_random for krb5 + + * test_context.c: Checks for gss_pseudo_random. + + * krb5/gkrb5_err.et: add KG_INPUT_TOO_LONG + + * Makefile.am: Add mech/gss_pseudo_random.c + + * gssapi/gssapi.h: try to load pseudo_random + + * mech/gss_mech_switch.c: try to load pseudo_random + + * mech/gss_pseudo_random.c: Add gss_pseudo_random. + + * gssapi_mech.h: Add hook for gm_pseudo_random. + +2007-01-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Don't assume bufer from gss_display_status is + ok. + + * mech/gss_wrap_size_limit.c: Reset out variables. + + * mech/gss_wrap.c: Reset out variables. + + * mech/gss_verify_mic.c: Reset out variables. + + * mech/gss_utils.c: Reset out variables. + + * mech/gss_release_oid_set.c: Reset out variables. + + * mech/gss_release_cred.c: Reset out variables. + + * mech/gss_release_buffer.c: Reset variables. + + * mech/gss_oid_to_str.c: Reset out variables. + + * mech/gss_inquire_sec_context_by_oid.c: Fix reset out variables. + + * mech/gss_mech_switch.c: Reset out variables. + + * mech/gss_inquire_sec_context_by_oid.c: Reset out variables. + + * mech/gss_inquire_names_for_mech.c: Reset out variables. + + * mech/gss_inquire_cred_by_oid.c: Reset out variables. + + * mech/gss_inquire_cred_by_oid.c: Reset out variables. + + * mech/gss_inquire_cred_by_mech.c: Reset out variables. + + * mech/gss_inquire_cred.c: Reset out variables, fix memory leak. + + * mech/gss_inquire_context.c: Reset out variables. + + * mech/gss_init_sec_context.c: Zero out outbuffer on failure. + + * mech/gss_import_name.c: Reset out variables. + + * mech/gss_import_name.c: Reset out variables. + + * mech/gss_get_mic.c: Reset out variables. + + * mech/gss_export_name.c: Reset out variables. + + * mech/gss_encapsulate_token.c: Reset out variables. + + * mech/gss_duplicate_oid.c: Reset out variables. + + * mech/gss_duplicate_oid.c: Reset out variables. + + * mech/gss_duplicate_name.c: Reset out variables. + + * mech/gss_display_status.c: Reset out variables. + + * mech/gss_display_name.c: Reset out variables. + + * mech/gss_delete_sec_context.c: Reset out variables using propper + macros. + + * mech/gss_decapsulate_token.c: Reset out variables using propper + macros. + + * mech/gss_add_cred.c: Reset out variables. + + * mech/gss_acquire_cred.c: Reset out variables. + + * mech/gss_accept_sec_context.c: Reset out variables using propper + macros. + + * mech/gss_init_sec_context.c: Reset out variables. + + * mech/mech_locl.h (_mg_buffer_zero): new macro that zaps a + gss_buffer_t + +2007-01-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech: sprinkel _gss_mg_error + + * mech/gss_display_status.c (gss_display_status): use + _gss_mg_get_error to fetch the error from underlaying mech, if it + failes, let do the regular dance for GSS-CODE version and a + generic print-the-error code for MECH-CODE. + + * mech/gss_oid_to_str.c: Don't include the NUL in the length of + the string. + + * mech/context.h: Protoypes for _gss_mg_. + + * mech/context.c: Glue to catch the error from the lower gss-api + layer and save that for later so gss_display_status() can show the + error. + + * gss.c: Detect NTLM. + +2007-01-11 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_accept_sec_context.c: spelling + +2007-01-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: Include build (private) prototypes header files. + + * Makefile.am (ntlmsrc): add ntlm/ntlm-private.h + +2006-12-28 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/accept_sec_context.c: Pass signseal argument to + _gss_ntlm_set_key. + + * ntlm/init_sec_context.c: Pass signseal argument to + _gss_ntlm_set_key. + + * ntlm/crypto.c (_gss_ntlm_set_key): add signseal argument + + * test_ntlm.c: add ntlmv2 test + + * ntlm/ntlm.h: break out struct ntlmv2_key; + + * ntlm/crypto.c (_gss_ntlm_set_key): set ntlm v2 keys. + + * ntlm/accept_sec_context.c: Set dummy ntlmv2 keys and Check TI. + + * ntlm/ntlm.h: NTLMv2 keys. + + * ntlm/crypto.c: NTLMv2 sign and verify. + +2006-12-20 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/accept_sec_context.c: Don't send targetinfo now. + + * ntlm/init_sec_context.c: Build ntlmv2 answer buffer. + + * ntlm/init_sec_context.c: Leak less memory. + + * ntlm/init_sec_context.c: Announce that we support key exchange. + + * ntlm/init_sec_context.c: Add NTLM_NEG_NTLM2_SESSION, NTLMv2 + session security (disable because missing sign and seal). + +2006-12-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/accept_sec_context.c: split RC4 send and recv keystreams + + * ntlm/init_sec_context.c: split RC4 send and recv keystreams + + * ntlm/ntlm.h: split RC4 send and recv keystreams + + * ntlm/crypto.c: Implement SEAL. + + * ntlm/crypto.c: move gss_wrap/gss_unwrap here + + * test_context.c: request INT and CONF from the gss layer, test + get and verify MIC. + + * ntlm/ntlm.h: add crypto bits. + + * ntlm/accept_sec_context.c: Save session master key. + + * Makefile.am: Move get and verify mic to the same file (crypto.c) + since they share code. + + * ntlm/crypto.c: Move get and verify mic to the same file since + they share code, implement NTLM v1 and dummy signatures. + + * ntlm/init_sec_context.c: pass on GSS_C_CONF_FLAG and + GSS_C_INTEG_FLAG, save the session master key + + * spnego/accept_sec_context.c: try using gss_accept_sec_context() + on the opportunistic token instead of guessing the acceptor name + and do gss_acquire_cred, this make SPNEGO work like before. + +2006-12-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/init_sec_context.c: Calculate the NTLM version 1 "master" + key. + + * spnego/accept_sec_context.c: Resurect negHints for the acceptor + sends first packet. + + * Makefile.am: Add "windows" versions of the NegTokenInitWin and + friends. + + * test_context.c: add --wrapunwrap flag + + * spnego/compat.c: move _gss_spnego_indicate_mechtypelist() to + compat.c, use the sequence types of MechTypeList, make + add_mech_type() static. + + * spnego/accept_sec_context.c: move + _gss_spnego_indicate_mechtypelist() to compat.c + + * Makefile.am: Generate sequence code for MechTypeList + + * spnego: check that the generated acceptor mechlist is acceptable too + + * spnego/init_sec_context.c: Abstract out the initiator filter + function, it will be needed for the acceptor too. + + * spnego/accept_sec_context.c: Abstract out the initiator filter + function, it will be needed for the acceptor too. Remove negHints. + + * test_context.c: allow asserting return mech + + * ntlm/accept_sec_context.c: add _gss_ntlm_allocate_ctx + + * ntlm/acquire_cred.c: Check that the KDC seem to there and + answering us, we can't do better then that wen checking if we will + accept the credential. + + * ntlm/get_mic.c: return GSS_S_UNAVAILABLE + + * mech/utils.h: add _gss_free_oid, reverse of _gss_copy_oid + + * mech/gss_utils.c: add _gss_free_oid, reverse of _gss_copy_oid + + * spnego/spnego.asn1: Its very sad, but NegHints its are not part + of the NegTokenInit, this makes SPNEGO acceptor life a lot harder. + + * spnego: try harder to handle names better. handle missing + acceptor and initator creds better (ie dont propose/accept mech + that there are no credentials for) split NegTokenInit and + NegTokenResp in acceptor + +2006-12-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/import_name.c: Allocate the buffer from the right length. + +2006-12-15 Love Hörnquist Ã…strand <lha@it.su.se> + + * ntlm/init_sec_context.c (init_sec_context): Tell the other side + what domain we think we are talking to. + + * ntlm/delete_sec_context.c: free username and password + + * ntlm/release_name.c (_gss_ntlm_release_name): free name. + + * ntlm/import_name.c (_gss_ntlm_import_name): add support for + GSS_C_NT_HOSTBASED_SERVICE names + + * ntlm/ntlm.h: Add ntlm_name. + + * test_context.c: allow testing of ntlm. + + * gssapi_mech.h: add __gss_ntlm_initialize + + * ntlm/accept_sec_context.c (handle_type3): verify that the kdc + approved of the ntlm exchange too + + * mech/gss_mech_switch.c: Add the builtin ntlm mech + + * test_ntlm.c: NTLM test app. + + * mech/gss_accept_sec_context.c: Add detection of NTLMSSP. + + * gssapi/gssapi.h: add ntlm mech oid + + * ntlm/external.c: Switch OID to the ms ntlmssp oid + + * Makefile.am: Add ntlm gss-api module. + + * ntlm/accept_sec_context.c: Catch more error errors. + + * ntlm/accept_sec_context.c: Check after a credential to use. + +2006-12-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/set_sec_context_option.c (GSS_KRB5_SET_DEFAULT_REALM_X): + don't fail on success. Bug report from Stefan Metzmacher. + +2006-12-13 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/init_sec_context.c (init_auth): only turn on + GSS_C_CONF_FLAG and GSS_C_INT_FLAG if the caller requseted it. + From Stefan Metzmacher. + +2006-12-11 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am (libgssapi_la_OBJECTS): depends on gssapi_asn1.h + spnego_asn1.h. + +2006-11-20 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/acquire_cred.c: Make krb5_get_init_creds_opt_free take a + context argument. + +2006-11-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Test that token keys are the same, return + actual_mech. + +2006-11-15 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/spnego_locl.h: Make bitfields unsigned, add maybe_open. + + * spnego/accept_sec_context.c: Use ASN.1 encoder functions to + encode CHOICE structure now that we can handle it. + + * spnego/init_sec_context.c: Use ASN.1 encoder functions to encode + CHOICE structure now that we can handle it. + + * spnego/accept_sec_context.c (_gss_spnego_accept_sec_context): + send back ad accept_completed when the security context is ->open, + w/o this the client doesn't know that the server have completed + the transaction. + + * test_context.c: Add delegate flag and check that the delegated + cred works. + + * spnego/init_sec_context.c: Keep track of the opportunistic token + in the inital message, it might be a complete gss-api context, in + that case we'll get back accept_completed without any token. With + this change, krb5 w/o mutual authentication works. + + * spnego/accept_sec_context.c: Use ASN.1 encoder functions to + encode CHOICE structure now that we can handle it. + + * spnego/accept_sec_context.c: Filter out SPNEGO from the out + supported mechs list and make sure we don't select that for the + preferred mechamism. + +2006-11-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_init_sec_context.c (_gss_mech_cred_find): break out the + cred finding to its own function + + * krb5/wrap.c: Better error strings, from Andrew Bartlet. + +2006-11-13 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Create our own krb5_context. + + * krb5: Switch from using a specific error message context in the + TLS to have a whole krb5_context in TLS. This have some + interestion side-effekts for the configruration setting options + since they operate on per-thread basis now. + + * mech/gss_set_cred_option.c: When calling ->gm_set_cred_option + and checking for success, use GSS_S_COMPLETE. From Andrew Bartlet. + +2006-11-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: Help solaris make even more. + + * Makefile.am: Help solaris make. + +2006-11-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: remove include $(srcdir)/Makefile-digest.am for now + + * mech/gss_accept_sec_context.c: Try better guessing what is mech + we are going to select by looking harder at the input_token, idea + from Luke Howard's mechglue branch. + + * Makefile.am: libgssapi_la_OBJECTS: add depency on gkrb5_err.h + + * gssapi/gssapi_krb5.h: add GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X + + * mech/gss_krb5.c: implement gss_krb5_set_allowable_enctypes + + * gssapi/gssapi.h: GSS_KRB5_S_ + + * krb5/gsskrb5_locl.h: Include <gkrb5_err.h>. + + * gssapi/gssapi_krb5.h: Add gss_krb5_set_allowable_enctypes. + + * Makefile.am: Build and install gkrb5_err.h + + * krb5/gkrb5_err.et: Move the GSS_KRB5_S error here. + +2006-11-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_krb5.c: Add gsskrb5_set_default_realm. + + * krb5/set_sec_context_option.c: Support + GSS_KRB5_SET_DEFAULT_REALM_X. + + * gssapi/gssapi_krb5.h: add GSS_KRB5_SET_DEFAULT_REALM_X + + * krb5/external.c: add GSS_KRB5_SET_DEFAULT_REALM_X + +2006-11-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: rename krb5_[gs]et_time_wrap to + krb5_[gs]et_max_time_skew + + * krb5/copy_ccache.c: _gsskrb5_extract_authz_data_from_sec_context + no longer used, bye bye + + * mech/gss_krb5.c: No depenency of the krb5 gssapi mech. + + * mech/gss_krb5.c (gsskrb5_extract_authtime_from_sec_context): use + _gsskrb5_decode_om_uint32. From Andrew Bartlet. + + * mech/gss_krb5.c: Add dummy gss_krb5_set_allowable_enctypes for + now. + + * spnego/spnego_locl.h: Include <roken.h> for compatiblity. + + * krb5/arcfour.c: Use IS_DCE_STYLE flag. There is no padding in + DCE-STYLE, don't try to use to. From Andrew Bartlett. + + * test_context.c: test wrap/unwrap, add flag for dce-style and + mutual auth, also support multi-roundtrip sessions + + * krb5/gsskrb5_locl.h: Add IS_DCE_STYLE macro. + + * krb5/accept_sec_context.c (gsskrb5_acceptor_start): use + krb5_rd_req_ctx + + * mech/gss_krb5.c (gsskrb5_get_subkey): return the per message + token subkey + + * krb5/inquire_sec_context_by_oid.c: check if there is any key at + all + +2006-11-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/inquire_sec_context_by_oid.c: Set more error strings, use + right enum for acceptor subkey. From Andrew Bartlett. + +2006-11-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Test gsskrb5_extract_service_keyblock, needed in + PAC valication. From Andrew Bartlett + + * mech/gss_krb5.c: Add gsskrb5_extract_authz_data_from_sec_context + and keyblock extraction functions. + + * gssapi/gssapi_krb5.h: Add extraction of keyblock function, from + Andrew Bartlett. + + * krb5/external.c: Add GSS_KRB5_GET_SERVICE_KEYBLOCK_X + +2006-11-03 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Rename various routines and constants from + canonize to canonicalize. From Andrew Bartlett + + * mech/gss_krb5.c: Rename various routines and constants from + canonize to canonicalize. From Andrew Bartlett + + * krb5/set_sec_context_option.c: Rename various routines and + constants from canonize to canonicalize. From Andrew Bartlett + + * krb5/external.c: Rename various routines and constants from + canonize to canonicalize. From Andrew Bartlett + + * gssapi/gssapi_krb5.h: Rename various routines and constants from + canonize to canonicalize. From Andrew Bartlett + +2006-10-25 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/accept_sec_context.c (gsskrb5_accept_delegated_token): need + to free ccache + +2006-10-24 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c (loop): free target_name + + * mech/gss_accept_sec_context.c: SLIST_INIT the ->gc_mc' + + * mech/gss_acquire_cred.c : SLIST_INIT the ->gc_mc' + + * krb5/init_sec_context.c: Avoid leaking memory. + + * mech/gss_buffer_set.c (gss_release_buffer_set): don't leak the + ->elements memory. + + * test_context.c: make compile + + * krb5/cfx.c (_gssapi_verify_mic_cfx): always free crypto context. + + * krb5/set_cred_option.c (import_cred): free sp + +2006-10-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_add_oid_set_member.c: Use old implementation of + gss_add_oid_set_member, it leaks less memory. + + * krb5/test_cfx.c: free krb5_crypto. + + * krb5/test_cfx.c: free krb5_context + + * mech/gss_release_name.c (gss_release_name): free input_name + it-self. + +2006-10-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Call setprogname. + + * mech/gss_krb5.c: Add gsskrb5_extract_authtime_from_sec_context. + + * gssapi/gssapi_krb5.h: add + gsskrb5_extract_authtime_from_sec_context + +2006-10-20 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/inquire_sec_context_by_oid.c: Add get_authtime. + + * krb5/external.c: add GSS_KRB5_GET_AUTHTIME_X + + * gssapi/gssapi_krb5.h: add GSS_KRB5_GET_AUTHTIME_X + + * krb5/set_sec_context_option.c: Implement GSS_KRB5_SEND_TO_KDC_X. + + * mech/gss_krb5.c: Add gsskrb5_set_send_to_kdc + + * gssapi/gssapi_krb5.h: Add GSS_KRB5_SEND_TO_KDC_X and + gsskrb5_set_send_to_kdc + + * krb5/external.c: add GSS_KRB5_SEND_TO_KDC_X + + * Makefile.am: more files + +2006-10-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: remove spnego/gssapi_spnego.h, its now in gssapi/ + + * test_context.c: Allow specifing mech. + + * krb5/external.c: add GSS_SASL_DIGEST_MD5_MECHANISM (for now) + + * gssapi/gssapi.h: Rename GSS_DIGEST_MECHANISM to + GSS_SASL_DIGEST_MD5_MECHANISM + +2006-10-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gssapi.asn1: Make it into a heim_any_set, its doesn't + except a tag. + + * mech/gssapi.asn1: GSSAPIContextToken is IMPLICIT SEQUENCE + + * gssapi/gssapi_krb5.h: add GSS_KRB5_GET_ACCEPTOR_SUBKEY_X + + * krb5/external.c: Add GSS_KRB5_GET_ACCEPTOR_SUBKEY_X. + + * gssapi/gssapi_krb5.h: add GSS_KRB5_GET_INITIATOR_SUBKEY_X and + GSS_KRB5_GET_SUBKEY_X + + * krb5/external.c: add GSS_KRB5_GET_INITIATOR_SUBKEY_X, + GSS_KRB5_GET_SUBKEY_X + +2006-10-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_context.c: Support switching on name type oid's + + * test_context.c: add test for dns canon flag + + * mech/gss_krb5.c: Add gsskrb5_set_dns_canonlize. + + * gssapi/gssapi_krb5.h: remove gss_krb5_compat_des3_mic + + * gssapi/gssapi_krb5.h: Add gsskrb5_set_dns_canonlize. + + * krb5/set_sec_context_option.c: implement + GSS_KRB5_SET_DNS_CANONIZE_X + + * gssapi/gssapi_krb5.h: add GSS_KRB5_SET_DNS_CANONIZE_X + + * krb5/external.c: add GSS_KRB5_SET_DNS_CANONIZE_X + + * mech/gss_krb5.c: add bits to make lucid context work + +2006-10-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_oid_to_str.c: Prefix der primitives with der_. + + * krb5/inquire_sec_context_by_oid.c: Prefix der primitives with + der_. + + * krb5/encapsulate.c: Prefix der primitives with der_. + + * mech/gss_oid_to_str.c: New der_print_heim_oid signature. + +2006-10-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: add test_context + + * krb5/inquire_sec_context_by_oid.c: Make it work. + + * test_oid.c: Test lucid oid. + + * gssapi/gssapi.h: Add OM_uint64_t. + + * krb5/inquire_sec_context_by_oid.c: Add lucid interface. + + * krb5/external.c: Add lucid interface, renumber oids to my + delegated space. + + * mech/gss_krb5.c: Add lucid interface. + + * gssapi/gssapi_krb5.h: Add lucid interface. + + * spnego/spnego_locl.h: Maybe include <netdb.h>. + +2006-10-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_mech_switch.c: define RTLD_LOCAL to 0 if not defined. + +2006-10-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: install gssapi_krb5.H and gssapi_spnego.h + + * gssapi/gssapi_krb5.h: Move krb5 stuff to <gssapi/gssapi_krb5.h>. + + * gssapi/gssapi.h: Move krb5 stuff to <gssapi/gssapi_krb5.h>. + + * Makefile.am: Drop some -I no longer needed. + + * gssapi/gssapi_spnego.h: Move gssapi_spengo.h over here. + + * krb5: reference all include files using 'krb5/' + +2006-10-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: Add file inclusion protection. + + * gssapi/gssapi.h: Correct header file inclusion protection. + + * gssapi/gssapi.h: Move the gssapi.h from lib/gssapi/ to + lib/gssapi/gssapi/ to please automake. + + * spnego/spnego_locl.h: Maybe include <sys/types.h>. + + * mech/mech_locl.h: Include <roken.h>. + + * Makefile.am: split build files into dist_ and noinst_ SOURCES + +2006-10-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss.c: #if 0 out unused code. + + * mech/gss_mech_switch.c: Cast argument to ctype(3) functions + to (unsigned char). + +2006-10-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/name.h: remove <sys/queue.h> + + * mech/mech_switch.h: remove <sys/queue.h> + + * mech/cred.h: remove <sys/queue.h> + +2006-10-02 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/arcfour.c: Thinker more with header lengths. + + * krb5/arcfour.c: Improve the calcucation of header + lengths. DCE-STYLE data is also padded so remove if (1 || ...) + code. + + * krb5/wrap.c (_gsskrb5_wrap_size_limit): use + _gssapi_wrap_size_arcfour for arcfour + + * krb5/arcfour.c: Move _gssapi_wrap_size_arcfour here. + + * Makefile.am: Split all mech to diffrent mechsrc variables. + + * spnego/context_stubs.c: Make internal function static (and + rename). + +2006-10-01 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/inquire_cred.c: Fix "if (x) lock(y)" bug. From Harald + Barth. + + * spnego/spnego_locl.h: Include <sys/param.h> for MAXHOSTNAMELEN. + +2006-09-25 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/arcfour.c: Add wrap support, interrop with itself but not + w2k3s-sp1 + + * krb5/gsskrb5_locl.h: move the arcfour specific stuff to the + arcfour header. + + * krb5/arcfour.c: Support DCE-style unwrap, tested with + w2k3server-sp1. + + * mech/gss_accept_sec_context.c (gss_accept_sec_context): if the + token doesn't start with [APPLICATION 0] SEQUENCE, lets assume its + a DCE-style kerberos 5 connection. XXX this needs to be made + better in cause we get another GSS-API protocol violating + protocol. It should be possible to detach the Kerberos DCE-style + since it starts with a AP-REQ PDU, but that have to wait for now. + +2006-09-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: Add GSS_C flags from + draft-brezak-win2k-krb-rc4-hmac-04.txt. + + * krb5/delete_sec_context.c: Free service_keyblock and fwd_data, + indent. + + * krb5/accept_sec_context.c: Merge of the acceptor part from the + samba patch by Stefan Metzmacher and Andrew Bartlet. + + * krb5/init_sec_context.c: Add GSS_C_DCE_STYLE. + + * krb5/{init_sec_context.c,gsskrb5_locl.h}: merge most of the + initiator part from the samba patch by Stefan Metzmacher and + Andrew Bartlet (still missing DCE/RPC support) + +2006-08-28 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss.c (help): use sl_slc_help(). + +2006-07-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss-commands.in: rename command to supported-mechanisms + + * Makefile.am: Make gss objects depend on the slc built + gss-commands.h + +2006-07-20 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss-commands.in: add slc commands for gss + + * krb5/gsskrb5_locl.h: Remove dup prototype of _gsskrb5_init() + + * Makefile.am: Add test_cfx + + * krb5/external.c: add GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X + + * krb5/set_sec_context_option.c: catch + GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X + + * krb5/accept_sec_context.c: reimplement + gsskrb5_register_acceptor_identity + + * mech/gss_krb5.c: implement gsskrb5_register_acceptor_identity + + * mech/gss_inquire_mechs_for_name.c: call _gss_load_mech + + * mech/gss_inquire_cred.c (gss_inquire_cred): call _gss_load_mech + + * mech/gss_mech_switch.c: Make _gss_load_mech() atomic and run + only once, this have the side effect that _gss_mechs and + _gss_mech_oids is only initialized once, so if just the users of + these two global variables calls _gss_load_mech() first, it will + act as a barrier and make sure the variables are never changed and + we don't need to lock them. + + * mech/utils.h: no need to mark functions extern. + + * mech/name.h: no need to mark _gss_find_mn extern. + +2006-07-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/cfx.c: Redo the wrap length calculations. + + * krb5/test_cfx.c: test max_wrap_size in cfx.c + + * mech/gss_display_status.c: Handle more error codes. + +2006-07-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/mech_locl.h: Include <krb5-types.h> and "mechqueue.h" + + * mech/mechqueue.h: Add SLIST macros. + + * krb5/inquire_context.c: Don't free return values on success. + + * krb5/inquire_cred.c (_gsskrb5_inquire_cred): When cred provided + is the default cred, acquire the acceptor cred and initator cred + in two diffrent steps and then query them for the information, + this way, the code wont fail if there are no keytab, but there is + a credential cache. + + * mech/gss_inquire_cred.c: move the check if we found any cred + where it matter for both cases + (default cred and provided cred) + + * mech/gss_init_sec_context.c: If the desired mechanism can't + convert the name to a MN, fail with GSS_S_BAD_NAME rather then a + NULL de-reference. + +2006-07-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/external.c: readd gss_spnego_inquire_names_for_mech + + * spnego/spnego_locl.h: reimplement + gss_spnego_inquire_names_for_mech add support function + _gss_spnego_supported_mechs + + * spnego/context_stubs.h: reimplement + gss_spnego_inquire_names_for_mech add support function + _gss_spnego_supported_mechs + + * spnego/context_stubs.c: drop gss_spnego_indicate_mechs + + * mech/gss_indicate_mechs.c: if the underlaying mech doesn't + support gss_indicate_mechs, use the oid in the mechswitch + structure + + * spnego/external.c: let the mech glue layer implement + gss_indicate_mechs + + * spnego/cred_stubs.c (gss_spnego_acquire_cred): don't care about + desired_mechs, get our own list with indicate_mechs and remove + ourself. + +2006-07-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * spnego/external.c: remove gss_spnego_inquire_names_for_mech, let + the mechglue layer implement it + + * spnego/context_stubs.c: remove gss_spnego_inquire_names_for_mech, let + the mechglue layer implement it + + * spnego/spnego_locl.c: remove gss_spnego_inquire_names_for_mech, let + the mechglue layer implement it + +2006-07-01 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_set_cred_option.c: fix argument to gss_release_cred + +2006-06-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/init_sec_context.c: Make work on compilers that are + somewhat more picky then gcc4 (like gcc2.95) + + * krb5/init_sec_context.c (do_delegation): use KDCOptions2int to + convert fwd_flags to an integer, since otherwise int2KDCOptions in + krb5_get_forwarded_creds wont do the right thing. + + * mech/gss_set_cred_option.c (gss_set_cred_option): free memory on + failure + + * krb5/set_sec_context_option.c (_gsskrb5_set_sec_context_option): + init global kerberos context + + * krb5/set_cred_option.c (_gsskrb5_set_cred_option): init global + kerberos context + + * mech/gss_accept_sec_context.c: Insert the delegated sub cred on + the delegated cred handle, not cred handle + + * mech/gss_accept_sec_context.c (gss_accept_sec_context): handle + the case where ret_flags == NULL + + * mech/gss_mech_switch.c (add_builtin): set + _gss_mech_switch->gm_mech_oid + + * mech/gss_set_cred_option.c (gss_set_cred_option): laod mechs + + * test_cred.c (gss_print_errors): don't try to print error when + gss_display_status failed + + * Makefile.am: Add mech/gss_release_oid.c + + * mech/gss_release_oid.c: Add gss_release_oid, reverse of + gss_duplicate_oid + + * spnego/compat.c: preferred_mech_type was allocated with + gss_duplicate_oid in one place and assigned static varianbles a + the second place. change that static assignement to + gss_duplicate_oid and bring back gss_release_oid. + + * spnego/compat.c (_gss_spnego_delete_sec_context): don't release + preferred_mech_type and negotiated_mech_type, they where never + allocated from the begining. + +2006-06-29 Love Hörnquist Ã…strand <lha@it.su.se> + + * mech/gss_import_name.c (gss_import_name): avoid + type-punned/strict aliasing rules + + * mech/gss_add_cred.c: avoid type-punned/strict aliasing rules + + * gssapi.h: Make gss_name_t an opaque type. + + * krb5: make gss_name_t an opaque type + + * krb5/set_cred_option.c: Add + + * mech/gss_set_cred_option.c (gss_set_cred_option): support the + case where *cred_handle == NULL + + * mech/gss_krb5.c (gss_krb5_import_cred): make sure cred is + GSS_C_NO_CREDENTIAL on failure. + + * mech/gss_acquire_cred.c (gss_acquire_cred): if desired_mechs is + NO_OID_SET, there is a need to load the mechs, so always do that. + +2006-06-28 Love Hörnquist Ã…strand <lha@it.su.se> + + * krb5/inquire_cred_by_oid.c: Reimplement GSS_KRB5_COPY_CCACHE_X + to instead pass a fullname to the credential, then resolve and + copy out the content, and then close the cred. + + * mech/gss_krb5.c: Reimplement GSS_KRB5_COPY_CCACHE_X to instead + pass a fullname to the credential, then resolve and copy out the + content, and then close the cred. + + * krb5/inquire_cred_by_oid.c: make "work", GSS_KRB5_COPY_CCACHE_X + interface needs to be re-done, currently its utterly broken. + + * mech/gss_set_cred_option.c: Make work. + + * krb5/external.c: Add _gsskrb5_set_{sec_context,cred}_option + + * mech/gss_krb5.c (gss_krb5_import_cred): implement + + * Makefile.am: Add gss_set_{sec_context,cred}_option and sort + + * mech/gss_set_{sec_context,cred}_option.c: add + + * gssapi.h: Add GSS_KRB5_IMPORT_CRED_X + + * test_*.c: make compile again + + * Makefile.am: Add lib dependencies and test programs + + * spnego: remove dependency on libkrb5 + + * mech: Bug fixes, cleanup, compiler warnings, restructure code. + + * spnego: Rename gss_context_id_t and gss_cred_id_t to local names + + * krb5: repro copy the krb5 files here + + * mech: import Doug Rabson mechglue from freebsd + + * spnego: Import Luke Howard's SPNEGO from the mechglue branch + +2006-06-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: Add oid_to_str. + + * Makefile.am: add oid_to_str and test_oid + + * oid_to_str.c: Add gss_oid_to_str + + * test_oid.c: Add test for gss_oid_to_str() + +2006-05-13 Love Hörnquist Ã…strand <lha@it.su.se> + + * verify_mic.c: Less pointer signedness warnings. + + * unwrap.c: Less pointer signedness warnings. + + * arcfour.c: Less pointer signedness warnings. + + * gssapi_locl.h: Use const void * to instead of unsigned char * to + avoid pointer signedness warnings. + + * encapsulate.c: Use const void * to instead of unsigned char * to + avoid pointer signedness warnings. + + * decapsulate.c: Use const void * to instead of unsigned char * to + avoid pointer signedness warnings. + + * decapsulate.c: Less pointer signedness warnings. + + * cfx.c: Less pointer signedness warnings. + + * init_sec_context.c: Less pointer signedness warnings (partly by + using the new asn.1 CHOICE decoder) + + * import_sec_context.c: Less pointer signedness warnings. + +2006-05-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * accept_sec_context.c (gsskrb5_is_cfx): always set is_cfx. From + Andrew Abartlet. + +2006-05-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * get_mic.c (mic_des3): make sure message_buffer doesn't point to + free()ed memory on failure. Pointed out by IBM checker. + +2006-05-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * Rename u_intXX_t to uintXX_t + +2006-05-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: Less pointer signedness warnings. + + * arcfour.c: Avoid pointer signedness warnings. + + * gssapi_locl.h (gssapi_decode_*): make data argument const void * + + * 8003.c (gssapi_decode_*): make data argument const void * + +2006-04-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * export_sec_context.c: Export sequence order element. From Wynn + Wilkes <wynn.wilkes@quest.com>. + + * import_sec_context.c: Import sequence order element. From Wynn + Wilkes <wynn.wilkes@quest.com>. + + * sequence.c (_gssapi_msg_order_import,_gssapi_msg_order_export): + New functions, used by {import,export}_sec_context. From Wynn + Wilkes <wynn.wilkes@quest.com>. + + * test_sequence.c: Add test for import/export sequence. + +2006-04-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * add_cred.c: Check that cred != GSS_C_NO_CREDENTIAL, this is a + standard conformance failure, but much better then a crash. + +2006-04-02 Love Hörnquist Ã…strand <lha@it.su.se> + + * get_mic.c (get_mic*)_: make sure message_token is cleaned on + error, found by IBM checker. + + * wrap.c (wrap*): Reset output_buffer on error, found by IBM + checker. + +2006-02-15 Love Hörnquist Ã…strand <lha@it.su.se> + + * import_name.c: Accept both GSS_C_NT_HOSTBASED_SERVICE and + GSS_C_NT_HOSTBASED_SERVICE_X as nametype for hostbased names. + +2006-01-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * delete_sec_context.c (gss_delete_sec_context): if the context + handle is GSS_C_NO_CONTEXT, don't fall over. + +2005-12-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: Replace gss_krb5_import_ccache with + gss_krb5_import_cred and add more references + +2005-12-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: Change gss_krb5_import_ccache to gss_krb5_import_cred, + it can handle keytabs too. + + * add_cred.c (gss_add_cred): avoid deadlock + + * context_time.c (gssapi_lifetime_left): define the 0 lifetime as + GSS_C_INDEFINITE. + +2005-12-01 Love Hörnquist Ã…strand <lha@it.su.se> + + * acquire_cred.c (acquire_acceptor_cred): only check if principal + exists if we got called with principal as an argument. + + * acquire_cred.c (acquire_acceptor_cred): check that the acceptor + exists in the keytab before returning ok. + +2005-11-29 Love Hörnquist Ã…strand <lha@it.su.se> + + * copy_ccache.c (gss_krb5_import_cred): fix buglet, from Andrew + Bartlett. + +2005-11-25 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_kcred.c: Rename gss_krb5_import_ccache to + gss_krb5_import_cred. + + * copy_ccache.c: Rename gss_krb5_import_ccache to + gss_krb5_import_cred and let it grow code to handle keytabs too. + +2005-11-02 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c: Change sematics of ok-as-delegate to match + windows if + [gssapi]realm/ok-as-delegate=true is set, otherwise keep old + sematics. + + * release_cred.c (gss_release_cred): use + GSS_CF_DESTROY_CRED_ON_RELEASE to decide if the cache should be + krb5_cc_destroy-ed + + * acquire_cred.c (acquire_initiator_cred): + GSS_CF_DESTROY_CRED_ON_RELEASE on created credentials. + + * accept_sec_context.c (gsskrb5_accept_delegated_token): rewrite + to use gss_krb5_import_ccache + +2005-11-01 Love Hörnquist Ã…strand <lha@it.su.se> + + * arcfour.c: Remove signedness warnings. + +2005-10-31 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: Document that gss_krb5_import_ccache is copy + by reference. + + * copy_ccache.c (gss_krb5_import_ccache): Instead of making a copy + of the ccache, make a reference by getting the name and resolving + the name. This way the cache is shared, this flipp side is of + course that if someone calls krb5_cc_destroy the cache is lost for + everyone. + + * test_kcred.c: Remove memory leaks. + +2005-10-26 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: build test_kcred + + * gss_acquire_cred.3: Document gss_krb5_import_ccache + + * gssapi.3: Sort and add gss_krb5_import_ccache. + + * acquire_cred.c (_gssapi_krb5_ccache_lifetime): break out code + used to extract lifetime from a credential cache + + * gssapi_locl.h: Add _gssapi_krb5_ccache_lifetime, used to extract + lifetime from a credential cache. + + * gssapi.h: add gss_krb5_import_ccache, reverse of + gss_krb5_copy_ccache + + * copy_ccache.c: add gss_krb5_import_ccache, reverse of + gss_krb5_copy_ccache + + * test_kcred.c: test gss_krb5_import_ccache + +2005-10-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * acquire_cred.c (acquire_initiator_cred): use krb5_cc_cache_match + to find a matching creditial cache, if that failes, fallback to + the default cache. + +2005-10-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi_locl.h: Add gssapi_krb5_set_status and + gssapi_krb5_clear_status + + * init_sec_context.c (spnego_reply): Don't pass back raw Kerberos + errors, use GSS-API errors instead. From Michael B Allen. + + * display_status.c: Add gssapi_krb5_clear_status, + gssapi_krb5_set_status for handling error messages. + +2005-08-23 Love Hörnquist Ã…strand <lha@it.su.se> + + * external.c: Use rk_UNCONST to avoid const warning. + + * display_status.c: Constify strings to avoid warnings. + +2005-08-11 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c: avoid warnings, update (c) + +2005-07-13 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c (spnego_initial): use NegotiationToken + encoder now that we have one with the new asn1. compiler. + + * Makefile.am: the new asn.1 compiler includes the modules name in + the depend file + +2005-06-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * decapsulate.c: use rk_UNCONST + + * ccache_name.c: rename to avoid shadowing + + * gssapi_locl.h: give kret in GSSAPI_KRB5_INIT a more unique name + + * process_context_token.c: use rk_UNCONST to unconstify + + * test_cred.c: rename optind to optidx + +2005-05-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c (init_auth): honor ok-as-delegate if local + configuration approves + + * gssapi_locl.h: prototype for _gss_check_compat + + * compat.c: export check_compat as _gss_check_compat + +2005-05-29 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c: Prefix Der_class with ASN1_C_ to avoid + problems with system headerfiles that pollute the name space. + + * accept_sec_context.c: Prefix Der_class with ASN1_C_ to avoid + problems with system headerfiles that pollute the name space. + +2005-05-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c (init_auth): set + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED (for java compatibility), + also while here, use krb5_auth_con_addflags + +2005-05-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * arcfour.c (_gssapi_wrap_arcfour): fix calculating the encap + length. From: Tom Maher <tmaher@eecs.berkeley.edu> + +2005-05-02 Dave Love <fx@gnu.org> + + * test_cred.c (main): Call setprogname. + +2005-04-27 Love Hörnquist Ã…strand <lha@it.su.se> + + * prefix all sequence symbols with _, they are not part of the + GSS-API api. By comment from Wynn Wilkes <wynnw@vintela.com> + +2005-04-10 Love Hörnquist Ã…strand <lha@it.su.se> + + * accept_sec_context.c: break out the processing of the delegated + credential to a separate function to make error handling easier, + move the credential handling to after other setup is done + + * test_sequence.c: make less verbose in case of success + + * Makefile.am: add test_sequence to TESTS + +2005-04-01 Love Hörnquist Ã…strand <lha@it.su.se> + + * 8003.c (gssapi_krb5_verify_8003_checksum): check that cksum + isn't NULL From: Nicolas Pouvesle <npouvesle@tenablesecurity.com> + +2005-03-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: use $(LIB_roken) + +2005-03-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * display_status.c (gssapi_krb5_set_error_string): pass in the + krb5_context to krb5_free_error_string + +2005-03-15 Love Hörnquist Ã…strand <lha@it.su.se> + + * display_status.c (gssapi_krb5_set_error_string): don't misuse + the krb5_get_error_string api + +2005-03-01 Love Hörnquist Ã…strand <lha@it.su.se> + + * compat.c (_gss_DES3_get_mic_compat): don't unlock mutex + here. Bug reported by Stefan Metzmacher <metze@samba.org> + +2005-02-21 Luke Howard <lukeh@padl.com> + + * init_sec_context.c: don't call krb5_get_credentials() with + KRB5_TC_MATCH_KEYTYPE, it can lead to the credentials cache + growing indefinitely as no key is found with KEYTYPE_NULL + + * compat.c: remove GSS_C_EXPECTING_MECH_LIST_MIC_FLAG, it is + no longer used (however the mechListMIC behaviour is broken, + rfc2478bis support requires the code in the mechglue branch) + + * init_sec_context.c: remove GSS_C_EXPECTING_MECH_LIST_MIC_FLAG + + * gssapi.h: remove GSS_C_EXPECTING_MECH_LIST_MIC_FLAG + +2005-01-05 Luke Howard <lukeh@padl.com> + + * 8003.c: use symbolic name for checksum type + + * accept_sec_context.c: allow client to indicate + that subkey should be used + + * acquire_cred.c: plug leak + + * get_mic.c: use gss_krb5_get_subkey() instead + of gss_krb5_get_{local,remote}key(), support + KEYTYPE_ARCFOUR_56 + + * gssapi_local.c: use gss_krb5_get_subkey(), + support KEYTYPE_ARCFOUR_56 + + * import_sec_context.c: plug leak + + * unwrap.c: use gss_krb5_get_subkey(), + support KEYTYPE_ARCFOUR_56 + + * verify_mic.c: use gss_krb5_get_subkey(), + support KEYTYPE_ARCFOUR_56 + + * wrap.c: use gss_krb5_get_subkey(), + support KEYTYPE_ARCFOUR_56 + +2004-11-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * inquire_cred.c: Reverse order of HEIMDAL_MUTEX_unlock and + gss_release_cred to avoid deadlock, from Luke Howard + <lukeh@padl.com>. + +2004-09-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: gss_krb5_extract_authz_data_from_sec_context + was renamed to gsskrb5_extract_authz_data_from_sec_context + +2004-08-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * unwrap.c: mutex buglet, From: Luke Howard <lukeh@PADL.COM> + + * arcfour.c: mutex buglet, From: Luke Howard <lukeh@PADL.COM> + +2004-05-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.3: spelling from Josef El-Rayes <josef@FreeBSD.org> while + here, write some text about the SPNEGO situation + +2004-04-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: s/CTXAcceptorSubkey/CFXAcceptorSubkey/ + +2004-04-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: add GSS_C_EXPECTING_MECH_LIST_MIC_FLAG From: Luke + Howard <lukeh@padl.com> + + * init_sec_context.c (spnego_reply): use + _gss_spnego_require_mechlist_mic to figure out if we need to check + MechListMIC; From: Luke Howard <lukeh@padl.com> + + * accept_sec_context.c (send_accept): use + _gss_spnego_require_mechlist_mic to figure out if we need to send + MechListMIC; From: Luke Howard <lukeh@padl.com> + + * gssapi_locl.h: add _gss_spnego_require_mechlist_mic + From: Luke Howard <lukeh@padl.com> + + * compat.c: add _gss_spnego_require_mechlist_mic for compatibility + with MS SPNEGO, From: Luke Howard <lukeh@padl.com> + +2004-04-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * accept_sec_context.c (gsskrb5_is_cfx): krb5_keyblock->keytype is + an enctype, not keytype + + * accept_sec_context.c: use ASN1_MALLOC_ENCODE + + * init_sec_context.c: avoid the malloc loop and just allocate the + propper amount of data + + * init_sec_context.c (spnego_initial): handle mech_token better + +2004-03-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: add gss_krb5_get_tkt_flags + + * Makefile.am: add ticket_flags.c + + * ticket_flags.c: Get ticket-flags from acceptor ticket From: Luke + Howard <lukeh@PADL.COM> + + * gss_acquire_cred.3: document gss_krb5_get_tkt_flags + +2004-03-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * acquire_cred.c (gss_acquire_cred): check usage before even + bothering to process it, add both keytab and initial tgt if + requested + + * wrap.c: support cfx, try to handle acceptor asserted subkey + + * unwrap.c: support cfx, try to handle acceptor asserted subkey + + * verify_mic.c: support cfx + + * get_mic.c: support cfx + + * test_sequence.c: handle changed signature of + gssapi_msg_order_create + + * import_sec_context.c: handle acceptor asserted subkey + + * init_sec_context.c: handle acceptor asserted subkey + + * accept_sec_context.c: handle acceptor asserted subkey + + * sequence.c: add dummy use_64 argument to gssapi_msg_order_create + + * gssapi_locl.h: add partial support for CFX + + * Makefile.am (noinst_PROGRAMS) += test_cred + + * test_cred.c: gssapi credential testing + + * test_acquire_cred.c: fix comment + +2004-03-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * arcfour.h: drop structures for message formats, no longer used + + * arcfour.c: comment describing message formats + + * accept_sec_context.c (spnego_accept_sec_context): make sure the + length of the choice element doesn't overrun us + + * init_sec_context.c (spnego_reply): make sure the length of the + choice element doesn't overrun us + + * spnego.asn1: move NegotiationToken to avoid warning + + * spnego.asn1: uncomment NegotiationToken + + * Makefile.am: spnego_files += asn1_NegotiationToken.x + +2004-01-25 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: add gss_krb5_ccache_name + + * Makefile.am (libgssapi_la_SOURCES): += ccache_name.c + + * ccache_name.c (gss_krb5_ccache_name): help function enable to + set krb5 name, using out_name argument makes function no longer + thread-safe + + * gssapi.3: add missing gss_krb5_ references + + * gss_acquire_cred.3: document gss_krb5_ccache_name + +2003-12-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: make rrc a modulus operation if its longer then the + length of the message, noticed by Sam Hartman + +2003-12-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * accept_sec_context.c: use krb5_auth_con_addflags + +2003-12-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: Wrap token id was in wrong order, found by Sam Hartman + +2003-12-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: add AcceptorSubkey (but no code understand it yet) ignore + unknown token flags + +2003-11-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * accept_sec_context.c: Don't require timestamp to be set on + delegated token, its already protected by the outer token (and + windows doesn't alway send it) Pointed out by Zi-Bin Yang + <zbyang@decru.com> on heimdal-discuss + +2003-11-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: fix {} error, pointed out by Liqiang Zhu + +2003-11-10 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: Sequence number should be stored in bigendian order From: + Luke Howard <lukeh@padl.com> + +2003-11-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * delete_sec_context.c (gss_delete_sec_context): don't free + ticket, krb5_free_ticket does that now + +2003-11-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: checksum the header last in MIC token, update to -03 + From: Luke Howard <lukeh@padl.com> + +2003-10-07 Love Hörnquist Ã…strand <lha@it.su.se> + + * add_cred.c: If its a MEMORY cc, make a copy. We need to do this + since now gss_release_cred will destroy the cred. This should be + really be solved a better way. + + * acquire_cred.c (gss_release_cred): if its a mcc, destroy it + rather the just release it Found by: "Zi-Bin Yang" + <zbyang@decru.com> + + * acquire_cred.c (acquire_initiator_cred): use kret instead of ret + where appropriate + +2003-09-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: spelling + From: jmc <jmc@prioris.mini.pw.edu.pl> + +2003-09-23 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: - EC and RRC are big-endian, not little-endian - The + default is now to rotate regardless of GSS_C_DCE_STYLE. There are + no longer any references to GSS_C_DCE_STYLE. - rrc_rotate() + avoids allocating memory on the heap if rrc <= 256 + From: Luke Howard <lukeh@padl.com> + +2003-09-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.[ch]: rrc_rotate() was untested and broken, fix it. + Set and verify wrap Token->Filler. + Correct token ID for wrap tokens, + were accidentally swapped with delete tokens. + From: Luke Howard <lukeh@PADL.COM> + +2003-09-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.[ch]: no ASN.1-ish header on per-message tokens + From: Luke Howard <lukeh@PADL.COM> + +2003-09-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * arcfour.h: remove depenency on gss_arcfour_mic_token and + gss_arcfour_warp_token + + * arcfour.c: remove depenency on gss_arcfour_mic_token and + gss_arcfour_warp_token + +2003-09-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * 8003.c: remove #if 0'ed code + +2003-09-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * accept_sec_context.c (gsskrb5_accept_sec_context): set sequence + number when not requesting mutual auth From: Luke Howard + <lukeh@PADL.COM> + + * init_sec_context.c (init_auth): set sequence number when not + requesting mutual auth From: Luke Howard <lukeh@PADL.COM> + +2003-09-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * arcfour.c (*): set minor_status + (gss_wrap): set conf_state to conf_req_flags on success + From: Luke Howard <lukeh@PADL.COM> + + * wrap.c (gss_wrap_size_limit): use existing function From: Luke + Howard <lukeh@PADL.COM> + +2003-09-12 Love Hörnquist Ã…strand <lha@it.su.se> + + * indicate_mechs.c (gss_indicate_mechs): in case of error, free + mech_set + + * indicate_mechs.c (gss_indicate_mechs): add SPNEGO + +2003-09-10 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c (spnego_initial): catch errors and return + them + + * init_sec_context.c (spnego_initial): add #if 0 out version of + the CHOICE branch encoding, also where here, free no longer used + memory + +2003-09-09 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: support GSS_SPNEGO_MECHANISM + + * accept_sec_context.c: SPNEGO doesn't include gss wrapping on + SubsequentContextToken like the Kerberos 5 mech does. + + * init_sec_context.c (spnego_reply): SPNEGO doesn't include gss + wrapping on SubsequentContextToken like the Kerberos 5 mech + does. Lets check for it anyway. + + * accept_sec_context.c: Add support for SPNEGO on the initator + side. Implementation initially from Assar Westerlund, passes + though quite a lot of hands before I commited it. + + * init_sec_context.c: Add support for SPNEGO on the initator side. + Tested with ldap server on a Windows 2000 DC. Implementation + initially from Assar Westerlund, passes though quite a lot of + hands before I commited it. + + * gssapi.h: export GSS_SPNEGO_MECHANISM + + * gssapi_locl.h: include spnego_as.h add prototype for + gssapi_krb5_get_mech + + * decapsulate.c (gssapi_krb5_get_mech): make non static + + * Makefile.am: build SPNEGO file + +2003-09-08 Love Hörnquist Ã…strand <lha@it.su.se> + + * external.c: SPENGO and IAKERB oids + + * spnego.asn1: SPENGO ASN1 + +2003-09-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.c: RRC also need to be zero before wraping them + From: Luke Howard <lukeh@PADL.COM> + +2003-09-04 Love Hörnquist Ã…strand <lha@it.su.se> + + * encapsulate.c (gssapi_krb5_encap_length): don't return void + +2003-09-03 Love Hörnquist Ã…strand <lha@it.su.se> + + * verify_mic.c: switch from the des_ to the DES_ api + + * get_mic.c: switch from the des_ to the DES_ api + + * unwrap.c: switch from the des_ to the DES_ api + + * wrap.c: switch from the des_ to the DES_ api + + * cfx.c: EC is not included in the checksum since the length might + change depending on the data. From: Luke Howard <lukeh@PADL.COM> + + * acquire_cred.c: use + krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free + +2003-09-01 Love Hörnquist Ã…strand <lha@it.su.se> + + * copy_ccache.c: rename + gss_krb5_extract_authz_data_from_sec_context to + gsskrb5_extract_authz_data_from_sec_context + + * gssapi.h: rename gss_krb5_extract_authz_data_from_sec_context to + gsskrb5_extract_authz_data_from_sec_context + +2003-08-31 Love Hörnquist Ã…strand <lha@it.su.se> + + * copy_ccache.c (gss_krb5_extract_authz_data_from_sec_context): + check that we have a ticket before we start to use it + + * gss_acquire_cred.3: document + gss_krb5_extract_authz_data_from_sec_context + + * gssapi.h (gss_krb5_extract_authz_data_from_sec_context): + return the kerberos authorizationdata, from idea of Luke Howard + + * copy_ccache.c (gss_krb5_extract_authz_data_from_sec_context): + return the kerberos authorizationdata, from idea of Luke Howard + + * verify_mic.c (gss_verify_mic_internal): switch type and key + argument + +2003-08-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * cfx.[ch]: draft-ietf-krb-wg-gssapi-cfx-01.txt implemetation + From: Luke Howard <lukeh@PADL.COM> + +2003-08-28 Love Hörnquist Ã…strand <lha@it.su.se> + + * arcfour.c (arcfour_mic_cksum): use free_Checksum to free the + checksum + + * arcfour.h: swap two last arguments to verify_mic for consistency + with des3 + + * wrap.c,unwrap.c,get_mic.c,verify_mic.c,cfx.c,cfx.h: + prefix cfx symbols with _gssapi_ + + * arcfour.c: release the right buffer + + * arcfour.c: rename token structure in consistency with rest of + GSS-API From: Luke Howard <lukeh@PADL.COM> + + * unwrap.c (unwrap_des3): use _gssapi_verify_pad + (unwrap_des): use _gssapi_verify_pad + + * arcfour.c (_gssapi_wrap_arcfour): set the correct padding + (_gssapi_unwrap_arcfour): verify and strip padding + + * gssapi_locl.h: added _gssapi_verify_pad + + * decapsulate.c (_gssapi_verify_pad): verify padding of a gss + wrapped message and return its length + + * arcfour.c: support KEYTYPE_ARCFOUR_56 keys, from Luke Howard + <lukeh@PADL.COM> + + * arcfour.c: use right seal alg, inherit keytype from parent key + + * arcfour.c: include the confounder in the checksum use the right + key usage number for warped/unwraped tokens + + * gssapi.h: add gss_krb5_nt_general_name as an mit compat glue + (same as GSS_KRB5_NT_PRINCIPAL_NAME) + + * unwrap.c: hook in arcfour unwrap + + * wrap.c: hook in arcfour wrap + + * verify_mic.c: hook in arcfour verify_mic + + * get_mic.c: hook in arcfour get_mic + + * arcfour.c: implement wrap/unwarp + + * gssapi_locl.h: add gssapi_{en,de}code_be_om_uint32 + + * 8003.c: add gssapi_{en,de}code_be_om_uint32 + +2003-08-27 Love Hörnquist Ã…strand <lha@it.su.se> + + * arcfour.c (_gssapi_verify_mic_arcfour): Do the checksum on right + area. Swap filler check, it was reversed. + + * Makefile.am (libgssapi_la_SOURCES): += arcfour.c + + * gssapi_locl.h: include "arcfour.h" + + * arcfour.c: arcfour gss-api mech, get_mic/verify_mic working + + * arcfour.h: arcfour gss-api mech, get_mic/verify_mic working + +2003-08-26 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi_locl.h: always include cfx.h add prototype for + _gssapi_decapsulate + + * cfx.[ch]: Implementation of draft-ietf-krb-wg-gssapi-cfx-00.txt + from Luke Howard <lukeh@PADL.COM> + + * decapsulate.c: add _gssapi_decapsulate, from Luke Howard + <lukeh@PADL.COM> + +2003-08-25 Love Hörnquist Ã…strand <lha@it.su.se> + + * unwrap.c: encap/decap now takes a oid if the enctype/keytype is + arcfour, return error add hook for cfx + + * verify_mic.c: encap/decap now takes a oid if the enctype/keytype + is arcfour, return error add hook for cfx + + * get_mic.c: encap/decap now takes a oid if the enctype/keytype is + arcfour, return error add hook for cfx + + * accept_sec_context.c: encap/decap now takes a oid + + * init_sec_context.c: encap/decap now takes a oid + + * gssapi_locl.h: include cfx.h if we need it lifetime is a + OM_uint32, depend on gssapi interface add all new encap/decap + functions + + * decapsulate.c: add decap functions that doesn't take the token + type also make all decap function take the oid mech that they + should use + + * encapsulate.c: add encap functions that doesn't take the token + type also make all encap function take the oid mech that they + should use + + * sequence.c (elem_insert): fix a off by one index counter + + * inquire_cred.c (gss_inquire_cred): handle cred_handle being + GSS_C_NO_CREDENTIAL and use the default cred then. + +2003-08-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: break out extensions and document + gsskrb5_register_acceptor_identity + +2003-08-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_acquire_cred.c (print_time): time is returned in seconds + from now, not unix time + +2003-08-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * compat.c (check_compat): avoid leaking principal when finding a + match + + * address_to_krb5addr.c: sa_size argument to krb5_addr2sockaddr is + a krb5_socklen_t + + * acquire_cred.c (gss_acquire_cred): 4th argument to + gss_test_oid_set_member is a int + +2003-07-22 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c (repl_mutual): don't set kerberos error where + there was no kerberos error + + * gssapi_locl.h: Add destruction/creation prototypes and structure + for the thread specific storage. + + * display_status.c: use thread specific storage to set/get the + kerberos error message + + * init.c: Provide locking around the creation of the global + krb5_context. Add destruction/creation functions for the thread + specific storage that the error string handling is using. + +2003-07-20 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: add missing prototype and missing .Ft + arguments + +2003-06-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * verify_mic.c: reorder code so sequence numbers can can be used + + * unwrap.c: reorder code so sequence numbers can can be used + + * sequence.c: remove unused function, indent, add + gssapi_msg_order_f that filter gss flags to gss_msg_order flags + + * gssapi_locl.h: prototypes for + gssapi_{encode_om_uint32,decode_om_uint32} add sequence number + verifier prototypes + + * delete_sec_context.c: destroy sequence number verifier + + * init_sec_context.c: remember to free data use sequence number + verifier + + * accept_sec_context.c: don't clear output_token twice remember to + free data use sequence number verifier + + * 8003.c: export and rename encode_om_uint32/decode_om_uint32 and + start to use them + +2003-06-09 Johan Danielsson <joda@pdc.kth.se> + + * Makefile.am: can't have sequence.c in two different places + +2003-06-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_sequence.c: check rollover, print summery + + * wrap.c (sub_wrap_size): gss_wrap_size_limit() has + req_output_size and max_input_size around the wrong way -- it + returns the output token size for a given input size, rather than + the maximum input size for a given output token size. + + From: Luke Howard <lukeh@PADL.COM> + +2003-06-05 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi_locl.h: add prototypes for sequence.c + + * Makefile.am (libgssapi_la_SOURCES): add sequence.c + (test_sequence): build + + * sequence.c: sequence number checks, order and replay + * test_sequence.c: sequence number checks, order and replay + +2003-06-03 Love Hörnquist Ã…strand <lha@it.su.se> + + * accept_sec_context.c (gss_accept_sec_context): make sure time is + returned in seconds from now, not in kerberos time + + * acquire_cred.c (gss_aquire_cred): make sure time is returned in + seconds from now, not in kerberos time + + * init_sec_context.c (init_auth): if the cred is expired before we + tries to create a token, fail so the peer doesn't need reject us + (*): make sure time is returned in seconds from now, + not in kerberos time + (repl_mutual): remember to unlock the context mutex + + * context_time.c (gss_context_time): remove unused variable + + * verify_mic.c: make sure minor_status is always set, pointed out + by Luke Howard <lukeh@PADL.COM> + +2003-05-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * *.[ch]: do some basic locking (no reference counting so contexts + can be removed while still used) + - don't export gss_ctx_id_t_desc_struct and gss_cred_id_t_desc_struct + - make sure all lifetime are returned in seconds left until expired, + not in unix epoch + + * gss_acquire_cred.3: document argument lifetime_rec to function + gss_inquire_context + +2003-05-17 Love Hörnquist Ã…strand <lha@it.su.se> + + * test_acquire_cred.c: test gss_add_cred more then once + +2003-05-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.h: if __cplusplus, wrap the extern variable (just to be + safe) and functions in extern "C" { } + +2003-04-30 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.3: more about the des3 mic mess + + * verify_mic.c (verify_mic_des3): always check if the mic is the + correct mic or the mic that old heimdal would have generated + +2003-04-28 Jacques Vidrine <nectar@kth.se> + + * verify_mic.c (verify_mic_des3): If MIC verification fails, + retry using the `old' MIC computation (with zero IV). + +2003-04-26 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: more about difference between comparing IN + and MN + + * gss_acquire_cred.3: more about name type and access control + +2003-04-25 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: document gss_context_time + + * context_time.c: if lifetime of context have expired, set + time_rec to 0 and return GSS_S_CONTEXT_EXPIRED + + * gssapi.3: document [gssapi]correct_des3_mic + [gssapi]broken_des3_mic + + * gss_acquire_cred.3: document gss_krb5_compat_des3_mic + + * compat.c (gss_krb5_compat_des3_mic): enable turning on/off des3 + mic compat + (_gss_DES3_get_mic_compat): handle [gssapi]correct_des3_mic too + + * gssapi.h (gss_krb5_compat_des3_mic): new function, turn on/off + des3 mic compat + (GSS_C_KRB5_COMPAT_DES3_MIC): cpp symbol that exists if + gss_krb5_compat_des3_mic exists + +2003-04-24 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: (libgssapi_la_LDFLAGS): update major + version of gssapi for incompatiblity in 3des getmic support + +2003-04-23 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: test_acquire_cred_LDADD: use libgssapi.la not + ./libgssapi.la (make make -jN work) + +2003-04-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.3: spelling + + * gss_acquire_cred.3: Change .Fd #include <header.h> to .In + header.h, from Thomas Klausner <wiz@netbsd.org> + + +2003-04-06 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: spelling + + * Makefile.am: remove stuff that sneaked in with last commit + + * acquire_cred.c (acquire_initiator_cred): if the requested name + isn't in the ccache, also check keytab. Extact the krbtgt for the + default realm to check how long the credentials will last. + + * add_cred.c (gss_add_cred): don't create a new ccache, just open + the old one; better check if output handle is compatible with new + (copied) handle + + * test_acquire_cred.c: test gss_add_cred too + +2003-04-03 Love Hörnquist Ã…strand <lha@it.su.se> + + * Makefile.am: build test_acquire_cred + + * test_acquire_cred.c: simple gss_acquire_cred test + +2003-04-02 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: s/gssapi/GSS-API/ + +2003-03-19 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: document v1 interface (and that they are + obsolete) + +2003-03-18 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: list supported mechanism and nametypes + +2003-03-16 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_acquire_cred.3: text about gss_display_name + + * Makefile.am (libgssapi_la_LDFLAGS): bump to 3:6:2 + (libgssapi_la_SOURCES): add all new functions + + * gssapi.3: now that we have a functions, uncomment the missing + ones + + * gss_acquire_cred.3: now that we have a functions, uncomment the + missing ones + + * process_context_token.c: implement gss_process_context_token + + * inquire_names_for_mech.c: implement gss_inquire_names_for_mech + + * inquire_mechs_for_name.c: implement gss_inquire_mechs_for_name + + * inquire_cred_by_mech.c: implement gss_inquire_cred_by_mech + + * add_cred.c: implement gss_add_cred + + * acquire_cred.c (gss_acquire_cred): more testing of input + argument, make sure output arguments are ok, since we don't know + the time_rec (for now), set it to time_req + + * export_sec_context.c: send lifetime, also set minor_status + + * get_mic.c: set minor_status + + * import_sec_context.c (gss_import_sec_context): add error + checking, pick up lifetime (if there is no lifetime, use + GSS_C_INDEFINITE) + + * init_sec_context.c: take care to set export value to something + sane before we start so caller will have harmless values in them + if then function fails + + * release_buffer.c (gss_release_buffer): set minor_status + + * wrap.c: make sure minor_status get set + + * verify_mic.c (gss_verify_mic_internal): rename verify_mic to + gss_verify_mic_internal and let it take the type as an argument, + (gss_verify_mic): call gss_verify_mic_internal + set minor_status + + * unwrap.c: set minor_status + + * test_oid_set_member.c (gss_test_oid_set_member): use + gss_oid_equal + + * release_oid_set.c (gss_release_oid_set): set minor_status + + * release_name.c (gss_release_name): set minor_status + + * release_cred.c (gss_release_cred): set minor_status + + * add_oid_set_member.c (gss_add_oid_set_member): set minor_status + + * compare_name.c (gss_compare_name): set minor_status + + * compat.c (check_compat): make sure ret have a defined value + + * context_time.c (gss_context_time): set minor_status + + * copy_ccache.c (gss_krb5_copy_ccache): set minor_status + + * create_emtpy_oid_set.c (gss_create_empty_oid_set): set + minor_status + + * delete_sec_context.c (gss_delete_sec_context): set minor_status + + * display_name.c (gss_display_name): set minor_status + + * display_status.c (gss_display_status): use gss_oid_equal, handle + supplementary errors + + * duplicate_name.c (gss_duplicate_name): set minor_status + + * inquire_context.c (gss_inquire_context): set lifetime_rec now + when we know it, set minor_status + + * inquire_cred.c (gss_inquire_cred): take care to set export value + to something sane before we start so caller will have harmless + values in them if the function fails + + * accept_sec_context.c (gss_accept_sec_context): take care to set + export value to something sane before we start so caller will have + harmless values in them if then function fails, set lifetime from + ticket expiration date + + * indicate_mechs.c (gss_indicate_mechs): use + gss_create_empty_oid_set and gss_add_oid_set_member + + * gssapi.h (gss_ctx_id_t_desc): store the lifetime in the cred, + since there is no ticket transfered in the exported context + + * export_name.c (gss_export_name): export name with + GSS_C_NT_EXPORT_NAME wrapping, not just the principal + + * import_name.c (import_export_name): new function, parses a + GSS_C_NT_EXPORT_NAME + (import_krb5_name): factor out common code of parsing krb5 name + (gss_oid_equal): rename from oid_equal + + * gssapi_locl.h: add prototypes for gss_oid_equal and + gss_verify_mic_internal + + * gssapi.h: comment out the argument names + +2003-03-15 Love Hörnquist Ã…strand <lha@it.su.se> + + * gssapi.3: add LIST OF FUNCTIONS and copyright/license + + * Makefile.am: s/gss_aquire_cred.3/gss_acquire_cred.3/ + + * Makefile.am: man_MANS += gss_aquire_cred.3 + +2003-03-14 Love Hörnquist Ã…strand <lha@it.su.se> + + * gss_aquire_cred.3: the gssapi api manpage + +2003-03-03 Love Hörnquist Ã…strand <lha@it.su.se> + + * inquire_context.c: (gss_inquire_context): rename argument open + to open_context + + * gssapi.h (gss_inquire_context): rename argument open to open_context + +2003-02-27 Love Hörnquist Ã…strand <lha@it.su.se> + + * init_sec_context.c (do_delegation): remove unused variable + subkey + + * gssapi.3: all 0.5.x version had broken token delegation + +2003-02-21 Love Hörnquist Ã…strand <lha@it.su.se> + + * (init_auth): only generate one subkey + +2003-01-27 Love Hörnquist Ã…strand <lha@it.su.se> + + * verify_mic.c (verify_mic_des3): fix 3des verify_mic to conform + to rfc (and mit kerberos), provide backward compat hook + + * get_mic.c (mic_des3): fix 3des get_mic to conform to rfc (and + mit kerberos), provide backward compat hook + + * init_sec_context.c (init_auth): check if we need compat for + older get_mic/verify_mic + + * gssapi_locl.h: add prototype for _gss_DES3_get_mic_compat + + * gssapi.h (more_flags): add COMPAT_OLD_DES3 + + * Makefile.am: add gssapi.3 and compat.c + + * gssapi.3: add gssapi COMPATIBILITY documentation + + * accept_sec_context.c (gss_accept_sec_context): check if we need + compat for older get_mic/verify_mic + + * compat.c: check for compatiblity with other heimdal's 3des + get_mic/verify_mic + +2002-10-31 Johan Danielsson <joda@pdc.kth.se> + + * check return value from gssapi_krb5_init + + * 8003.c (gssapi_krb5_verify_8003_checksum): check size of input + +2002-09-03 Johan Danielsson <joda@pdc.kth.se> + + * wrap.c (wrap_des3): use ETYPE_DES3_CBC_NONE + + * unwrap.c (unwrap_des3): use ETYPE_DES3_CBC_NONE + +2002-09-02 Johan Danielsson <joda@pdc.kth.se> + + * init_sec_context.c: we need to generate a local subkey here + +2002-08-20 Jacques Vidrine <n@nectar.com> + + * acquire_cred.c, inquire_cred.c, release_cred.c: Use default + credential resolution if gss_acquire_cred is called with + GSS_C_NO_NAME. + +2002-06-20 Jacques Vidrine <n@nectar.com> + + * import_name.c: Compare name types by value if pointers do + not match. Reported by: "Douglas E. Engert" <deengert@anl.gov> + +2002-05-20 Jacques Vidrine <n@nectar.com> + + * verify_mic.c (gss_verify_mic), unwrap.c (gss_unwrap): initialize + the qop_state parameter. from Doug Rabson <dfr@nlsystems.com> + +2002-05-09 Jacques Vidrine <n@nectar.com> + + * acquire_cred.c: handle GSS_C_INITIATE/GSS_C_ACCEPT/GSS_C_BOTH + +2002-05-08 Jacques Vidrine <n@nectar.com> + + * acquire_cred.c: initialize gssapi; handle null desired_name + +2002-03-22 Johan Danielsson <joda@pdc.kth.se> + + * Makefile.am: remove non-functional stuff accidentally committed + +2002-03-11 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): bump version to 3:5:2 + * 8003.c (gssapi_krb5_verify_8003_checksum): handle zero channel + bindings + +2001-10-31 Jacques Vidrine <n@nectar.com> + + * get_mic.c (mic_des3): MIC computation using DES3/SHA1 + was bogusly appending the message buffer to the result, + overwriting a heap buffer in the process. + +2001-08-29 Assar Westerlund <assar@sics.se> + + * 8003.c (gssapi_krb5_verify_8003_checksum, + gssapi_krb5_create_8003_checksum): make more consistent by always + returning an gssapi error and setting minor status. update + callers + +2001-08-28 Jacques Vidrine <n@nectar.com> + + * accept_sec_context.c: Create a cache for delegated credentials + when needed. + +2001-08-28 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): set version to 3:4:2 + +2001-08-23 Assar Westerlund <assar@sics.se> + + * *.c: handle minor_status more consistently + + * display_status.c (gss_display_status): handle krb5_get_err_text + failing + +2001-08-15 Johan Danielsson <joda@pdc.kth.se> + + * gssapi_locl.h: fix prototype for gssapi_krb5_init + +2001-08-13 Johan Danielsson <joda@pdc.kth.se> + + * accept_sec_context.c (gsskrb5_register_acceptor_identity): init + context and check return value from kt_resolve + + * init.c: return error code + +2001-07-19 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): update to 3:3:2 + +2001-07-12 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LIBADD): add required library + dependencies + +2001-07-06 Assar Westerlund <assar@sics.se> + + * accept_sec_context.c (gsskrb5_register_acceptor_identity): set + the keytab to be used for gss_acquire_cred too' + +2001-07-03 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): set version to 3:2:2 + +2001-06-18 Assar Westerlund <assar@sics.se> + + * wrap.c: replace gss_krb5_getsomekey with gss_krb5_get_localkey + and gss_krb5_get_remotekey + * verify_mic.c: update krb5_auth_con function names use + gss_krb5_get_remotekey + * unwrap.c: replace gss_krb5_getsomekey with gss_krb5_get_localkey + and gss_krb5_get_remotekey + * gssapi_locl.h (gss_krb5_get_remotekey, gss_krb5_get_localkey): + add prototypes + * get_mic.c: update krb5_auth_con function names. use + gss_krb5_get_localkey + * accept_sec_context.c: update krb5_auth_con function names + +2001-05-17 Assar Westerlund <assar@sics.se> + + * Makefile.am: bump version to 3:1:2 + +2001-05-14 Assar Westerlund <assar@sics.se> + + * address_to_krb5addr.c: adapt to new address functions + +2001-05-11 Assar Westerlund <assar@sics.se> + + * try to return the error string from libkrb5 where applicable + +2001-05-08 Assar Westerlund <assar@sics.se> + + * delete_sec_context.c (gss_delete_sec_context): remember to free + the memory used by the ticket itself. from <tmartin@mirapoint.com> + +2001-05-04 Assar Westerlund <assar@sics.se> + + * gssapi_locl.h: add config.h for completeness + * gssapi.h: remove config.h, this is an installed header file + sys/types.h is not needed either + +2001-03-12 Assar Westerlund <assar@sics.se> + + * acquire_cred.c (gss_acquire_cred): remove memory leaks. from + Jason R Thorpe <thorpej@zembu.com> + +2001-02-18 Assar Westerlund <assar@sics.se> + + * accept_sec_context.c (gss_accept_sec_context): either return + gss_name NULL-ed or set + + * import_name.c: set minor_status in some cases where it was not + done + +2001-02-15 Assar Westerlund <assar@sics.se> + + * wrap.c: use krb5_generate_random_block for the confounders + +2001-01-30 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): bump version to 3:0:2 + * acquire_cred.c, init_sec_context.c, release_cred.c: add support + for getting creds from a keytab, from fvdl@netbsd.org + + * copy_ccache.c: add gss_krb5_copy_ccache + +2001-01-27 Assar Westerlund <assar@sics.se> + + * get_mic.c: cast parameters to des function to non-const pointers + to handle the case where these functions actually take non-const + des_cblock * + +2001-01-09 Assar Westerlund <assar@sics.se> + + * accept_sec_context.c (gss_accept_sec_context): use krb5_rd_cred2 + instead of krb5_rd_cred + +2000-12-11 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): bump to 2:3:1 + +2000-12-08 Assar Westerlund <assar@sics.se> + + * wrap.c (wrap_des3): use the checksum as ivec when encrypting the + sequence number + * unwrap.c (unwrap_des3): use the checksum as ivec when encrypting + the sequence number + * init_sec_context.c (init_auth): always zero fwd_data + +2000-12-06 Johan Danielsson <joda@pdc.kth.se> + + * accept_sec_context.c: de-pointerise auth_context parameter to + krb5_mk_rep + +2000-11-15 Assar Westerlund <assar@sics.se> + + * init_sec_context.c (init_auth): update to new + krb5_build_authenticator + +2000-09-19 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): bump to 2:2:1 + +2000-08-27 Assar Westerlund <assar@sics.se> + + * init_sec_context.c: actually pay attention to `time_req' + * init_sec_context.c: re-organize. leak less memory. + * gssapi_locl.h (gssapi_krb5_encapsulate, gss_krb5_getsomekey): + update prototypes add assert.h + * gssapi.h (GSS_KRB5_CONF_C_QOP_DES, GSS_KRB5_CONF_C_QOP_DES3_KD): + add + * verify_mic.c: re-organize and add 3DES code + * wrap.c: re-organize and add 3DES code + * unwrap.c: re-organize and add 3DES code + * get_mic.c: re-organize and add 3DES code + * encapsulate.c (gssapi_krb5_encapsulate): do not free `in_data', + let the caller do that. fix the callers. + +2000-08-16 Assar Westerlund <assar@sics.se> + + * Makefile.am: bump version to 2:1:1 + +2000-07-29 Assar Westerlund <assar@sics.se> + + * decapsulate.c (gssapi_krb5_verify_header): sanity-check length + +2000-07-25 Johan Danielsson <joda@pdc.kth.se> + + * Makefile.am: bump version to 2:0:1 + +2000-07-22 Assar Westerlund <assar@sics.se> + + * gssapi.h: update OID for GSS_C_NT_HOSTBASED_SERVICE and other + details from rfc2744 + +2000-06-29 Assar Westerlund <assar@sics.se> + + * address_to_krb5addr.c (gss_address_to_krb5addr): actually use + `int' instead of `sa_family_t' for the address family. + +2000-06-21 Assar Westerlund <assar@sics.se> + + * add support for token delegation. From Daniel Kouril + <kouril@ics.muni.cz> and Miroslav Ruda <ruda@ics.muni.cz> + +2000-05-15 Assar Westerlund <assar@sics.se> + + * Makefile.am (libgssapi_la_LDFLAGS): set version to 1:1:1 + +2000-04-12 Assar Westerlund <assar@sics.se> + + * release_oid_set.c (gss_release_oid_set): clear set for + robustness. From GOMBAS Gabor <gombasg@inf.elte.hu> + * release_name.c (gss_release_name): reset input_name for + robustness. From GOMBAS Gabor <gombasg@inf.elte.hu> + * release_buffer.c (gss_release_buffer): set value to NULL to be + more robust. From GOMBAS Gabor <gombasg@inf.elte.hu> + * add_oid_set_member.c (gss_add_oid_set_member): actually check if + the oid is a member first. leave the oid_set unchanged if realloc + fails. + +2000-02-13 Assar Westerlund <assar@sics.se> + + * Makefile.am: set version to 1:0:1 + +2000-02-12 Assar Westerlund <assar@sics.se> + + * gssapi_locl.h: add flags for import/export + * import_sec_context.c (import_sec_context: add flags for what + fields are included. do not include the authenticator for now. + * export_sec_context.c (export_sec_context: add flags for what + fields are included. do not include the authenticator for now. + * accept_sec_context.c (gss_accept_sec_context): set target in + context_handle + +2000-02-11 Assar Westerlund <assar@sics.se> + + * delete_sec_context.c (gss_delete_sec_context): set context to + GSS_C_NO_CONTEXT + + * Makefile.am: add {export,import}_sec_context.c + * export_sec_context.c: new file + * import_sec_context.c: new file + * accept_sec_context.c (gss_accept_sec_context): set trans flag + +2000-02-07 Assar Westerlund <assar@sics.se> + + * Makefile.am: set version to 0:5:0 + +2000-01-26 Assar Westerlund <assar@sics.se> + + * delete_sec_context.c (gss_delete_sec_context): handle a NULL + output_token + + * wrap.c: update to pseudo-standard APIs for md4,md5,sha. some + changes to libdes calls to make them more portable. + * verify_mic.c: update to pseudo-standard APIs for md4,md5,sha. + some changes to libdes calls to make them more portable. + * unwrap.c: update to pseudo-standard APIs for md4,md5,sha. some + changes to libdes calls to make them more portable. + * get_mic.c: update to pseudo-standard APIs for md4,md5,sha. some + changes to libdes calls to make them more portable. + * 8003.c: update to pseudo-standard APIs for md4,md5,sha. + +2000-01-06 Assar Westerlund <assar@sics.se> + + * Makefile.am: set version to 0:4:0 + +1999-12-26 Assar Westerlund <assar@sics.se> + + * accept_sec_context.c (gss_accept_sec_context): always set + `output_token' + * init_sec_context.c (init_auth): always initialize `output_token' + * delete_sec_context.c (gss_delete_sec_context): always set + `output_token' + +1999-12-06 Assar Westerlund <assar@sics.se> + + * Makefile.am: bump version to 0:3:0 + +1999-10-20 Assar Westerlund <assar@sics.se> + + * Makefile.am: set version to 0:2:0 + +1999-09-21 Assar Westerlund <assar@sics.se> + + * init_sec_context.c (gss_init_sec_context): initialize `ticket' + + * gssapi.h (gss_ctx_id_t_desc): add ticket in here. ick. + + * delete_sec_context.c (gss_delete_sec_context): free ticket + + * accept_sec_context.c (gss_accept_sec_context): stove away + `krb5_ticket' in context so that ugly programs such as + gss_nt_server can get at it. uck. + +1999-09-20 Johan Danielsson <joda@pdc.kth.se> + + * accept_sec_context.c: set minor_status + +1999-08-04 Assar Westerlund <assar@sics.se> + + * display_status.c (calling_error, routine_error): right shift the + code to make it possible to index into the arrays + +1999-07-28 Assar Westerlund <assar@sics.se> + + * gssapi.h (GSS_C_AF_INET6): add + + * import_name.c (import_hostbased_name): set minor_status + +1999-07-26 Assar Westerlund <assar@sics.se> + + * Makefile.am: set version to 0:1:0 + +Wed Apr 7 14:05:15 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * display_status.c: set minor_status + + * init_sec_context.c: set minor_status + + * lib/gssapi/init.c: remove donep (check gssapi_krb5_context + directly) + diff --git a/third_party/heimdal/lib/gssapi/Makefile.am b/third_party/heimdal/lib/gssapi/Makefile.am new file mode 100644 index 0000000..a69ebff --- /dev/null +++ b/third_party/heimdal/lib/gssapi/Makefile.am @@ -0,0 +1,468 @@ +# $Id$ + +include $(top_srcdir)/Makefile.am.common + +WFLAGS += $(WFLAGS_ENUM_CONV) + +AUTOMAKE_OPTIONS = subdir-objects + +AM_CPPFLAGS += \ + -I$(top_srcdir)/lib \ + -I$(srcdir)/../krb5 \ + -I$(srcdir) \ + -I$(srcdir)/gssapi \ + -I$(srcdir)/mech \ + -I$(srcdir)/ntlm \ + -I$(srcdir)/krb5 \ + -I$(srcdir)/spnego \ + -I$(srcdir)/sanon \ + $(INCLUDE_libintl) + +lib_LTLIBRARIES = libgssapi.la test_negoex_mech.la + +krb5src = \ + krb5/8003.c \ + krb5/accept_sec_context.c \ + krb5/acquire_cred.c \ + krb5/add_cred.c \ + krb5/address_to_krb5addr.c \ + krb5/aeap.c \ + krb5/arcfour.c \ + krb5/canonicalize_name.c \ + krb5/creds.c \ + krb5/ccache_name.c \ + krb5/cfx.c \ + krb5/cfx.h \ + krb5/compare_name.c \ + krb5/compat.c \ + krb5/context_time.c \ + krb5/copy_ccache.c \ + krb5/decapsulate.c \ + krb5/delete_sec_context.c \ + krb5/display_name.c \ + krb5/display_status.c \ + krb5/duplicate_cred.c \ + krb5/duplicate_name.c \ + krb5/encapsulate.c \ + krb5/export_name.c \ + krb5/export_sec_context.c \ + krb5/external.c \ + krb5/get_mic.c \ + krb5/gsskrb5_locl.h \ + $(srcdir)/krb5/gsskrb5-private.h \ + krb5/import_name.c \ + krb5/import_sec_context.c \ + krb5/indicate_mechs.c \ + krb5/init.c \ + krb5/init_sec_context.c \ + krb5/inquire_context.c \ + krb5/inquire_cred.c \ + krb5/inquire_cred_by_mech.c \ + krb5/inquire_cred_by_oid.c \ + krb5/inquire_mechs_for_name.c \ + krb5/inquire_names_for_mech.c \ + krb5/inquire_sec_context_by_oid.c \ + krb5/name_attrs.c \ + krb5/pname_to_uid.c \ + krb5/process_context_token.c \ + krb5/prf.c \ + krb5/release_buffer.c \ + krb5/release_cred.c \ + krb5/release_name.c \ + krb5/sequence.c \ + krb5/store_cred.c \ + krb5/set_cred_option.c \ + krb5/set_sec_context_option.c \ + krb5/ticket_flags.c \ + krb5/unwrap.c \ + krb5/authorize_localname.c \ + krb5/verify_mic.c \ + krb5/wrap.c + +mechsrc = \ + mech/context.h \ + mech/context.c \ + mech/cred.h \ + mech/cred.c \ + mech/compat.h \ + mech/doxygen.c \ + mech/gss_accept_sec_context.c \ + mech/gss_acquire_cred.c \ + mech/gss_acquire_cred_from.c \ + mech/gss_acquire_cred_impersonate_name.c \ + mech/gss_acquire_cred_with_password.c \ + mech/gss_add_cred.c \ + mech/gss_add_cred_from.c \ + mech/gss_add_cred_with_password.c \ + mech/gss_add_oid_set_member.c \ + mech/gss_aeap.c \ + mech/gss_buffer_set.c \ + mech/gss_canonicalize_name.c \ + mech/gss_compare_name.c \ + mech/gss_context_time.c \ + mech/gss_create_empty_oid_set.c \ + mech/gss_cred.c \ + mech/gss_decapsulate_token.c \ + mech/gss_delete_name_attribute.c \ + mech/gss_delete_sec_context.c \ + mech/gss_destroy_cred.c \ + mech/gss_display_name.c \ + mech/gss_display_name_ext.c \ + mech/gss_display_status.c \ + mech/gss_duplicate_cred.c \ + mech/gss_duplicate_name.c \ + mech/gss_duplicate_oid.c \ + mech/gss_duplicate_oid_set.c \ + mech/gss_encapsulate_token.c \ + mech/gss_export_name.c \ + mech/gss_export_name_composite.c \ + mech/gss_export_sec_context.c \ + mech/gss_get_mic.c \ + mech/gss_get_neg_mechs.c \ + mech/gss_get_name_attribute.c \ + mech/gss_import_name.c \ + mech/gss_import_sec_context.c \ + mech/gss_indicate_mechs.c \ + mech/gss_init_sec_context.c \ + mech/gss_inquire_context.c \ + mech/gss_inquire_cred.c \ + mech/gss_inquire_cred_by_mech.c \ + mech/gss_inquire_cred_by_oid.c \ + mech/gss_inquire_mechs_for_name.c \ + mech/gss_inquire_name.c \ + mech/gss_inquire_names_for_mech.c \ + mech/gss_krb5.c \ + mech/gss_mech_switch.c \ + mech/gss_mo.c \ + mech/gss_names.c \ + mech/gss_oid.c \ + mech/gss_oid_equal.c \ + mech/gss_oid_to_str.c \ + mech/gss_pname_to_uid.c \ + mech/gss_process_context_token.c \ + mech/gss_pseudo_random.c \ + mech/gss_release_buffer.c \ + mech/gss_release_cred.c \ + mech/gss_release_name.c \ + mech/gss_release_oid.c \ + mech/gss_release_oid_set.c \ + mech/gss_rfc4121.c \ + mech/gss_seal.c \ + mech/gss_set_cred_option.c \ + mech/gss_set_name_attribute.c \ + mech/gss_set_neg_mechs.c \ + mech/gss_set_sec_context_option.c \ + mech/gss_sign.c \ + mech/gss_store_cred.c \ + mech/gss_store_cred_into.c \ + mech/gss_test_oid_set_member.c \ + mech/gss_unseal.c \ + mech/gss_unwrap.c \ + mech/gss_authorize_localname.c \ + mech/gss_utils.c \ + mech/gss_verify.c \ + mech/gss_verify_mic.c \ + mech/gss_wrap.c \ + mech/gss_wrap_size_limit.c \ + mech/gss_inquire_sec_context_by_oid.c \ + mech/gssspi_exchange_meta_data.c \ + mech/gssspi_query_mechanism_info.c \ + mech/gssspi_query_meta_data.c \ + mech/mech_switch.h \ + mech/mech_locl.h \ + mech/name.h \ + mech/utils.h + +spnegosrc = \ + spnego/accept_sec_context.c \ + spnego/compat.c \ + spnego/context_storage.c \ + spnego/context_stubs.c \ + spnego/external.c \ + spnego/init_sec_context.c \ + spnego/negoex_ctx.c \ + spnego/negoex_util.c \ + spnego/spnego_locl.h \ + spnego/negoex_locl.h \ + $(srcdir)/spnego/spnego-private.h + +ntlmsrc = \ + ntlm/accept_sec_context.c \ + ntlm/acquire_cred.c \ + ntlm/add_cred.c \ + ntlm/canonicalize_name.c \ + ntlm/compare_name.c \ + ntlm/context_time.c \ + ntlm/creds.c \ + ntlm/crypto.c \ + ntlm/delete_sec_context.c \ + ntlm/display_name.c \ + ntlm/display_status.c \ + ntlm/duplicate_name.c \ + ntlm/export_name.c \ + ntlm/export_sec_context.c \ + ntlm/external.c \ + ntlm/ntlm.h \ + ntlm/import_name.c \ + ntlm/import_sec_context.c \ + ntlm/indicate_mechs.c \ + ntlm/init_sec_context.c \ + ntlm/inquire_context.c \ + ntlm/inquire_cred_by_mech.c \ + ntlm/inquire_mechs_for_name.c \ + ntlm/inquire_names_for_mech.c \ + ntlm/inquire_sec_context_by_oid.c \ + ntlm/iter_cred.c \ + ntlm/process_context_token.c \ + ntlm/release_cred.c \ + ntlm/release_name.c \ + ntlm/set_sec_context_option.c \ + ntlm/kdc.c + +$(srcdir)/ntlm/ntlm-private.h: $(ntlmsrc) + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p ntlm/ntlm-private.h $(ntlmsrc) || rm -f ntlm/ntlm-private.h + +sanonsrc = \ + sanon/accept_sec_context.c \ + sanon/acquire_cred.c \ + sanon/add_cred.c \ + sanon/canonicalize_name.c \ + sanon/compare_name.c \ + sanon/context_time.c \ + sanon/crypto.c \ + sanon/delete_sec_context.c \ + sanon/display_name.c \ + sanon/display_status.c \ + sanon/duplicate_cred.c \ + sanon/duplicate_name.c \ + sanon/export_name.c \ + sanon/export_cred.c \ + sanon/export_sec_context.c \ + sanon/external.c \ + sanon/import_cred.c \ + sanon/import_name.c \ + sanon/import_sec_context.c \ + sanon/init_sec_context.c \ + sanon/inquire_context.c \ + sanon/inquire_cred.c \ + sanon/inquire_cred_by_mech.c \ + sanon/inquire_mechs_for_name.c \ + sanon/inquire_names_for_mech.c \ + sanon/inquire_sec_context_by_oid.c \ + sanon/negoex.c \ + sanon/process_context_token.c \ + sanon/release_cred.c \ + sanon/release_name.c \ + sanon/sanon_locl.h \ + sanon/sanon-private.h + +dist_libgssapi_la_SOURCES = \ + $(krb5src) \ + $(mechsrc) \ + $(ntlmsrc) \ + $(spnegosrc) \ + $(sanonsrc) + +nodist_libgssapi_la_SOURCES = \ + gkrb5_err.c \ + gkrb5_err.h \ + negoex_err.c \ + negoex_err.h \ + $(BUILT_SOURCES) + +libgssapi_la_DEPENDENCIES = version-script.map + +libgssapi_la_LDFLAGS = -version-info 3:0:0 + +if versionscript +libgssapi_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +endif + +libgssapi_la_LIBADD = \ + $(top_builddir)/lib/ntlm/libheimntlm.la \ + $(top_builddir)/lib/krb5/libkrb5.la \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_com_err) \ + $(LIB_hcrypto) \ + $(LIBADD_roken) + +man_MANS = gssapi.3 gss_acquire_cred.3 mech/mech.5 gss-token.1 + +include_HEADERS = gssapi.h +noinst_HEADERS = \ + gssapi_asn1.h \ + gssapi_mech.h \ + $(srcdir)/ntlm/ntlm-private.h \ + $(srcdir)/spnego/spnego-private.h \ + $(srcdir)/sanon/sanon-private.h \ + $(srcdir)/krb5/gsskrb5-private.h + +nobase_include_HEADERS = \ + gssapi/gssapi.h \ + gssapi/gssapi_krb5.h \ + gssapi/gssapi_ntlm.h \ + gssapi/gssapi_oid.h \ + gssapi/gssapi_spnego.h + +gssapidir = $(includedir)/gssapi +nodist_gssapi_HEADERS = gkrb5_err.h negoex_err.h + +gssapi_files = \ + asn1_GSSAPIContextToken.c + +spnego_files = \ + asn1_ContextFlags.c \ + asn1_MechType.c \ + asn1_MechTypeList.c \ + asn1_NegHints.c \ + asn1_NegStateEnum.c \ + asn1_NegTokenInit.c \ + asn1_NegTokenInit2.c \ + asn1_NegTokenResp.c \ + asn1_NegotiationToken.c \ + asn1_NegotiationToken2.c + +BUILTHEADERS = \ + $(srcdir)/krb5/gsskrb5-private.h \ + $(srcdir)/spnego/spnego-private.h \ + $(srcdir)/sanon/sanon-private.h \ + $(srcdir)/ntlm/ntlm-private.h + +$(libgssapi_la_OBJECTS): $(BUILTHEADERS) +$(test_context_OBJECTS): $(BUILTHEADERS) + +$(libgssapi_la_OBJECTS): $(srcdir)/version-script.map + +BUILT_SOURCES = $(spnego_files) $(gssapi_files) + +$(libgssapi_la_OBJECTS): gkrb5_err.h negoex_err.h +gkrb5_err.h: $(srcdir)/krb5/gkrb5_err.et +negoex_err.h: $(srcdir)/spnego/negoex_err.et + +CLEANFILES = $(BUILT_SOURCES) \ + gkrb5_err.[ch] negoex_err.[ch] \ + $(spnego_files) spnego_asn1*.h* spnego_asn1_files spnego_asn1-template.[cx] \ + $(gssapi_files) gssapi_asn1*.h* gssapi_asn1_files gssapi_asn1-template.[cx] \ + gss-commands.h gss-commands.c \ + gssapi_asn1.json gssapi_asn1_oids.c gssapi_asn1_syms.c \ + spnego_asn1.json spnego_asn1_oids.c spnego_asn1_syms.c + +$(spnego_files) spnego_asn1.h spnego_asn1-priv.h: spnego_asn1_files + for genfile in '$(spnego_files)'; do \ + $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \ + done + +$(gssapi_files) gssapi_asn1.h gssapi_asn1-priv.h: gssapi_asn1_files + for genfile in '$(gssapi_files)'; do \ + $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \ + done + +spnego_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/spnego/spnego.asn1 $(srcdir)/spnego/spnego.opt + $(ASN1_COMPILE) --option-file=$(srcdir)/spnego/spnego.opt $(srcdir)/spnego/spnego.asn1 spnego_asn1 + @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat spnego_asn1_files) + +gssapi_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/mech/gssapi.asn1 + $(ASN1_COMPILE) $(srcdir)/mech/gssapi.asn1 gssapi_asn1 + @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat gssapi_asn1_files) + +$(srcdir)/krb5/gsskrb5-private.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p krb5/gsskrb5-private.h $(krb5src) || rm -f krb5/gsskrb5-private.h + +$(srcdir)/spnego/spnego-private.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p spnego/spnego-private.h $(spnegosrc) || rm -f spnego/spnego-private.h + +$(srcdir)/sanon/sanon-private.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p sanon/sanon-private.h $(sanonsrc) || rm -f sanon/sanon-private.h + +TESTS = test_oid test_names test_cfx +# test_sequence + +test_cfx_SOURCES = krb5/test_cfx.c + +check_PROGRAMS = test_acquire_cred $(TESTS) + +bin_PROGRAMS = gsstool gss-token +noinst_PROGRAMS = test_cred test_kcred test_context test_ntlm test_add_store_cred + +test_context_SOURCES = test_context.c test_common.c test_common.h +test_ntlm_SOURCES = test_ntlm.c test_common.c test_common.h +test_acquire_cred_SOURCES = test_acquire_cred.c test_common.c test_common.h + +test_add_store_cred_SOURCES = test_add_store_cred.c + +test_ntlm_LDADD = \ + $(top_builddir)/lib/ntlm/libheimntlm.la \ + $(LDADD) + +LDADD = libgssapi.la \ + $(top_builddir)/lib/krb5/libkrb5.la \ + $(LIB_roken) + +test_names_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la +test_context_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la $(top_builddir)/lib/wind/libwind.la + +# gss + +dist_gsstool_SOURCES = gsstool.c +nodist_gsstool_SOURCES = gss-commands.c gss-commands.h +dist_gss_token_SOURCES = gss-token.c + +gsstool_LDADD = libgssapi.la \ + $(top_builddir)/lib/sl/libsl.la \ + $(top_builddir)/lib/krb5/libkrb5.la \ + $(LIB_readline) \ + $(LIB_roken) + +gss_token_LDADD = libgssapi.la \ + $(top_builddir)/lib/krb5/libkrb5.la \ + $(LIB_roken) + +gss-commands.c gss-commands.h: gss-commands.in + $(SLC) $(srcdir)/gss-commands.in + +$(gsstool_OBJECTS): gss-commands.h + +EXTRA_DIST = \ + NTMakefile \ + libgssapi-version.rc \ + libgssapi-exports.def \ + $(man_MANS) \ + gen-oid.pl \ + gssapi/gssapi_netlogon.h \ + krb5/test_acquire_cred.c \ + krb5/test_cred.c \ + krb5/test_kcred.c \ + krb5/test_oid.c \ + oid.txt \ + krb5/gkrb5_err.et \ + mech/gssapi.asn1 \ + spnego/spnego.asn1 \ + spnego/spnego.opt \ + spnego/negoex_err.et \ + test_negoex_mech.c \ + version-script.map \ + gss-commands.in + +$(libgssapi_la_OBJECTS): gkrb5_err.h gssapi_asn1.h gssapi_asn1-priv.h +$(libgssapi_la_OBJECTS): spnego_asn1.h spnego_asn1-priv.h +$(libgssapi_la_OBJECTS): $(srcdir)/gssapi/gssapi_oid.h + +gkrb5_err.h gkrb5_err.c: $(srcdir)/krb5/gkrb5_err.et + $(COMPILE_ET) $(srcdir)/krb5/gkrb5_err.et + +negoex_err.h negoex_err.c: $(srcdir)/spnego/negoex_err.et + $(COMPILE_ET) $(srcdir)/spnego/negoex_err.et + +$(srcdir)/gssapi/gssapi_oid.h $(srcdir)/mech/gss_oid.c: + perl $(srcdir)/gen-oid.pl -b base -h $(srcdir)/oid.txt > $(srcdir)/gssapi/gssapi_oid.h + perl $(srcdir)/gen-oid.pl -b base $(srcdir)/oid.txt > $(srcdir)/mech/gss_oid.c + +# +# NegoEx test mechanism, uses decode_GSSAPIContextToken +# + +test_negoex_mech_la_SOURCES = test_negoex_mech.c $(gssapi_files) +test_negoex_mech_la_LDFLAGS = -module +test_negoex_mech_la_LIBADD = \ + $(top_builddir)/lib/asn1/libasn1.la \ + libgssapi.la diff --git a/third_party/heimdal/lib/gssapi/NTMakefile b/third_party/heimdal/lib/gssapi/NTMakefile new file mode 100644 index 0000000..ffba9d5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/NTMakefile @@ -0,0 +1,747 @@ +######################################################################## +# +# Copyright (c) 2009-2011 Secure Endpoints Inc. +# Copyright (c) 2018 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +RELDIR=lib\gssapi + +intcflags=-DASN1_LIB + +!include ../../windows/NTMakefile.w32 + +krb5src = \ + krb5/8003.c \ + krb5/accept_sec_context.c \ + krb5/acquire_cred.c \ + krb5/add_cred.c \ + krb5/address_to_krb5addr.c \ + krb5/aeap.c \ + krb5/arcfour.c \ + krb5/authorize_localname.c \ + krb5/canonicalize_name.c \ + krb5/creds.c \ + krb5/ccache_name.c \ + krb5/cfx.c \ + krb5/cfx.h \ + krb5/compare_name.c \ + krb5/compat.c \ + krb5/context_time.c \ + krb5/copy_ccache.c \ + krb5/decapsulate.c \ + krb5/delete_sec_context.c \ + krb5/display_name.c \ + krb5/display_status.c \ + krb5/duplicate_name.c \ + krb5/duplicate_cred.c \ + krb5/encapsulate.c \ + krb5/export_name.c \ + krb5/export_sec_context.c \ + krb5/external.c \ + krb5/get_mic.c \ + krb5/gsskrb5_locl.h \ + krb5/import_name.c \ + krb5/import_sec_context.c \ + krb5/indicate_mechs.c \ + krb5/init.c \ + krb5/init_sec_context.c \ + krb5/inquire_context.c \ + krb5/inquire_cred.c \ + krb5/inquire_cred_by_mech.c \ + krb5/inquire_cred_by_oid.c \ + krb5/inquire_mechs_for_name.c \ + krb5/inquire_names_for_mech.c \ + krb5/inquire_sec_context_by_oid.c \ + krb5/name_attrs.c \ + krb5/pname_to_uid.c \ + krb5/process_context_token.c \ + krb5/prf.c \ + krb5/release_buffer.c \ + krb5/release_cred.c \ + krb5/release_name.c \ + krb5/sequence.c \ + krb5/store_cred.c \ + krb5/set_cred_option.c \ + krb5/set_sec_context_option.c \ + krb5/ticket_flags.c \ + krb5/unwrap.c \ + krb5/verify_mic.c \ + krb5/wrap.c + +mechsrc = \ + mech/context.h \ + mech/context.c \ + mech/cred.h \ + mech/cred.c \ + mech/gss_accept_sec_context.c \ + mech/gss_acquire_cred.c \ + mech/gss_acquire_cred_from.c \ + mech/gss_acquire_cred_impersonate_name.c \ + mech/gss_acquire_cred_with_password.c \ + mech/gss_add_cred.c \ + mech/gss_add_cred_from.c \ + mech/gss_add_cred_with_password.c \ + mech/gss_add_oid_set_member.c \ + mech/gss_aeap.c \ + mech/gss_authorize_localname.c \ + mech/gss_buffer_set.c \ + mech/gss_canonicalize_name.c \ + mech/gss_compare_name.c \ + mech/gss_context_time.c \ + mech/gss_create_empty_oid_set.c \ + mech/gss_cred.c \ + mech/gss_decapsulate_token.c \ + mech/gss_delete_name_attribute.c \ + mech/gss_delete_sec_context.c \ + mech/gss_destroy_cred.c \ + mech/gss_display_name.c \ + mech/gss_display_name_ext.c \ + mech/gss_display_status.c \ + mech/gss_duplicate_name.c \ + mech/gss_duplicate_cred.c \ + mech/gss_duplicate_oid.c \ + mech/gss_duplicate_oid_set.c \ + mech/gss_encapsulate_token.c \ + mech/gss_export_name.c \ + mech/gss_export_name_composite.c \ + mech/gss_export_sec_context.c \ + mech/gss_get_mic.c \ + mech/gss_get_neg_mechs.c \ + mech/gss_get_name_attribute.c \ + mech/gss_import_name.c \ + mech/gss_import_sec_context.c \ + mech/gss_indicate_mechs.c \ + mech/gss_init_sec_context.c \ + mech/gss_inquire_context.c \ + mech/gss_inquire_cred.c \ + mech/gss_inquire_cred_by_mech.c \ + mech/gss_inquire_cred_by_oid.c \ + mech/gss_inquire_mechs_for_name.c \ + mech/gss_inquire_name.c \ + mech/gss_inquire_names_for_mech.c \ + mech/gss_krb5.c \ + mech/gss_mech_switch.c \ + mech/gss_mo.c \ + mech/gss_names.c \ + mech/gss_oid.c \ + mech/gss_oid_equal.c \ + mech/gss_oid_to_str.c \ + mech/gss_pname_to_uid.c \ + mech/gss_process_context_token.c \ + mech/gss_pseudo_random.c \ + mech/gss_release_buffer.c \ + mech/gss_release_cred.c \ + mech/gss_release_name.c \ + mech/gss_release_oid.c \ + mech/gss_release_oid_set.c \ + mech/gss_rfc4121.c \ + mech/gss_seal.c \ + mech/gss_set_cred_option.c \ + mech/gss_set_name_attribute.c \ + mech/gss_set_neg_mechs.c \ + mech/gss_set_sec_context_option.c \ + mech/gss_sign.c \ + mech/gss_store_cred.c \ + mech/gss_store_cred_into.c \ + mech/gss_test_oid_set_member.c \ + mech/gss_unseal.c \ + mech/gss_unwrap.c \ + mech/gss_utils.c \ + mech/gss_verify.c \ + mech/gss_verify_mic.c \ + mech/gss_wrap.c \ + mech/gss_wrap_size_limit.c \ + mech/gss_inquire_sec_context_by_oid.c \ + mech/gssspi_exchange_meta_data.c \ + mech/gssspi_query_mechanism_info.c \ + mech/gssspi_query_meta_data.c \ + mech/mech_switch.h \ + mech/mech_locl.h \ + mech/name.h \ + mech/utils.h + +spnegosrc = \ + spnego/accept_sec_context.c \ + spnego/compat.c \ + spnego/context_storage.c \ + spnego/context_stubs.c \ + spnego/external.c \ + spnego/init_sec_context.c \ + spnego/negoex_ctx.c \ + spnego/negoex_util.c \ + spnego/spnego_locl.h \ + spnego/negoex_locl.h + +ntlmsrc = \ + ntlm/accept_sec_context.c \ + ntlm/acquire_cred.c \ + ntlm/add_cred.c \ + ntlm/canonicalize_name.c \ + ntlm/compare_name.c \ + ntlm/context_time.c \ + ntlm/creds.c \ + ntlm/crypto.c \ + ntlm/delete_sec_context.c \ + ntlm/display_name.c \ + ntlm/display_status.c \ + ntlm/duplicate_name.c \ + ntlm/duplicate_cred.c \ + ntlm/export_name.c \ + ntlm/export_sec_context.c \ + ntlm/external.c \ + ntlm/ntlm.h \ + ntlm/import_name.c \ + ntlm/import_sec_context.c \ + ntlm/indicate_mechs.c \ + ntlm/init_sec_context.c \ + ntlm/inquire_context.c \ + ntlm/inquire_cred_by_mech.c \ + ntlm/inquire_mechs_for_name.c \ + ntlm/inquire_names_for_mech.c \ + ntlm/inquire_sec_context_by_oid.c \ + ntlm/iter_cred.c \ + ntlm/process_context_token.c \ + ntlm/release_cred.c \ + ntlm/release_name.c \ + ntlm/set_sec_context_option.c \ + ntlm/kdc.c + +sanonsrc = \ + sanon/accept_sec_context.c \ + sanon/acquire_cred.c \ + sanon/add_cred.c \ + sanon/canonicalize_name.c \ + sanon/compare_name.c \ + sanon/context_time.c \ + sanon/crypto.c \ + sanon/delete_sec_context.c \ + sanon/display_name.c \ + sanon/display_status.c \ + sanon/duplicate_cred.c \ + sanon/duplicate_name.c \ + sanon/export_cred.c \ + sanon/export_name.c \ + sanon/export_sec_context.c \ + sanon/external.c \ + sanon/import_cred.c \ + sanon/import_name.c \ + sanon/import_sec_context.c \ + sanon/init_sec_context.c \ + sanon/inquire_context.c \ + sanon/inquire_cred.c \ + sanon/inquire_cred_by_mech.c \ + sanon/inquire_mechs_for_name.c \ + sanon/inquire_names_for_mech.c \ + sanon/inquire_sec_context_by_oid.c \ + sanon/negoex.c \ + sanon/process_context_token.c \ + sanon/release_cred.c \ + sanon/release_name.c + +$(OBJ)\ntlm\ntlm-private.h: $(ntlmsrc) + $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(ntlmsrc) + +$(OBJ)\krb5\gsskrb5-private.h: $(krb5src) + $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(krb5src) + +$(OBJ)\spnego\spnego-private.h: $(spnegosrc) + $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(spnegosrc) + +$(OBJ)\sanon\sanon-private.h: $(sanonsrc) + $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(sanonsrc) + +$(OBJ)\gssapi\asn1_gssapi_asn1.c $(OBJ)\gssapi\gssapi_asn1.h $(OBJ)\gssapi\gssapi_asn1-priv.h: \ +$(BINDIR)\asn1_compile.exe mech\gssapi.asn1 + cd $(OBJ)\gssapi + $(BINDIR)\asn1_compile.exe --one-code-file $(SRCDIR)\mech\gssapi.asn1 gssapi_asn1 \ + || ( $(RM) $(OBJ)\gssapi\gssapi_asn1.h ; exit /b 1 ) + cd $(SRCDIR) + +$(OBJ)\spnego\asn1_spnego_asn1.c $(OBJ)\spnego\spnego_asn1.h $(OBJ)\spnego\spnego_asn1-priv.h: \ +$(BINDIR)\asn1_compile.exe spnego\spnego.asn1 + cd $(OBJ)\spnego + $(BINDIR)\asn1_compile --one-code-file --sequence=MechTypeList \ + $(SRCDIR)\spnego\spnego.asn1 spnego_asn1 \ + || ( $(RM) $(OBJ)\spnego\spnego_asn1.h ; exit /b 1 ) + cd $(SRCDIR) + +$(OBJ)\gkrb5_err.c $(OBJ)\gkrb5_err.h: krb5\gkrb5_err.et + cd $(OBJ) + $(BINDIR)\compile_et.exe $(SRCDIR)\krb5\gkrb5_err.et + cd $(SRCDIR) + +$(OBJ)\negoex_err.c $(OBJ)\negoex_err.h: spnego\negoex_err.et + cd $(OBJ) + $(BINDIR)\compile_et.exe $(SRCDIR)\spnego\negoex_err.et + cd $(SRCDIR) + +INCFILES= \ + $(INCDIR)\gssapi.h \ + $(INCDIR)\gssapi\gssapi.h \ + $(INCDIR)\gssapi\gssapi_krb5.h \ + $(INCDIR)\gssapi\gssapi_oid.h \ + $(INCDIR)\gssapi\gssapi_ntlm.h \ + $(INCDIR)\gssapi\gssapi_spnego.h \ + $(INCDIR)\gssapi\gkrb5_err.h \ + $(OBJ)\ntlm\ntlm-private.h \ + $(OBJ)\spnego\spnego-private.h \ + $(OBJ)\sanon\sanon-private.h \ + $(OBJ)\krb5\gsskrb5-private.h \ + $(OBJ)\gkrb5_err.h \ + $(OBJ)\negoex_err.h \ + $(OBJ)\gssapi\gssapi_asn1.h \ + $(OBJ)\gssapi\gssapi_asn1-priv.h \ + $(OBJ)\spnego\spnego_asn1.h \ + $(OBJ)\spnego\spnego_asn1-priv.h + +all:: $(INCFILES) + +libgssapi_OBJs = \ + $(OBJ)\krb5/8003.obj \ + $(OBJ)\krb5/accept_sec_context.obj \ + $(OBJ)\krb5/acquire_cred.obj \ + $(OBJ)\krb5/add_cred.obj \ + $(OBJ)\krb5/address_to_krb5addr.obj \ + $(OBJ)\krb5/authorize_localname.obj \ + $(OBJ)\krb5/aeap.obj \ + $(OBJ)\krb5/arcfour.obj \ + $(OBJ)\krb5/canonicalize_name.obj \ + $(OBJ)\krb5/creds.obj \ + $(OBJ)\krb5/ccache_name.obj \ + $(OBJ)\krb5/cfx.obj \ + $(OBJ)\krb5/compare_name.obj \ + $(OBJ)\krb5/compat.obj \ + $(OBJ)\krb5/context_time.obj \ + $(OBJ)\krb5/copy_ccache.obj \ + $(OBJ)\krb5/decapsulate.obj \ + $(OBJ)\krb5/delete_sec_context.obj \ + $(OBJ)\krb5/display_name.obj \ + $(OBJ)\krb5/display_status.obj \ + $(OBJ)\krb5/duplicate_cred.obj \ + $(OBJ)\krb5/duplicate_name.obj \ + $(OBJ)\krb5/encapsulate.obj \ + $(OBJ)\krb5/export_name.obj \ + $(OBJ)\krb5/export_sec_context.obj \ + $(OBJ)\krb5/external.obj \ + $(OBJ)\krb5/get_mic.obj \ + $(OBJ)\krb5/import_name.obj \ + $(OBJ)\krb5/import_sec_context.obj \ + $(OBJ)\krb5/indicate_mechs.obj \ + $(OBJ)\krb5/init.obj \ + $(OBJ)\krb5/init_sec_context.obj \ + $(OBJ)\krb5/inquire_context.obj \ + $(OBJ)\krb5/inquire_cred.obj \ + $(OBJ)\krb5/inquire_cred_by_mech.obj \ + $(OBJ)\krb5/inquire_cred_by_oid.obj \ + $(OBJ)\krb5/inquire_mechs_for_name.obj \ + $(OBJ)\krb5/inquire_names_for_mech.obj \ + $(OBJ)\krb5/inquire_sec_context_by_oid.obj \ + $(OBJ)\krb5/name_attrs.obj \ + $(OBJ)\krb5/pname_to_uid.obj \ + $(OBJ)\krb5/process_context_token.obj \ + $(OBJ)\krb5/prf.obj \ + $(OBJ)\krb5/release_buffer.obj \ + $(OBJ)\krb5/release_cred.obj \ + $(OBJ)\krb5/release_name.obj \ + $(OBJ)\krb5/sequence.obj \ + $(OBJ)\krb5/store_cred.obj \ + $(OBJ)\krb5/set_cred_option.obj \ + $(OBJ)\krb5/set_sec_context_option.obj \ + $(OBJ)\krb5/ticket_flags.obj \ + $(OBJ)\krb5/unwrap.obj \ + $(OBJ)\krb5/verify_mic.obj \ + $(OBJ)\krb5/wrap.obj \ + $(OBJ)\mech/context.obj \ + $(OBJ)\mech/cred.obj \ + $(OBJ)\mech/gss_accept_sec_context.obj \ + $(OBJ)\mech/gss_acquire_cred.obj \ + $(OBJ)\mech/gss_acquire_cred_from.obj \ + $(OBJ)\mech/gss_acquire_cred_impersonate_name.obj \ + $(OBJ)\mech/gss_acquire_cred_with_password.obj \ + $(OBJ)\mech/gss_add_cred.obj \ + $(OBJ)\mech/gss_add_cred_from.obj \ + $(OBJ)\mech/gss_add_cred_with_password.obj \ + $(OBJ)\mech/gss_add_oid_set_member.obj \ + $(OBJ)\mech/gss_aeap.obj \ + $(OBJ)\mech/gss_authorize_localname.obj \ + $(OBJ)\mech/gss_buffer_set.obj \ + $(OBJ)\mech/gss_canonicalize_name.obj \ + $(OBJ)\mech/gss_compare_name.obj \ + $(OBJ)\mech/gss_context_time.obj \ + $(OBJ)\mech/gss_create_empty_oid_set.obj \ + $(OBJ)\mech/gss_cred.obj \ + $(OBJ)\mech/gss_decapsulate_token.obj \ + $(OBJ)\mech/gss_delete_name_attribute.obj \ + $(OBJ)\mech/gss_delete_sec_context.obj \ + $(OBJ)\mech/gss_destroy_cred.obj \ + $(OBJ)\mech/gss_display_name.obj \ + $(OBJ)\mech/gss_display_name_ext.obj \ + $(OBJ)\mech/gss_display_status.obj \ + $(OBJ)\mech/gss_duplicate_cred.obj \ + $(OBJ)\mech/gss_duplicate_name.obj \ + $(OBJ)\mech/gss_duplicate_oid.obj \ + $(OBJ)\mech/gss_duplicate_oid_set.obj \ + $(OBJ)\mech/gss_encapsulate_token.obj \ + $(OBJ)\mech/gss_export_name.obj \ + $(OBJ)\mech/gss_export_name_composite.obj \ + $(OBJ)\mech/gss_export_sec_context.obj \ + $(OBJ)\mech/gss_get_mic.obj \ + $(OBJ)\mech/gss_get_neg_mechs.obj \ + $(OBJ)\mech/gss_get_name_attribute.obj \ + $(OBJ)\mech/gss_import_name.obj \ + $(OBJ)\mech/gss_import_sec_context.obj \ + $(OBJ)\mech/gss_indicate_mechs.obj \ + $(OBJ)\mech/gss_init_sec_context.obj \ + $(OBJ)\mech/gss_inquire_context.obj \ + $(OBJ)\mech/gss_inquire_cred.obj \ + $(OBJ)\mech/gss_inquire_cred_by_mech.obj \ + $(OBJ)\mech/gss_inquire_cred_by_oid.obj \ + $(OBJ)\mech/gss_inquire_mechs_for_name.obj \ + $(OBJ)\mech/gss_inquire_name.obj \ + $(OBJ)\mech/gss_inquire_names_for_mech.obj \ + $(OBJ)\mech/gss_krb5.obj \ + $(OBJ)\mech/gss_mech_switch.obj \ + $(OBJ)\mech/gss_mo.obj \ + $(OBJ)\mech/gss_names.obj \ + $(OBJ)\mech/gss_oid.obj \ + $(OBJ)\mech/gss_oid_equal.obj \ + $(OBJ)\mech/gss_oid_to_str.obj \ + $(OBJ)\mech/gss_pname_to_uid.obj \ + $(OBJ)\mech/gss_process_context_token.obj \ + $(OBJ)\mech/gss_pseudo_random.obj \ + $(OBJ)\mech/gss_release_buffer.obj \ + $(OBJ)\mech/gss_release_cred.obj \ + $(OBJ)\mech/gss_release_name.obj \ + $(OBJ)\mech/gss_release_oid.obj \ + $(OBJ)\mech/gss_release_oid_set.obj \ + $(OBJ)\mech/gss_rfc4121.obj \ + $(OBJ)\mech/gss_seal.obj \ + $(OBJ)\mech/gss_set_cred_option.obj \ + $(OBJ)\mech/gss_set_name_attribute.obj \ + $(OBJ)\mech/gss_set_neg_mechs.obj \ + $(OBJ)\mech/gss_set_sec_context_option.obj \ + $(OBJ)\mech/gss_sign.obj \ + $(OBJ)\mech/gss_store_cred.obj \ + $(OBJ)\mech/gss_store_cred_into.obj \ + $(OBJ)\mech/gss_test_oid_set_member.obj \ + $(OBJ)\mech/gss_unseal.obj \ + $(OBJ)\mech/gss_unwrap.obj \ + $(OBJ)\mech/gss_utils.obj \ + $(OBJ)\mech/gss_verify.obj \ + $(OBJ)\mech/gss_verify_mic.obj \ + $(OBJ)\mech/gss_wrap.obj \ + $(OBJ)\mech/gss_wrap_size_limit.obj \ + $(OBJ)\mech/gss_inquire_sec_context_by_oid.obj \ + $(OBJ)\mech/gssspi_exchange_meta_data.obj \ + $(OBJ)\mech/gssspi_query_mechanism_info.obj \ + $(OBJ)\mech/gssspi_query_meta_data.obj \ + $(OBJ)\spnego/accept_sec_context.obj \ + $(OBJ)\spnego/compat.obj \ + $(OBJ)\spnego/context_storage.obj \ + $(OBJ)\spnego/context_stubs.obj \ + $(OBJ)\spnego/external.obj \ + $(OBJ)\spnego/init_sec_context.obj \ + $(OBJ)\spnego/negoex_ctx.obj \ + $(OBJ)\spnego/negoex_util.obj \ + $(OBJ)\ntlm/accept_sec_context.obj \ + $(OBJ)\ntlm/acquire_cred.obj \ + $(OBJ)\ntlm/add_cred.obj \ + $(OBJ)\ntlm/canonicalize_name.obj \ + $(OBJ)\ntlm/compare_name.obj \ + $(OBJ)\ntlm/context_time.obj \ + $(OBJ)\ntlm/creds.obj \ + $(OBJ)\ntlm/crypto.obj \ + $(OBJ)\ntlm/delete_sec_context.obj \ + $(OBJ)\ntlm/display_name.obj \ + $(OBJ)\ntlm/display_status.obj \ + $(OBJ)\ntlm/duplicate_cred.obj \ + $(OBJ)\ntlm/duplicate_name.obj \ + $(OBJ)\ntlm/export_name.obj \ + $(OBJ)\ntlm/export_sec_context.obj \ + $(OBJ)\ntlm/external.obj \ + $(OBJ)\ntlm/import_name.obj \ + $(OBJ)\ntlm/import_sec_context.obj \ + $(OBJ)\ntlm/indicate_mechs.obj \ + $(OBJ)\ntlm/init_sec_context.obj \ + $(OBJ)\ntlm/inquire_context.obj \ + $(OBJ)\ntlm/inquire_cred_by_mech.obj \ + $(OBJ)\ntlm/inquire_mechs_for_name.obj \ + $(OBJ)\ntlm/inquire_names_for_mech.obj \ + $(OBJ)\ntlm/inquire_sec_context_by_oid.obj \ + $(OBJ)\ntlm/iter_cred.obj \ + $(OBJ)\ntlm/process_context_token.obj \ + $(OBJ)\ntlm/release_cred.obj \ + $(OBJ)\ntlm/release_name.obj \ + $(OBJ)\ntlm/set_sec_context_option.obj \ + $(OBJ)\ntlm/kdc.obj \ + $(OBJ)\sanon/accept_sec_context.obj \ + $(OBJ)\sanon/acquire_cred.obj \ + $(OBJ)\sanon/add_cred.obj \ + $(OBJ)\sanon/canonicalize_name.obj \ + $(OBJ)\sanon/compare_name.obj \ + $(OBJ)\sanon/context_time.obj \ + $(OBJ)\sanon/crypto.obj \ + $(OBJ)\sanon/delete_sec_context.obj \ + $(OBJ)\sanon/display_name.obj \ + $(OBJ)\sanon/display_status.obj \ + $(OBJ)\sanon/duplicate_cred.obj \ + $(OBJ)\sanon/duplicate_name.obj \ + $(OBJ)\sanon/export_cred.obj \ + $(OBJ)\sanon/export_name.obj \ + $(OBJ)\sanon/export_sec_context.obj \ + $(OBJ)\sanon/external.obj \ + $(OBJ)\sanon/import_cred.obj \ + $(OBJ)\sanon/import_name.obj \ + $(OBJ)\sanon/import_sec_context.obj \ + $(OBJ)\sanon/init_sec_context.obj \ + $(OBJ)\sanon/inquire_context.obj \ + $(OBJ)\sanon/inquire_cred.obj \ + $(OBJ)\sanon/inquire_cred_by_mech.obj \ + $(OBJ)\sanon/inquire_mechs_for_name.obj \ + $(OBJ)\sanon/inquire_names_for_mech.obj \ + $(OBJ)\sanon/inquire_sec_context_by_oid.obj \ + $(OBJ)\sanon/negoex.obj \ + $(OBJ)\sanon/process_context_token.obj \ + $(OBJ)\sanon/release_cred.obj \ + $(OBJ)\sanon/release_name.obj \ + $(OBJ)\gkrb5_err.obj \ + $(OBJ)\negoex_err.obj \ + $(OBJ)\spnego\asn1_spnego_asn1.obj \ + $(OBJ)\gssapi\asn1_gssapi_asn1.obj + +GCOPTS=-I$(SRCDIR) -I$(OBJ) -Igssapi -DBUILD_GSSAPI_LIB + +{$(OBJ)\krb5}.c{$(OBJ)\krb5}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\krb5\ -Fd$(OBJ)\krb5\ -I$(OBJ)\krb5 $(GCOPTS) + +{krb5}.c{$(OBJ)\krb5}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\krb5\ -Fd$(OBJ)\krb5\ -I$(OBJ)\krb5 $(GCOPTS) -DASN1_LIB + +{$(OBJ)\mech}.c{$(OBJ)\mech}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\mech\ -Fd$(OBJ)\mech\ -I$(OBJ)\mech $(GCOPTS) + +{mech}.c{$(OBJ)\mech}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\mech\ -Fd$(OBJ)\mech\ -I$(OBJ)\mech -I$(OBJ)\gssapi $(GCOPTS) -DASN1_LIB + +{$(OBJ)\ntlm}.c{$(OBJ)\ntlm}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\ntlm\ -Fd$(OBJ)\ntlm\ -I$(OBJ)\ntlm $(GCOPTS) + +{ntlm}.c{$(OBJ)\ntlm}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\ntlm\ -Fd$(OBJ)\ntlm\ -I$(OBJ)\ntlm $(GCOPTS) -DASN1_LIB + +{$(OBJ)\spnego}.c{$(OBJ)\spnego}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\spnego\ -Fd$(OBJ)\spnego\ -I$(OBJ)\spnego $(GCOPTS) + +{spnego}.c{$(OBJ)\spnego}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\spnego\ -Fd$(OBJ)\spnego\ -I$(OBJ)\spnego -Imech $(GCOPTS) -DASN1_LIB + +{$(OBJ)\sanon}.c{$(OBJ)\sanon}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\sanon\ -Fd$(OBJ)\sanon\ -I$(OBJ)\sanon -I$(OBJ) -I$(OBJ)\krb5 -I$(OBJ)\gssapi -Ikrb5 -Imech -Igssapi $(GCOPTS) + +{sanon}.c{$(OBJ)\sanon}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\sanon\ -Fd$(OBJ)\sanon\ -I$(OBJ)\sanon -I$(OBJ) -I$(OBJ)\krb5 -I$(OBJ)\gssapi -Ikrb5 -Imech -Igssapi $(GCOPTS) -DASN1_LIB + +{$(OBJ)\gssapi}.c{$(OBJ)\gssapi}.obj:: + $(C2OBJ_NP) -Fo$(OBJ)\gssapi\ -Fd$(OBJ)\gssapi\ -I$(OBJ)\gssapi $(GCOPTS) + +{$(OBJ)}.c{$(OBJ)}.obj:: + $(C2OBJ_P) $(GCOPTS) + +{gssapi}.h{$(INCDIR)\gssapi}.h: + $(CP) $** $@ + +{$(OBJ)}.h{$(INCDIR)\gssapi}.h: + $(CP) $** $@ + +LIBGSSAPI_LIBS=\ + $(LIBHEIMBASE) \ + $(LIBROKEN) \ + $(LIBHEIMDAL) \ + $(LIBHEIMNTLM) \ + $(LIBCOMERR) + +LIBGSSAPI_SDKLIBS=\ + $(PTHREAD_LIB) \ + Secur32.lib Shell32.lib Advapi32.lib + +!ifndef STATICLIBS + +RES=$(OBJ)\libgssapi-version.res + +$(BINDIR)\gssapi.dll: $(libgssapi_OBJs) $(RES) + $(DLLGUILINK_C) -implib:$(LIBGSSAPI) \ + -out:$(BINDIR)\gssapi.dll \ + -def:libgssapi-exports.def \ + $(LIBGSSAPI_LIBS) $(RES) $(LIBGSSAPI_SDKLIBS) @<< +$(libgssapi_OBJs: = +) +<< + $(DLLPREP_NODIST) + +$(LIBGSSAPI): $(BINDIR)\gssapi.dll + +clean:: + -$(RM) $(BINDIR)\gssapi.* + +!else + +$(LIBGSSAPI): $(libgssapi_OBJs) + $(LIBCON_C) -OUT:$@ $(LIBGSSAPI_LIBS) $(LIBGSSAPI_SDKLIBS) @<< +$(libgssapi_OBJs: = +) +<< + +!endif + +all:: $(LIBGSSAPI) + +clean:: + -$(RM) $(LIBGSSAPI) + +prep:: mkdirs-gss + +mkdirs-gss: +!if !exist($(OBJ)\ntlm) + $(MKDIR) $(OBJ)\ntlm +!endif +!if !exist($(OBJ)\krb5) + $(MKDIR) $(OBJ)\krb5 +!endif +!if !exist($(OBJ)\spnego) + $(MKDIR) $(OBJ)\spnego +!endif +!if !exist($(OBJ)\sanon) + $(MKDIR) $(OBJ)\sanon +!endif +!if !exist($(OBJ)\mech) + $(MKDIR) $(OBJ)\mech +!endif +!if !exist($(OBJ)\gssapi) + $(MKDIR) $(OBJ)\gssapi +!endif + +clean:: + -$(RM) $(OBJ)\ntlm\*.* + -$(RM) $(OBJ)\krb5\*.* + -$(RM) $(OBJ)\spnego\*.* + -$(RM) $(OBJ)\mech\*.* + -$(RM) $(OBJ)\sanon\*.* + -$(RM) $(OBJ)\gssapi\*.* + +all-tools:: $(BINDIR)\gsstool.exe + +$(BINDIR)\gsstool.exe: $(OBJ)\gsstool.obj $(OBJ)\gss-commands.obj $(LIBGSSAPI) $(LIBROKEN) $(LIBSL) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP) + +$(OBJ)\gss-commands.c $(OBJ)\gss-commands.h: gss-commands.in + cd $(OBJ) + $(CP) $(SRCDIR)\gss-commands.in gss-commands.in + $(BINDIR)\slc.exe gss-commands.in + cd $(SRCDIR) + +!ifdef ELISP +# This macro invocation is used to update the libgssapi_OBJs +# definition below (generate-obj-macro is defined in maint.el): + +(generate-obj-macro "libgssapi_OBJs" + (concat "\t$(OBJ)\\gkrb5_err.obj \\\n" + "\t$(OBJ)\\negoex_err.obj \\\n" + "\t$(OBJ)\\spnego\\asn1_spnego_asn1.obj \\\n" + "\t$(OBJ)\\gssapi\\asn1_gssapi_asn1.obj") + "krb5src" "mechsrc" "spnegosrc" "ntlmsrc") +!endif + +test-exports: + $(PERL) ..\..\cf\w32-check-exported-symbols.pl --vs version-script.map --def libgssapi-exports.def + +test:: test-exports + + +TEST_BINARIES=\ + $(OBJ)\test_oid.exe \ + $(OBJ)\test_names.exe \ + $(OBJ)\test_cfx.exe \ + $(OBJ)\test_acquire_cred.exe \ + $(OBJ)\test_cred.exe \ + $(OBJ)\test_kcred.exe \ + $(OBJ)\test_context.exe \ + $(OBJ)\test_ntlm.exe + +$(OBJ)\test_oid.exe: $(OBJ)\test_oid.obj $(LIBGSSAPI) $(LIBROKEN) + $(EXECONLINK) + $(EXEPREP_NODIST) + +$(OBJ)\test_names.exe: $(OBJ)\test_names.obj $(LIBGSSAPI) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP_NODIST) + +$(OBJ)\test_cfx.exe: $(OBJ)\krb5\test_cfx.obj $(LIBHEIMDAL) $(LIBGSSAPI) $(LIBROKEN) + $(EXECONLINK) + $(EXEPREP_NODIST) + +$(OBJ)\test_acquire_cred.exe: $(OBJ)\test_acquire_cred.obj $(OBJ)\test_common.obj \ + $(LIBGSSAPI) $(LIBROKEN) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP_NODIST) + +$(OBJ)\test_cred.exe: $(OBJ)\test_cred.obj $(LIBGSSAPI) $(LIBROKEN) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP_NODIST) + +$(OBJ)\test_kcred.exe: $(OBJ)\test_kcred.obj $(LIBGSSAPI) $(LIBHEIMDAL) \ + $(LIBROKEN) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP_NODIST) + +$(OBJ)\test_context.exe: $(OBJ)\test_context.obj $(OBJ)\test_common.obj \ + $(LIBGSSAPI) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP_NODIST) + +$(OBJ)\test_ntlm.exe: $(OBJ)\test_ntlm.obj $(OBJ)\test_common.obj \ + $(LIBGSSAPI) $(LIBHEIMNTLM) $(LIBROKEN) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP_NODIST) + +{}.c{$(OBJ)}.obj:: + $(C2OBJ_P) -I$(OBJ)\krb5 -I$(OBJ) -I$(SRCDIR) -I$(SRCDIR)\gssapi + +test-binaries: $(LIBGSSAPI) $(TEST_BINARIES) + +run-test: + cd $(OBJ) + -test_oid + -test_names + -test_cfx + -test_kcred + cd $(SRCDIR) + +test:: test-binaries run-test diff --git a/third_party/heimdal/lib/gssapi/gen-oid.pl b/third_party/heimdal/lib/gssapi/gen-oid.pl new file mode 100644 index 0000000..d635f28 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gen-oid.pl @@ -0,0 +1,149 @@ +#!/usr/bin/perl +# +# Copyright (c) 2010 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +use Getopt::Std; + +my $output; +my $CFILE, $HFILE; +my $onlybase; +my $header = 0; + +getopts('b:h') || die "USAGE: ./gen-oid [-b BASE] [-h HEADER]"; + +if($opt_b) { + $onlybase = $opt_b; +} + +$header = 1 if ($opt_h); + +printf "/* Generated file */\n"; +if ($header) { + printf "#ifndef GSSAPI_GSSAPI_OID\n"; + printf "#define GSSAPI_GSSAPI_OID 1\n\n"; +} else { + printf "#include \"mech_locl.h\"\n\n"; +} + +my %tables; +my %types; + +while(<>) { + + if (/^\w*#(.*)/) { + my $comment = $1; + + if ($header) { + printf("$comment\n"); + } + + } elsif (/^oid\s+([\w\.]+)\s+(\w+)\s+([\w\.]+)/) { + my ($base, $name, $oid) = ($1, $2, $3); + + next if (defined $onlybase and $onlybase ne $base); + + my $store = "__" . lc($name) . "_oid_desc"; + + # encode oid + + my @array = split(/\./, $oid); + my $length = 0; + my $data = ""; + + my $num; + + $n = $#array; + while ($n > 1) { + $num = $array[$n]; + + my $p = int($num % 128); + $data = sprintf("\\x%02x", $p) . $data; + + $num = int($num / 128); + + $length += 1; + + while ($num > 0) { + $p = int($num % 128) + 128; + $num = int($num / 128); + $data = sprintf("\\x%02x", $p) . $data; + $length += 1; + } + $n--; + } + $num = int($array[0] * 40 + $array[1]); + + $data = sprintf("\\x%x", $num) . $data; + $length += 1; + + if ($header) { + printf "extern GSSAPI_LIB_VARIABLE gss_OID_desc $store;\n"; + printf "#define $name (&$store)\n\n"; + } else { + printf "/* $name - $oid */\n"; + printf "gss_OID_desc GSSAPI_LIB_VARIABLE $store = { $length, rk_UNCONST(\"$data\") };\n\n"; + } + push(@oidstorage, $store); + } elsif (/^desc\s+([\w]+)\s+(\w+)\s+(\"[^\"]*\")\s+(\"[^\"]*\")/) { + my ($type, $oid, $short, $long) = ($1, $2, $3, $4); + my $object = { type=> $type, oid => $oid, short => $short, long => $long }; + + $tables{$oid} = \$object; + $types{$type} = 1; + } + +} + +foreach my $k (sort keys %types) { + if (!$header) { + print "struct _gss_oid_name_table _gss_ont_" . $k . "[] = {\n"; + foreach my $m (sort {$$a->{oid} cmp $$b->{oid}} values %tables) { + if ($$m->{type} eq $k) { + printf " { %s, \"%s\", %s, %s },\n", $$m->{oid}, $$m->{oid}, $$m->{short}, $$m->{long}; + } + } + printf " { NULL, NULL, NULL, NULL }\n"; + printf "};\n\n"; + + } +} + +if ($header) { + printf "#endif /* GSSAPI_GSSAPI_OID */\n"; +} else { + printf "gss_OID _gss_ot_internal[] = {\n"; + foreach my $k (@oidstorage) { + print " &$k,\n"; + } + printf "};\n\n"; + printf "size_t _gss_ot_internal_count = sizeof(_gss_ot_internal) / sizeof(_gss_ot_internal[0]);\n"; +} diff --git a/third_party/heimdal/lib/gssapi/gss-commands.in b/third_party/heimdal/lib/gssapi/gss-commands.in new file mode 100644 index 0000000..25ec1c8 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gss-commands.in @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $Id$ */ + +command = { + name = "mechanisms" + name = "supported-mechanisms" + help = "Print the supported mechanisms" +} +command = { + name = "attributes" + name = "attrs-for-mech" + help = "Print the attributes for mechs" + option = { + long = "all" + type = "flag" + } + option = { + long = "mech" + type = "string" + argument = "mechanism" + } +} +command = { + name = "help" + name = "?" + argument = "[command]" + min_args = "0" + max_args = "1" + help = "Help! I need somebody." +} diff --git a/third_party/heimdal/lib/gssapi/gss-token.1 b/third_party/heimdal/lib/gssapi/gss-token.1 new file mode 100644 index 0000000..7bd50b0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gss-token.1 @@ -0,0 +1,108 @@ +.\" +.\" +.Dd May 12, 2014 +.Os +.Dt GSS-TOKEN 1 +.Sh NAME +.Nm gss-token +.Nd generate and consume base64 GSS tokens +.Sh SYNOPSIS +.Nm +.Op Fl DNn +.Op Fl c count +.Ar service@host +.Nm +.Fl r +.Op Fl MNln +.Op Fl C Ar ccache +.Op Fl S Ar maxsize +.Op Fl c count +.Op Fl m mech +.Op Ar service@host +.Sh DESCRIPTION +.Nm +generates and consumes base64 encoded GSS tokens. +By default, it runs as an initiator and with the +.Fl r +flag it becomes an acceptor. +.Pp +.Nm +supports the following options: +.Bl -tag -width indentxxxx +.It Fl C Ar ccache +write an accepted delegated credential into +.Ar ccache . +This only makes sense if +.Fl r +is specified. +.It Fl D +delegate credentials. +This only makes sense as a client, that is when +.Fl r +is not specified. +.It Fl M +copy the default ccache to a MEMORY: ccache before each +separate write operation. +The default ccache will not pick up any obtained service +tickets. +If specified with +.Fl c , +the cache will revert to its original state before each +new token is written. +This can be used to load test the KDC. +.It Fl N +prepend +.Dq Negotiate\ +to generated tokens and expect it on consumed tokens. +.It Fl S Ar maxsize +split each token that is generated into components of maximum +size +.Ar maxsize . +Each token is base64 encoded and output separately. +.It Fl c Ar count +repeat the operation +.Ar count +times. +This flag only changes the behaviour when operating in initiator mode. +This is good for very basic benchmarking. +.It Fl l +loop indefinitely in acceptor mode. +.It Fl m Ar mech +specifies the GSS mechanism that will be used in initiator mode. +If a mechanism name of +.Do ? Dc +is specified, a list of supported mechanisms will be output and +.Nm +will exit. +.It Fl n +do not output the generated tokens. +.It Fl r +run in acceptor mode. +.El +.Pp +.Nm +takes one argument, a +.Ar host@service +specifier. +The argument is required when running as an initiator but is optional as +an acceptor. +.Pp +.Nm +will try to read a token whenever the GSS mechanism expects one +and will output a token whenever the GSS mechanism provides one. +Tokens are base64 encoded and terminated by either two successive +newlines or one newline and EOF. +The base64 encoding may be broken up by single newlines which will +be ignored when read. No extra whitespace will be ignored. +.Sh EXAMPLES +To test a simple GSS mechanism which doesn't require a round trip, +a single +.Pa /bin/sh +pipeline will suffice: +.Bd -literal -offset indent +$ export KRB5_KTNAME=/path/to/keytab +$ gss-token HTTP@$(hostname) | gss-token -r +.Ed +.Sh SEE ALSO +.Xr gssapi 3 , +.Xr kerberos 8 . diff --git a/third_party/heimdal/lib/gssapi/gss-token.c b/third_party/heimdal/lib/gssapi/gss-token.c new file mode 100644 index 0000000..844fa4d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gss-token.c @@ -0,0 +1,678 @@ +/* */ + +/*- + * Copyright (c) 1997-2011 Roland C. Dowdeswell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer and + * dedication in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <errno.h> +#ifdef __APPLE__ +#include <malloc/malloc.h> +#elif HAVE_MALLOC_H +#include <malloc.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gssapi/gssapi.h> +#include <gssapi/gssapi_krb5.h> +#include <krb5.h> +#include <base64.h> +#include <getarg.h> +#include <roken.h> +#include <vers.h> + +#define GBAIL(x, _maj, _min) do { \ + if (GSS_ERROR(_maj)) { \ + char *the_gss_err; \ + \ + ret = 1; \ + the_gss_err = gss_mk_err(_maj, _min, x); \ + if (the_gss_err) \ + fprintf(stderr, "%s\n", the_gss_err); \ + else \ + fprintf(stderr, "err making err\n"); \ + free(the_gss_err); \ + goto bail; \ + } \ + } while (0) + +#define K5BAIL(x) do { \ + kret = x; \ + if (kret) { \ + const char *k5err; \ + \ + k5err = krb5_get_error_message(kctx, kret); \ + if (k5err) { \ + fprintf(stderr, "%s in %s:%s\n", k5err, \ + #x, __func__); \ + krb5_free_error_message(kctx, k5err); \ + } else { \ + fprintf(stderr, "unknown error %d in " \ + "%s:%s\n", kret, #x, __func__); \ + } \ + exit(1); /* XXXrcd: shouldn't exit */ \ + } \ + } while (0) + + +/* + * global variables + */ + +int Sflag = 0; +int nflag = 0; +gss_OID global_mech = GSS_C_NO_OID; + +static char * +gss_mk_err(OM_uint32 maj_stat, OM_uint32 min_stat, const char *preamble) +{ + gss_buffer_desc status; + OM_uint32 new_stat; + OM_uint32 cur_stat; + OM_uint32 msg_ctx = 0; + OM_uint32 ret; + int type; + size_t newlen; + char *str = NULL; + char *tmp = NULL; + + cur_stat = maj_stat; + type = GSS_C_GSS_CODE; + + for (;;) { + + /* + * GSS_S_FAILURE produces a rather unhelpful message, so + * we skip straight to the mech specific error in this case. + */ + + if (type == GSS_C_GSS_CODE && cur_stat == GSS_S_FAILURE) { + type = GSS_C_MECH_CODE; + cur_stat = min_stat; + } + + ret = gss_display_status(&new_stat, cur_stat, type, + GSS_C_NO_OID, &msg_ctx, &status); + + if (GSS_ERROR(ret)) + return str; /* XXXrcd: hmmm, not quite?? */ + + if (str) + newlen = strlen(str); + else + newlen = strlen(preamble); + + newlen += status.length + 3; + + tmp = str; + str = malloc(newlen); + + if (!str) { + gss_release_buffer(&new_stat, &status); + return tmp; /* XXXrcd: hmmm, not quite?? */ + } + + snprintf(str, newlen, "%s%s%.*s", tmp?tmp:preamble, + tmp?", ":": ", (int)status.length, (char *)status.value); + + gss_release_buffer(&new_stat, &status); + free(tmp); + + /* + * If we are finished processing for maj_stat, then + * move onto min_stat. + */ + + if (msg_ctx == 0 && type == GSS_C_GSS_CODE && min_stat != 0) { + type = GSS_C_MECH_CODE; + cur_stat = min_stat; + continue; + } + + if (msg_ctx == 0) + break; + } + + return str; +} + +static char * +read_buffer(FILE *fp) +{ + char buf[65536]; + char *p; + char *ret = NULL; + size_t buflen; + size_t retlen = 0; + + while (fgets(buf, sizeof(buf), fp) != NULL) { + if ((p = strchr(buf, '\n')) == NULL) { + fprintf(stderr, "Long line, exiting.\n"); + exit(1); + } + *p = '\0'; + buflen = strlen(buf); + if (buflen == 0) + break; + + ret = realloc(ret, retlen + buflen + 1); + if (!ret) { + perror("realloc"); + exit(1); + } + memcpy(ret + retlen, buf, buflen); + ret[retlen + buflen] = '\0'; + retlen += buflen; + } + + if (ferror(stdin)) { + perror("fgets"); + exit(1); + } + + return ret; +} + +static int +write_and_free_token(gss_buffer_t out, int negotiate) +{ + OM_uint32 min; + char *outstr = NULL; + char *p = out->value; + size_t len = out->length; + size_t inc; + int ret = 0; + int first = 1; + + if (nflag) + goto bail; + + /* + * According to RFC 2744 page 25, we simply don't output + * zero length output tokens. + */ + if (len == 0) + goto bail; + + inc = len; + if (Sflag) + inc = Sflag; + + do { + if (first) + first = 0; + else + printf("\n"); + if (len < inc) + inc = len; + ret = rk_base64_encode(p, inc, &outstr); + if (ret < 0) { + fprintf(stderr, "Out of memory.\n"); + ret = 1; + goto bail; + } + ret = 0; + printf("%s%s\n", negotiate?"Negotiate ":"", outstr); + free(outstr); + p += inc; + len -= inc; + } while (len > 0); + +bail: + gss_release_buffer(&min, out); + return ret; +} + +static int +read_token(gss_buffer_t in, int negotiate) +{ + char *inbuf = NULL; + char *tmp; + size_t len; + int ret = 0; + + /* We must flush before we block wanting input */ + fflush(stdout); + + *in = (gss_buffer_desc)GSS_C_EMPTY_BUFFER; + inbuf = read_buffer(stdin); + if (!inbuf) + /* Just a couple of \n's in a row or EOF, no error. */ + return 0; + + tmp = inbuf; + if (negotiate) { + if (strncasecmp("Negotiate ", inbuf, 10) != 0) { + fprintf(stderr, "Token doesn't begin with " + "\"Negotiate \"\n"); + ret = -1; + goto bail; + } + + tmp += 10; + } + + len = strlen(tmp); + in->value = malloc(len + 1); + if (!in->value) { + fprintf(stderr, "Out of memory.\n"); + ret = -1; + goto bail; + } + ret = rk_base64_decode(tmp, in->value); + if (ret < 0) { + free(in->value); + in->value = NULL; + if (errno == EOVERFLOW) + fprintf(stderr, "Token is too big\n"); + else + fprintf(stderr, "Token encoding is not valid " + "base64\n"); + goto bail; + } else { + in->length = ret; + } + ret = 0; + +bail: + free(inbuf); + return ret; +} + +static int +initiate_one(gss_name_t service, int delegate, int negotiate) +{ + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_buffer_desc in; + gss_buffer_desc out; + OM_uint32 maj; + OM_uint32 min; + OM_uint32 flags = 0; + int first = 1; + int ret = 0; + + if (delegate) + flags |= GSS_C_DELEG_FLAG; + + do { + out.length = 0; + out.value = 0; + + if (first) { + in.length = 0; + in.value = 0; + first = 0; + } else { + printf("\n"); + ret = read_token(&in, negotiate); + if (ret) + return ret; + if (feof(stdin)) + return -1; + } + + maj = gss_init_sec_context(&min, GSS_C_NO_CREDENTIAL, &ctx, + service, global_mech, flags, 0, + GSS_C_NO_CHANNEL_BINDINGS, &in, NULL, &out, + NULL, NULL); + + ret = write_and_free_token(&out, negotiate); + if (ret) + return ret; + + GBAIL("gss_init_sec_context", maj, min); + } while (maj & GSS_S_CONTINUE_NEEDED); + +bail: + if (ctx != GSS_C_NO_CONTEXT) { + /* + * XXXrcd: here we ignore the fact that we might have an + * output token as this program doesn't do terribly + * well in that case. + */ + gss_delete_sec_context(&min, &ctx, NULL); + } + + return ret; +} + +static krb5_error_code +copy_cache(krb5_context kctx, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code kret; + krb5_principal princ = NULL; + krb5_cc_cursor cursor; + krb5_creds cred; + + K5BAIL(krb5_cc_get_principal(kctx, from, &princ)); + K5BAIL(krb5_cc_initialize(kctx, to, princ)); + K5BAIL(krb5_cc_start_seq_get(kctx, from, &cursor)); + for (;;) { + kret = krb5_cc_next_cred(kctx, from, &cursor, &cred); + if (kret) + break; + kret = krb5_cc_store_cred(kctx, to, &cred); + krb5_free_cred_contents(kctx, &cred); + if (kret) + break; + } + krb5_cc_end_seq_get(kctx, from, &cursor); + + if (kret == KRB5_CC_END) + kret = 0; + K5BAIL(kret); + + if (princ) + krb5_free_principal(kctx, princ); + + return kret; +} + +static int +initiate_many(gss_name_t service, int delegate, int negotiate, int memcache, + size_t count) +{ + krb5_error_code kret = 0; + krb5_context kctx = NULL; + krb5_ccache def_cache = NULL; + krb5_ccache mem_cache = NULL; + size_t i; + + if (memcache) { + K5BAIL(krb5_init_context(&kctx)); + K5BAIL(krb5_cc_default(kctx, &def_cache)); + K5BAIL(krb5_cc_resolve(kctx, "MEMORY:mem_cache", &mem_cache)); + putenv("KRB5CCNAME=MEMORY:mem_cache"); + } + + for (i=0; i < count; i++) { + if (memcache) + K5BAIL(copy_cache(kctx, def_cache, mem_cache)); + kret = initiate_one(service, delegate, negotiate); + + if (!nflag && i < count - 1) + printf("\n"); + } + + if (kctx) + krb5_free_context(kctx); + if (def_cache) + krb5_cc_close(kctx, def_cache); + if (mem_cache) + krb5_cc_close(kctx, mem_cache); + + return kret; +} + +static int +accept_one(gss_name_t service, const char *ccname, int negotiate) +{ + gss_cred_id_t cred = NULL; + gss_cred_id_t deleg_creds = NULL; + gss_name_t client; + gss_OID mech_oid; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_buffer_desc in = GSS_C_EMPTY_BUFFER; + gss_buffer_desc out; + gss_buffer_desc dname = GSS_C_EMPTY_BUFFER; + krb5_context kctx = NULL; + krb5_ccache ccache = NULL; + krb5_error_code kret; + OM_uint32 maj, min; + int ret = 0; + + if (service) { + maj = gss_acquire_cred(&min, service, 0, NULL, GSS_C_ACCEPT, + &cred, NULL, NULL); + GBAIL("gss_acquire_cred", maj, min); + } + + do { + if (feof(stdin)) + return -1; + ret = read_token(&in, negotiate); + if (ret) + return ret; + + out.length = 0; + out.value = 0; + + maj = gss_accept_sec_context(&min, &ctx, cred, &in, + GSS_C_NO_CHANNEL_BINDINGS, &client, &mech_oid, &out, + NULL, NULL, &deleg_creds); + + ret = write_and_free_token(&out, negotiate); + if (ret) + return ret; + GBAIL("gss_accept_sec_context", maj, min); + } while (maj & GSS_S_CONTINUE_NEEDED); + + /* + * XXXrcd: not bothering to clean up because we're about to exit. + * Probably should fix this in case the code is used as + * an example by someone. + */ + + maj = gss_display_name(&min, client, &dname, NULL); + GBAIL("gss_display_name", maj, min); + + if (!nflag) + printf("Authenticated: %.*s\n", (int)dname.length, + (char *)dname.value); + (void) gss_release_buffer(&min, &dname); + (void) gss_release_name(&min, &client); + + if (ccname) { +#ifdef HAVE_GSS_STORE_CRED_INTO + gss_key_value_set_desc store; + gss_key_value_element_desc elem; + int overwrite_cred = 1; + int default_cred = 0; + + elem.key = "ccache"; + elem.value = ccname; + store.count = 1; + store.elements = &elem; + + maj = gss_store_cred_into(&min, deleg_creds, GSS_C_INITIATE, + GSS_C_NO_OID, overwrite_cred, default_cred, &store, NULL, + NULL); + GBAIL("gss_store_cred_into", maj, min); +#else + K5BAIL(krb5_init_context(&kctx)); + K5BAIL(krb5_cc_resolve(kctx, ccname, &ccache)); + + maj = gss_krb5_copy_ccache(&min, deleg_creds, ccache); + GBAIL("gss_krb5_copy_ccache", maj, min); +#endif + } + +bail: + if (kctx) + krb5_free_context(kctx); + if (ccache) + krb5_cc_close(kctx, ccache); + if (cred) + gss_release_cred(&min, &cred); + if (deleg_creds) + gss_release_cred(&min, &deleg_creds); + + free(in.value); + + return ret; +} + +static gss_name_t +import_service(char *service) +{ + gss_buffer_desc name; + gss_name_t svc = NULL; + OM_uint32 maj; + OM_uint32 min; + int ret = 0; + + name.length = strlen(service); + name.value = service; + + maj = gss_import_name(&min, &name, GSS_C_NT_HOSTBASED_SERVICE, &svc); + + GBAIL("gss_import_name", maj, min); + +bail: + if (ret) + exit(1); + return svc; +} + +static void +print_all_mechs(void) +{ + OM_uint32 maj, min; + gss_OID_set mech_set; + size_t i; + int ret = 0; + + maj = gss_indicate_mechs(&min, &mech_set); + GBAIL("gss_indicate_mechs", maj, min); + + for (i=0; i < mech_set->count; i++) + printf("%s\n", gss_oid_to_name(&mech_set->elements[i])); + + (void) gss_release_oid_set(&min, &mech_set); + +bail: + exit(ret); +} + +static void +usage(int ecode) +{ + FILE *f = ecode == 0 ? stdout : stderr; + fprintf(f, "Usage: gss-token [-DNn] [-c count] service@host\n"); + fprintf(f, " gss-token -r [-Nln] [-C ccache] [-c count] " + "[service@host]\n"); + exit(ecode); +} + +int +main(int argc, char **argv) +{ + OM_uint32 min; + gss_name_t service = NULL; + size_t count = 1; + int Dflag = 0; + int Mflag = 0; + int Nflag = 0; + int hflag = 0; + int lflag = 0; + int rflag = 0; + int version_flag = 0; + int ret = 0; + int optidx = 0; + char *ccname = NULL; + char *mech = NULL; + struct getargs args[] = { + { "help", 'h', arg_flag, &hflag, NULL, NULL }, + { "version", 0, arg_flag, &version_flag, NULL, NULL }, + { NULL, 'C', arg_string, &ccname, NULL, NULL }, + { NULL, 'D', arg_flag, &Dflag, NULL, NULL }, + { NULL, 'M', arg_flag, &Mflag, NULL, NULL }, + { NULL, 'N', arg_flag, &Nflag, NULL, NULL }, + { NULL, 'S', arg_integer, &Sflag, NULL, NULL }, + { NULL, 'c', arg_integer, &count, NULL, NULL }, + { NULL, 'l', arg_flag, &lflag, NULL, NULL }, + { NULL, 'm', arg_string, &mech, NULL, NULL }, + { NULL, 'n', arg_flag, &nflag, NULL, NULL }, + { NULL, 'r', arg_flag, &rflag, NULL, NULL }, + }; + + setprogname(argv[0]); + if (argc == 1 || + getarg(args, sizeof(args)/sizeof(args[0]), argc, argv, &optidx)) + usage(1); + if (hflag) + usage(0); + if (version_flag) { + print_version(NULL); + return 0; + } + + argc -= optidx; + argv += optidx; + + if (mech) { + if (mech[0] == '?' && mech[1] == '\0') { + print_all_mechs(); + exit(0); + } + global_mech = gss_name_to_oid(mech); + if (!global_mech) { + fprintf(stderr, "Invalid mech \"%s\".\n", mech); + usage(1); + } + } + + if (argc > 0) + service = import_service(*argv); + + if (!rflag) { + if (!argc) { + fprintf(stderr, "Without -r, hostbased_service must " + "be provided.\n"); + usage(1); + } + if (ccname) { + fprintf(stderr, "Specifying a target ccache doesn't " + "make sense without -r.\n"); + usage(1); + } + ret = initiate_many(service, Dflag, Nflag, Mflag, count); + goto done; + } + + if (Dflag) { + fprintf(stderr, "Delegating credentials (-D) doesn't make " + "sense when reading tokens (-r).\n"); + usage(1); + } + + do { + ret = accept_one(service, ccname, Nflag); + } while (lflag && !ret && !feof(stdin)); + +done: + if (service) + gss_release_name(&min, &service); + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/gss_acquire_cred.3 b/third_party/heimdal/lib/gssapi/gss_acquire_cred.3 new file mode 100644 index 0000000..de58ecd --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gss_acquire_cred.3 @@ -0,0 +1,688 @@ +.\" Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id$ +.\" +.Dd October 26, 2005 +.Dt GSS_ACQUIRE_CRED 3 +.Os HEIMDAL +.Sh NAME +.Nm gss_accept_sec_context , +.Nm gss_acquire_cred , +.Nm gss_add_cred , +.Nm gss_add_oid_set_member , +.Nm gss_canonicalize_name , +.Nm gss_compare_name , +.Nm gss_context_time , +.Nm gss_create_empty_oid_set , +.Nm gss_delete_sec_context , +.Nm gss_display_name , +.Nm gss_display_status , +.Nm gss_duplicate_name , +.Nm gss_export_name , +.Nm gss_export_sec_context , +.Nm gss_get_mic , +.Nm gss_import_name , +.Nm gss_import_sec_context , +.Nm gss_indicate_mechs , +.Nm gss_init_sec_context , +.Nm gss_inquire_context , +.Nm gss_inquire_cred , +.Nm gss_inquire_cred_by_mech , +.Nm gss_inquire_mechs_for_name , +.Nm gss_inquire_names_for_mech , +.Nm gss_krb5_ccache_name , +.Nm gss_krb5_compat_des3_mic , +.Nm gss_krb5_copy_ccache , +.Nm gss_krb5_import_cred +.Nm gsskrb5_extract_authz_data_from_sec_context , +.Nm gsskrb5_register_acceptor_identity , +.Nm gss_krb5_import_ccache , +.Nm gss_krb5_get_tkt_flags , +.Nm gss_process_context_token , +.Nm gss_release_buffer , +.Nm gss_release_cred , +.Nm gss_release_name , +.Nm gss_release_oid_set , +.Nm gss_seal , +.Nm gss_sign , +.Nm gss_test_oid_set_member , +.Nm gss_unseal , +.Nm gss_unwrap , +.Nm gss_verify , +.Nm gss_verify_mic , +.Nm gss_wrap , +.Nm gss_wrap_size_limit +.Nd Generic Security Service Application Program Interface library +.Sh LIBRARY +GSS-API library (libgssapi, -lgssapi) +.Sh SYNOPSIS +.In gssapi.h +.Pp +.Ft OM_uint32 +.Fo gss_accept_sec_context +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t * context_handle" +.Fa "gss_const_cred_id_t acceptor_cred_handle" +.Fa "const gss_buffer_t input_token_buffer" +.Fa "const gss_channel_bindings_t input_chan_bindings" +.Fa "gss_name_t * src_name" +.Fa "gss_OID * mech_type" +.Fa "gss_buffer_t output_token" +.Fa "OM_uint32 * ret_flags" +.Fa "OM_uint32 * time_rec" +.Fa "gss_cred_id_t * delegated_cred_handle" +.Fc +.Pp +.Ft OM_uint32 +.Fo gss_acquire_cred +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_name_t desired_name" +.Fa "OM_uint32 time_req" +.Fa "const gss_OID_set desired_mechs" +.Fa "gss_cred_usage_t cred_usage" +.Fa "gss_cred_id_t * output_cred_handle" +.Fa "gss_OID_set * actual_mechs" +.Fa "OM_uint32 * time_rec" +.Fc +.Ft OM_uint32 +.Fo gss_add_cred +.Fa "OM_uint32 *minor_status" +.Fa "gss_const_cred_id_t input_cred_handle" +.Fa "gss_const_name_t desired_name" +.Fa "const gss_OID desired_mech" +.Fa "gss_cred_usage_t cred_usage" +.Fa "OM_uint32 initiator_time_req" +.Fa "OM_uint32 acceptor_time_req" +.Fa "gss_cred_id_t *output_cred_handle" +.Fa "gss_OID_set *actual_mechs" +.Fa "OM_uint32 *initiator_time_rec" +.Fa "OM_uint32 *acceptor_time_rec" +.Fc +.Ft OM_uint32 +.Fo gss_add_oid_set_member +.Fa "OM_uint32 * minor_status" +.Fa "const gss_OID member_oid" +.Fa "gss_OID_set * oid_set" +.Fc +.Ft OM_uint32 +.Fo gss_canonicalize_name +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_name_t input_name" +.Fa "const gss_OID mech_type" +.Fa "gss_name_t * output_name" +.Fc +.Ft OM_uint32 +.Fo gss_compare_name +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_name_t name1" +.Fa "gss_const_name_t name2" +.Fa "int * name_equal" +.Fc +.Ft OM_uint32 +.Fo gss_context_time +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "OM_uint32 * time_rec" +.Fc +.Ft OM_uint32 +.Fo gss_create_empty_oid_set +.Fa "OM_uint32 * minor_status" +.Fa "gss_OID_set * oid_set" +.Fc +.Ft OM_uint32 +.Fo gss_delete_sec_context +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t * context_handle" +.Fa "gss_buffer_t output_token" +.Fc +.Ft OM_uint32 +.Fo gss_display_name +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_name_t input_name" +.Fa "gss_buffer_t output_name_buffer" +.Fa "gss_OID * output_name_type" +.Fc +.Ft OM_uint32 +.Fo gss_display_status +.Fa "OM_uint32 *minor_status" +.Fa "OM_uint32 status_value" +.Fa "int status_type" +.Fa "const gss_OID mech_type" +.Fa "OM_uint32 *message_context" +.Fa "gss_buffer_t status_string" +.Fc +.Ft OM_uint32 +.Fo gss_duplicate_name +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_name_t src_name" +.Fa "gss_name_t * dest_name" +.Fc +.Ft OM_uint32 +.Fo gss_export_name +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_name_t input_name" +.Fa "gss_buffer_t exported_name" +.Fc +.Ft OM_uint32 +.Fo gss_export_sec_context +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t * context_handle" +.Fa "gss_buffer_t interprocess_token" +.Fc +.Ft OM_uint32 +.Fo gss_get_mic +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "gss_qop_t qop_req" +.Fa "const gss_buffer_t message_buffer" +.Fa "gss_buffer_t message_token" +.Fc +.Ft OM_uint32 +.Fo gss_import_name +.Fa "OM_uint32 * minor_status" +.Fa "const gss_buffer_t input_name_buffer" +.Fa "const gss_OID input_name_type" +.Fa "gss_name_t * output_name" +.Fc +.Ft OM_uint32 +.Fo gss_import_sec_context +.Fa "OM_uint32 * minor_status" +.Fa "const gss_buffer_t interprocess_token" +.Fa "gss_ctx_id_t * context_handle" +.Fc +.Ft OM_uint32 +.Fo gss_indicate_mechs +.Fa "OM_uint32 * minor_status" +.Fa "gss_OID_set * mech_set" +.Fc +.Ft OM_uint32 +.Fo gss_init_sec_context +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_cred_id_t initiator_cred_handle" +.Fa "gss_ctx_id_t * context_handle" +.Fa "gss_const_name_t target_name" +.Fa "const gss_OID mech_type" +.Fa "OM_uint32 req_flags" +.Fa "OM_uint32 time_req" +.Fa "const gss_channel_bindings_t input_chan_bindings" +.Fa "const gss_buffer_t input_token" +.Fa "gss_OID * actual_mech_type" +.Fa "gss_buffer_t output_token" +.Fa "OM_uint32 * ret_flags" +.Fa "OM_uint32 * time_rec" +.Fc +.Ft OM_uint32 +.Fo gss_inquire_context +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "gss_name_t * src_name" +.Fa "gss_name_t * targ_name" +.Fa "OM_uint32 * lifetime_rec" +.Fa "gss_OID * mech_type" +.Fa "OM_uint32 * ctx_flags" +.Fa "int * locally_initiated" +.Fa "int * open_context" +.Fc +.Ft OM_uint32 +.Fo gss_inquire_cred +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_cred_id_t cred_handle" +.Fa "gss_name_t * name" +.Fa "OM_uint32 * lifetime" +.Fa "gss_cred_usage_t * cred_usage" +.Fa "gss_OID_set * mechanisms" +.Fc +.Ft OM_uint32 +.Fo gss_inquire_cred_by_mech +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_cred_id_t cred_handle" +.Fa "const gss_OID mech_type" +.Fa "gss_name_t * name" +.Fa "OM_uint32 * initiator_lifetime" +.Fa "OM_uint32 * acceptor_lifetime" +.Fa "gss_cred_usage_t * cred_usage" +.Fc +.Ft OM_uint32 +.Fo gss_inquire_mechs_for_name +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_name_t input_name" +.Fa "gss_OID_set * mech_types" +.Fc +.Ft OM_uint32 +.Fo gss_inquire_names_for_mech +.Fa "OM_uint32 * minor_status" +.Fa "const gss_OID mechanism" +.Fa "gss_OID_set * name_types" +.Fc +.Ft OM_uint32 +.Fo gss_krb5_ccache_name +.Fa "OM_uint32 *minor" +.Fa "const char *name" +.Fa "const char **old_name" +.Fc +.Ft OM_uint32 +.Fo gss_krb5_copy_ccache +.Fa "OM_uint32 *minor" +.Fa "gss_cred_id_t cred" +.Fa "krb5_ccache out" +.Fc +.Ft OM_uint32 +.Fo gss_krb5_import_cred +.Fa "OM_uint32 *minor_status" +.Fa "krb5_ccache id" +.Fa "krb5_principal keytab_principal" +.Fa "krb5_keytab keytab" +.Fa "gss_cred_id_t *cred" +.Fc +.Ft OM_uint32 +.Fo gss_krb5_compat_des3_mic +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t context_handle" +.Fa "int onoff" +.Fc +.Ft OM_uint32 +.Fo gsskrb5_extract_authz_data_from_sec_context +.Fa "OM_uint32 *minor_status" +.Fa "gss_ctx_id_t context_handle" +.Fa "int ad_type" +.Fa "gss_buffer_t ad_data" +.Fc +.Ft OM_uint32 +.Fo gsskrb5_register_acceptor_identity +.Fa "const char *identity" +.Fc +.Ft OM_uint32 +.Fo gss_krb5_import_cache +.Fa "OM_uint32 *minor" +.Fa "krb5_ccache id" +.Fa "krb5_keytab keytab" +.Fa "gss_cred_id_t *cred" +.Fc +.Ft OM_uint32 +.Fo gss_krb5_get_tkt_flags +.Fa "OM_uint32 *minor_status" +.Fa "gss_ctx_id_t context_handle" +.Fa "OM_uint32 *tkt_flags" +.Fc +.Ft OM_uint32 +.Fo gss_process_context_token +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "const gss_buffer_t token_buffer" +.Fc +.Ft OM_uint32 +.Fo gss_release_buffer +.Fa "OM_uint32 * minor_status" +.Fa "gss_buffer_t buffer" +.Fc +.Ft OM_uint32 +.Fo gss_release_cred +.Fa "OM_uint32 * minor_status" +.Fa "gss_cred_id_t * cred_handle" +.Fc +.Ft OM_uint32 +.Fo gss_release_name +.Fa "OM_uint32 * minor_status" +.Fa "gss_name_t * input_name" +.Fc +.Ft OM_uint32 +.Fo gss_release_oid_set +.Fa "OM_uint32 * minor_status" +.Fa "gss_OID_set * set" +.Fc +.Ft OM_uint32 +.Fo gss_seal +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t context_handle" +.Fa "int conf_req_flag" +.Fa "int qop_req" +.Fa "gss_buffer_t input_message_buffer" +.Fa "int * conf_state" +.Fa "gss_buffer_t output_message_buffer" +.Fc +.Ft OM_uint32 +.Fo gss_sign +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t context_handle" +.Fa "int qop_req" +.Fa "gss_buffer_t message_buffer" +.Fa "gss_buffer_t message_token" +.Fc +.Ft OM_uint32 +.Fo gss_test_oid_set_member +.Fa "OM_uint32 * minor_status" +.Fa "const gss_OID member" +.Fa "const gss_OID_set set" +.Fa "int * present" +.Fc +.Ft OM_uint32 +.Fo gss_unseal +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t context_handle" +.Fa "gss_buffer_t input_message_buffer" +.Fa "gss_buffer_t output_message_buffer" +.Fa "int * conf_state" +.Fa "int * qop_state" +.Fc +.Ft OM_uint32 +.Fo gss_unwrap +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "const gss_buffer_t input_message_buffer" +.Fa "gss_buffer_t output_message_buffer" +.Fa "int * conf_state" +.Fa "gss_qop_t * qop_state" +.Fc +.Ft OM_uint32 +.Fo gss_verify +.Fa "OM_uint32 * minor_status" +.Fa "gss_ctx_id_t context_handle" +.Fa "gss_buffer_t message_buffer" +.Fa "gss_buffer_t token_buffer" +.Fa "int * qop_state" +.Fc +.Ft OM_uint32 +.Fo gss_verify_mic +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "const gss_buffer_t message_buffer" +.Fa "const gss_buffer_t token_buffer" +.Fa "gss_qop_t * qop_state" +.Fc +.Ft OM_uint32 +.Fo gss_wrap +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "int conf_req_flag" +.Fa "gss_qop_t qop_req" +.Fa "const gss_buffer_t input_message_buffer" +.Fa "int * conf_state" +.Fa "gss_buffer_t output_message_buffer" +.Fc +.Ft OM_uint32 +.Fo gss_wrap_size_limit +.Fa "OM_uint32 * minor_status" +.Fa "gss_const_ctx_id_t context_handle" +.Fa "int conf_req_flag" +.Fa "gss_qop_t qop_req" +.Fa "OM_uint32 req_output_size" +.Fa "OM_uint32 * max_input_size" +.Fc +.Sh DESCRIPTION +Generic Security Service API (GSS-API) version 2, and its C binding, +is described in +.Li RFC2743 +and +.Li RFC2744 . +Version 1 (deprecated) of the C binding is described in +.Li RFC1509 . +.Pp +Heimdals GSS-API implementation supports the following mechanisms +.Bl -bullet +.It +.Li GSS_KRB5_MECHANISM +.It +.Li GSS_SPNEGO_MECHANISM +.El +.Pp +GSS-API have generic name types that all mechanism are supposed to +implement (if possible): +.Bl -bullet +.It +.Li GSS_C_NT_USER_NAME +.It +.Li GSS_C_NT_MACHINE_UID_NAME +.It +.Li GSS_C_NT_STRING_UID_NAME +.It +.Li GSS_C_NT_HOSTBASED_SERVICE +.It +.Li GSS_C_NT_ANONYMOUS +.It +.Li GSS_C_NT_EXPORT_NAME +.El +.Pp +GSS-API implementations that supports Kerberos 5 have some additional +name types: +.Bl -bullet +.It +.Li GSS_KRB5_NT_PRINCIPAL_NAME +.It +.Li GSS_KRB5_NT_USER_NAME +.It +.Li GSS_KRB5_NT_MACHINE_UID_NAME +.It +.Li GSS_KRB5_NT_STRING_UID_NAME +.El +.Pp +In GSS-API, names have two forms, internal names and contiguous string +names. +.Bl -bullet +.It +.Li Internal name and mechanism name +.Pp +Internal names are implementation specific representation of +a GSS-API name. +.Li Mechanism names +special form of internal names corresponds to one and only one mechanism. +.Pp +In GSS-API an internal name is stored in a +.Dv gss_name_t . +.It +.Li Contiguous string name and exported name +.Pp +Contiguous string names are gssapi names stored in a +.Dv OCTET STRING +that together with a name type identifier (OID) uniquely specifies a +gss-name. +A special form of the contiguous string name is the exported name that +have a OID embedded in the string to make it unique. +Exported name have the nametype +.Dv GSS_C_NT_EXPORT_NAME . +.Pp +In GSS-API an contiguous string name is stored in a +.Dv gss_buffer_t . +.Pp +Exported names also have the property that they are specified by the +mechanism itself and compatible between different GSS-API +implementations. +.El +.Sh ACCESS CONTROL +There are two ways of comparing GSS-API names, either comparing two +internal names with each other or two contiguous string names with +either other. +.Pp +To compare two internal names with each other, import (if needed) the +names with +.Fn gss_import_name +into the GSS-API implementation and the compare the imported name with +.Fn gss_compare_name . +.Pp +Importing names can be slow, so when its possible to store exported +names in the access control list, comparing contiguous string name +might be better. +.Pp +when comparing contiguous string name, first export them into a +.Dv GSS_C_NT_EXPORT_NAME +name with +.Fn gss_export_name +and then compare with +.Xr memcmp 3 . +.Pp +Note that there are might be a difference between the two methods of +comparing names. +The first (using +.Fn gss_compare_name ) +will compare to (unauthenticated) names are the same. +The second will compare if a mechanism will authenticate them as the +same principal. +.Pp +For example, if +.Fn gss_import_name +name was used with +.Dv GSS_C_NO_OID +the default syntax is used for all mechanism the GSS-API +implementation supports. +When compare the imported name of +.Dv GSS_C_NO_OID +it may match several mechanism names (MN). +.Pp +The resulting name from +.Fn gss_display_name +must not be used for access control. +.Sh FUNCTIONS +.Fn gss_display_name +takes the gss name in +.Fa input_name +and puts a printable form in +.Fa output_name_buffer . +.Fa output_name_buffer +should be freed when done using +.Fn gss_release_buffer . +.Fa output_name_type +can either be +.Dv NULL +or a pointer to a +.Li gss_OID +and will in the latter case contain the OID type of the name. +The name must only be used for printing. +If access control is needed, see section +.Sx ACCESS CONTROL . +.Pp +.Fn gss_inquire_context +returns information about the context. +Information is available even after the context have expired. +.Fa lifetime_rec +argument is set to +.Dv GSS_C_INDEFINITE +(don't expire) or the number of seconds that the context is still valid. +A value of 0 means that the context is expired. +.Fa mech_type +argument should be considered readonly and must not be released. +.Fa src_name +and +.Fn dest_name +are both mechanims names and must be released with +.Fn gss_release_name +when no longer used. +.Pp +.Nm gss_context_time +will return the amount of time (in seconds) of the context is still +valid. +If its expired +.Fa time_rec +will be set to 0 and +.Dv GSS_S_CONTEXT_EXPIRED +returned. +.Pp +.Fn gss_sign , +.Fn gss_verify , +.Fn gss_seal , +and +.Fn gss_unseal +are part of the GSS-API V1 interface and are obsolete. +The functions should not be used for new applications. +They are provided so that version 1 applications can link against the +library. +.Sh EXTENSIONS +.Fn gss_krb5_ccache_name +sets the internal kerberos 5 credential cache name to +.Fa name . +The old name is returned in +.Fa old_name , +and must not be freed. +The data allocated for +.Fa old_name +is free upon next call to +.Fn gss_krb5_ccache_name . +This function is not threadsafe if +.Fa old_name +argument is used. +.Pp +.Fn gss_krb5_copy_ccache +will extract the krb5 credentials that are transferred from the +initiator to the acceptor when using token delegation in the Kerberos +mechanism. +The acceptor receives the delegated token in the last argument to +.Fn gss_accept_sec_context . +.Pp +.Fn gss_krb5_import_cred +will import the krb5 credentials (both keytab and/or credential cache) +into gss credential so it can be used withing GSS-API. +The +.Fa ccache +is copied by reference and thus shared, so if the credential is destroyed +with +.Fa krb5_cc_destroy , +all users of thep +.Fa gss_cred_id_t +returned by +.Fn gss_krb5_import_ccache +will fail. +.Pp +.Fn gsskrb5_register_acceptor_identity +sets the Kerberos 5 filebased keytab that the acceptor will use. The +.Fa identifier +is the file name. +.Pp +.Fn gsskrb5_extract_authz_data_from_sec_context +extracts the Kerberos authorizationdata that may be stored within the +context. +Tha caller must free the returned buffer +.Fa ad_data +with +.Fn gss_release_buffer +upon success. +.Pp +.Fn gss_krb5_get_tkt_flags +return the ticket flags for the kerberos ticket receive when +authenticating the initiator. +Only valid on the acceptor context. +.Pp +.Fn gss_krb5_compat_des3_mic +turns on or off the compatibility with older version of Heimdal using +des3 get and verify mic, this is way to programmatically set the +[gssapi]broken_des3_mic and [gssapi]correct_des3_mic flags (see +COMPATIBILITY section in +.Xr gssapi 3 ) . +If the CPP symbol +.Dv GSS_C_KRB5_COMPAT_DES3_MIC +is present, +.Fn gss_krb5_compat_des3_mic +exists. +.Fn gss_krb5_compat_des3_mic +will be removed in a later version of the GSS-API library. +.Sh SEE ALSO +.Xr gssapi 3 , +.Xr krb5 3 , +.Xr krb5_ccache 3 , +.Xr kerberos 8 diff --git a/third_party/heimdal/lib/gssapi/gssapi.3 b/third_party/heimdal/lib/gssapi/gssapi.3 new file mode 100644 index 0000000..089f751 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi.3 @@ -0,0 +1,172 @@ +.\" Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id$ +.\" +.Dd April 20, 2005 +.Dt GSSAPI 3 +.Os +.Sh NAME +.Nm gssapi +.Nd Generic Security Service Application Program Interface library +.Sh LIBRARY +GSS-API Library (libgssapi, -lgssapi) +.Sh DESCRIPTION +The Generic Security Service Application Program Interface (GSS-API) +provides security services to callers in a generic fashion, +supportable with a range of underlying mechanisms and technologies and +hence allowing source-level portability of applications to different +environments. +.Pp +The GSS-API implementation in Heimdal implements the Kerberos 5 and +the SPNEGO GSS-API security mechanisms. +.Sh LIST OF FUNCTIONS +These functions constitute the gssapi library, +.Em libgssapi . +Declarations for these functions may be obtained from the include file +.Pa gssapi.h . +.Bl -column -compact +.It Sy Name/Page +.It Xr gss_accept_sec_context 3 +.It Xr gss_acquire_cred 3 +.It Xr gss_add_cred 3 +.It Xr gss_add_oid_set_member 3 +.It Xr gss_canonicalize_name 3 +.It Xr gss_compare_name 3 +.It Xr gss_context_time 3 +.It Xr gss_create_empty_oid_set 3 +.It Xr gss_delete_sec_context 3 +.It Xr gss_display_name 3 +.It Xr gss_display_status 3 +.It Xr gss_duplicate_name 3 +.It Xr gss_export_name 3 +.It Xr gss_export_sec_context 3 +.It Xr gss_get_mic 3 +.It Xr gss_import_name 3 +.It Xr gss_import_sec_context 3 +.It Xr gss_indicate_mechs 3 +.It Xr gss_init_sec_context 3 +.It Xr gss_inquire_context 3 +.It Xr gss_inquire_cred 3 +.It Xr gss_inquire_cred_by_mech 3 +.It Xr gss_inquire_mechs_for_name 3 +.It Xr gss_inquire_names_for_mech 3 +.It Xr gss_krb5_ccache_name 3 +.It Xr gss_krb5_compat_des3_mic 3 +.It Xr gss_krb5_copy_ccache 3 +.It Xr gss_krb5_extract_authz_data_from_sec_context 3 +.It Xr gss_krb5_import_ccache 3 +.It Xr gss_process_context_token 3 +.It Xr gss_release_buffer 3 +.It Xr gss_release_cred 3 +.It Xr gss_release_name 3 +.It Xr gss_release_oid_set 3 +.It Xr gss_seal 3 +.It Xr gss_sign 3 +.It Xr gss_test_oid_set_member 3 +.It Xr gss_unseal 3 +.It Xr gss_unwrap 3 +.It Xr gss_verify 3 +.It Xr gss_verify_mic 3 +.It Xr gss_wrap 3 +.It Xr gss_wrap_size_limit 3 +.El +.Sh COMPATIBILITY +The +.Nm Heimdal +GSS-API implementation had a bug in releases before 0.6 that made it +fail to inter-operate when using DES3 with other GSS-API +implementations when using +.Fn gss_get_mic +/ +.Fn gss_verify_mic . +It is possible to modify the behavior of the generator of the MIC with +the +.Pa krb5.conf +configuration file so that old clients/servers will still +work. +.Pp +New clients/servers will try both the old and new MIC in Heimdal 0.6. +In 0.7 it will check only if configured - the compatibility code will +be removed in 0.8. +.Pp +Heimdal 0.6 still generates by default the broken GSS-API DES3 mic, +this will change in 0.7 to generate correct des3 mic. +.Pp +To turn on compatibility with older clients and servers, change the +.Nm [gssapi] +.Ar broken_des3_mic +in +.Pa krb5.conf +that contains a list of globbing expressions that will be matched +against the server name. +To turn off generation of the old (incompatible) mic of the MIC use +.Nm [gssapi] +.Ar correct_des3_mic . +.Pp +If a match for a entry is in both +.Nm [gssapi] +.Ar correct_des3_mic +and +.Nm [gssapi] +.Ar broken_des3_mic , +the later will override. +.Pp +This config option modifies behaviour for both clients and servers. +.Pp +Microsoft implemented SPNEGO to Windows2000, however, they managed to +get it wrong, their implementation didn't fill in the MechListMIC in +the reply token with the right content. +There is a work around for this problem, but not all implementation +support it. +.Pp +Heimdal defaults to correct SPNEGO when the the kerberos +implementation uses CFX, or when it is configured by the user. +To turn on compatibility with peers, use option +.Nm [gssapi] +.Ar require_mechlist_mic . +.Sh EXAMPLES +.Bd -literal -offset indent +[gssapi] + broken_des3_mic = cvs/*@SU.SE + broken_des3_mic = host/*@E.KTH.SE + correct_des3_mic = host/*@SU.SE + require_mechlist_mic = host/*@SU.SE +.Ed +.Sh BUGS +All of 0.5.x versions of +.Nm heimdal +had broken token delegations in the client side, the server side was +correct. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5.conf 5 , +.Xr kerberos 8 diff --git a/third_party/heimdal/lib/gssapi/gssapi.h b/third_party/heimdal/lib/gssapi/gssapi.h new file mode 100644 index 0000000..d2f039a --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef GSSAPI_H_ +#define GSSAPI_H_ + +#include <gssapi/gssapi.h> + +#endif diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi.h new file mode 100644 index 0000000..726543f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi.h @@ -0,0 +1,1281 @@ +/* + * Copyright (c) 1997 - 2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef GSSAPI_GSSAPI_H_ +#define GSSAPI_GSSAPI_H_ + +/* + * First, include stddef.h to get size_t defined. + */ +#include <stdarg.h> +#include <stddef.h> + +#include <krb5-types.h> + +#ifndef BUILD_GSSAPI_LIB +#if defined(_WIN32) +#define GSSAPI_LIB_FUNCTION __declspec(dllimport) +#define GSSAPI_LIB_CALL __stdcall +#define GSSAPI_LIB_VARIABLE __declspec(dllimport) +#else +#define GSSAPI_LIB_FUNCTION +#define GSSAPI_LIB_CALL +#define GSSAPI_LIB_VARIABLE +#endif +#endif + +#ifndef GSSAPI_DEPRECATED_FUNCTION +#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 ))) +#define GSSAPI_DEPRECATED_FUNCTION(X) __attribute__((deprecated)) +#else +#define GSSAPI_DEPRECATED_FUNCTION(X) +#endif +#endif + +/* Compatiblity with MIT Kerberos on the Mac */ +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(push,2) +#endif + +#ifdef __cplusplus +#define GSSAPI_CPP_START extern "C" { +#define GSSAPI_CPP_END } +#else +#define GSSAPI_CPP_START +#define GSSAPI_CPP_END +#endif + +#ifdef _WIN32 +#define GSSAPI_CALLCONV __stdcall +#else +#define GSSAPI_CALLCONV +#endif + +/* + * Now define the three implementation-dependent types. + */ + +typedef uint32_t OM_uint32; +typedef uint64_t OM_uint64; + +typedef uint32_t gss_uint32; + +struct gss_name_t_desc_struct; +typedef struct gss_name_t_desc_struct *gss_name_t; +typedef const struct gss_name_t_desc_struct *gss_const_name_t; + +struct gss_ctx_id_t_desc_struct; +typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t; +typedef const struct gss_ctx_id_t_desc_struct *gss_const_ctx_id_t; + +typedef struct gss_OID_desc_struct { + OM_uint32 length; + void *elements; +} gss_OID_desc, *gss_OID; +typedef const gss_OID_desc * gss_const_OID; + +typedef struct gss_OID_set_desc_struct { + size_t count; + gss_OID elements; +} gss_OID_set_desc, *gss_OID_set; +typedef const gss_OID_set_desc * gss_const_OID_set; + +typedef int gss_cred_usage_t; + +struct gss_cred_id_t_desc_struct; +typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t; +typedef const struct gss_cred_id_t_desc_struct *gss_const_cred_id_t; + +typedef struct gss_buffer_desc_struct { + size_t length; + void *value; +} gss_buffer_desc, *gss_buffer_t; +typedef const gss_buffer_desc * gss_const_buffer_t; + +typedef struct gss_channel_bindings_struct { + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; +} *gss_channel_bindings_t; +typedef const struct gss_channel_bindings_struct *gss_const_channel_bindings_t; + +/* GGF extension data types */ +typedef struct gss_buffer_set_desc_struct { + size_t count; + gss_buffer_desc *elements; +} gss_buffer_set_desc, *gss_buffer_set_t; + +typedef struct gss_iov_buffer_desc_struct { + OM_uint32 type; + gss_buffer_desc buffer; +} gss_iov_buffer_desc, *gss_iov_buffer_t; + +/* Credential store extensions */ +typedef struct gss_key_value_element_struct { + const char *key; + const char *value; +} gss_key_value_element_desc; + +typedef struct gss_key_value_set_struct { + OM_uint32 count; /* should be size_t, but for MIT compat */ + gss_key_value_element_desc *elements; +} gss_key_value_set_desc, *gss_key_value_set_t; + +typedef const gss_key_value_set_desc *gss_const_key_value_set_t; + +/* + * For now, define a QOP-type as an OM_uint32 + */ +typedef OM_uint32 gss_qop_t; + + +/* + * Flag bits for context-level services. + */ +#define GSS_C_DELEG_FLAG 1 +#define GSS_C_MUTUAL_FLAG 2 +#define GSS_C_REPLAY_FLAG 4 +#define GSS_C_SEQUENCE_FLAG 8 +#define GSS_C_CONF_FLAG 16 +#define GSS_C_INTEG_FLAG 32 +#define GSS_C_ANON_FLAG 64 +#define GSS_C_PROT_READY_FLAG 128 +#define GSS_C_TRANS_FLAG 256 + +#define GSS_C_CHANNEL_BOUND_FLAG 2048 +#define GSS_C_DCE_STYLE 4096 +#define GSS_C_IDENTIFY_FLAG 8192 +#define GSS_C_EXTENDED_ERROR_FLAG 16384 +#define GSS_C_DELEG_POLICY_FLAG 32768 + +/* + * Credential usage options + */ +#define GSS_C_BOTH 0 +#define GSS_C_INITIATE 1 +#define GSS_C_ACCEPT 2 + +/* + * Status code types for gss_display_status + */ +#define GSS_C_GSS_CODE 1 +#define GSS_C_MECH_CODE 2 + +/* + * The constant definitions for channel-bindings address families + */ +#define GSS_C_AF_UNSPEC 0 +#define GSS_C_AF_LOCAL 1 +#define GSS_C_AF_INET 2 +#define GSS_C_AF_IMPLINK 3 +#define GSS_C_AF_PUP 4 +#define GSS_C_AF_CHAOS 5 +#define GSS_C_AF_NS 6 +#define GSS_C_AF_NBS 7 +#define GSS_C_AF_ECMA 8 +#define GSS_C_AF_DATAKIT 9 +#define GSS_C_AF_CCITT 10 +#define GSS_C_AF_SNA 11 +#define GSS_C_AF_DECnet 12 +#define GSS_C_AF_DLI 13 +#define GSS_C_AF_LAT 14 +#define GSS_C_AF_HYLINK 15 +#define GSS_C_AF_APPLETALK 16 +#define GSS_C_AF_BSC 17 +#define GSS_C_AF_DSS 18 +#define GSS_C_AF_OSI 19 +#define GSS_C_AF_X25 21 +#define GSS_C_AF_INET6 24 + +#define GSS_C_AF_NULLADDR 255 + +/* + * Various Null values + */ +#define GSS_C_NO_NAME ((gss_name_t) 0) +#define GSS_C_NO_BUFFER ((gss_buffer_t) 0) +#define GSS_C_NO_BUFFER_SET ((gss_buffer_set_t) 0) +#define GSS_C_NO_OID ((gss_OID) 0) +#define GSS_C_NO_OID_SET ((gss_OID_set) 0) +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) +#define GSS_C_EMPTY_BUFFER {0, NULL} +#define GSS_C_EMPTY_BUFFER_SET {0, NULL} +#define GSS_C_NO_IOV_BUFFER ((gss_iov_buffer_t)0) +#define GSS_C_NO_CRED_STORE ((gss_key_value_set_t)0) + +/* + * Some alternate names for a couple of the above + * values. These are defined for V1 compatibility. + */ +#define GSS_C_NULL_OID GSS_C_NO_OID +#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET + +/* + * Define the default Quality of Protection for per-message + * services. Note that an implementation that offers multiple + * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero + * (as done here) to mean "default protection", or to a specific + * explicit QOP value. However, a value of 0 should always be + * interpreted by a GSSAPI implementation as a request for the + * default protection level. + */ +#define GSS_C_QOP_DEFAULT 0 + +#define GSS_KRB5_CONF_C_QOP_DES 0x0100 +#define GSS_KRB5_CONF_C_QOP_DES3_KD 0x0200 + +/* + * Expiration time of 2^32-1 seconds means infinite lifetime for a + * credential or security context + */ +#define GSS_C_INDEFINITE 0xfffffffful + +/* + * Type of gss_wrap_iov()/gss_unwrap_iov(). + */ + +#define GSS_IOV_BUFFER_TYPE_EMPTY 0 +#define GSS_IOV_BUFFER_TYPE_DATA 1 +#define GSS_IOV_BUFFER_TYPE_HEADER 2 +#define GSS_IOV_BUFFER_TYPE_MECH_PARAMS 3 + +#define GSS_IOV_BUFFER_TYPE_TRAILER 7 +#define GSS_IOV_BUFFER_TYPE_PADDING 9 +#define GSS_IOV_BUFFER_TYPE_STREAM 10 +#define GSS_IOV_BUFFER_TYPE_SIGN_ONLY 11 + +#define GSS_IOV_BUFFER_TYPE_FLAG_MASK 0xffff0000 +#define GSS_IOV_BUFFER_FLAG_ALLOCATE 0x00010000 +#define GSS_IOV_BUFFER_FLAG_ALLOCATED 0x00020000 + +#define GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE 0x00010000 /* old name */ +#define GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED 0x00020000 /* old name */ + +#define GSS_IOV_BUFFER_TYPE(_t) ((_t) & ~GSS_IOV_BUFFER_TYPE_FLAG_MASK) +#define GSS_IOV_BUFFER_FLAGS(_t) ((_t) & GSS_IOV_BUFFER_TYPE_FLAG_MASK) + +GSSAPI_CPP_START + +#include <gssapi/gssapi_oid.h> + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_user_name_oid_desc; +#define GSS_C_NT_USER_NAME (&__gss_c_nt_user_name_oid_desc) + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_machine_uid_name_oid_desc; +#define GSS_C_NT_MACHINE_UID_NAME (&__gss_c_nt_machine_uid_name_oid_desc) + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_string_uid_name_oid_desc; +#define GSS_C_NT_STRING_UID_NAME (&__gss_c_nt_string_uid_name_oid_desc) + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)). The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc. This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_hostbased_service_x_oid_desc; +#define GSS_C_NT_HOSTBASED_SERVICE_X (&__gss_c_nt_hostbased_service_x_oid_desc) + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x04"}, corresponding to an + * object-identifier value of {iso(1) member-body(2) + * Unites States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized + * to point to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_hostbased_service_oid_desc; +#define GSS_C_NT_HOSTBASED_SERVICE (&__gss_c_nt_hostbased_service_oid_desc) + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_anonymous_oid_desc; +#define GSS_C_NT_ANONYMOUS (&__gss_c_nt_anonymous_oid_desc) + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_export_name_oid_desc; +#define GSS_C_NT_EXPORT_NAME (&__gss_c_nt_export_name_oid_desc) + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x06"}, corresponding to an + * object-identifier value of {iso(1) identified-organization(3) dod(6) + * internet(1) security(5) nametypes(6) gss-composite-export(6)}. + * The constant GSS_C_NT_COMPOSITE_EXPORT [RFC6680] should be initialized to + * point to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_composite_export_oid_desc; +#define GSS_C_NT_COMPOSITE_EXPORT (&__gss_c_nt_composite_export_oid_desc) + +/* Major status codes */ + +#define GSS_S_COMPLETE 0 + +/* + * Some "helper" definitions to make the status code macros obvious. + */ +#define GSS_C_CALLING_ERROR_OFFSET 24 +#define GSS_C_ROUTINE_ERROR_OFFSET 16 +#define GSS_C_SUPPLEMENTARY_OFFSET 0 +#define GSS_C_CALLING_ERROR_MASK 0377ul +#define GSS_C_ROUTINE_ERROR_MASK 0377ul +#define GSS_C_SUPPLEMENTARY_MASK 0177777ul + +/* + * The macros that test status codes for error conditions. + * Note that the GSS_ERROR() macro has changed slightly from + * the V1 GSSAPI so that it now evaluates its argument + * only once. + */ +#define GSS_CALLING_ERROR(x) \ + (x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) +#define GSS_ROUTINE_ERROR(x) \ + (x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) +#define GSS_SUPPLEMENTARY_INFO(x) \ + (x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) +#define GSS_ERROR(x) \ + (x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + +/* + * Now the actual status code definitions + */ + +/* + * Calling errors: + */ +#define GSS_S_CALL_INACCESSIBLE_READ \ + (1ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_INACCESSIBLE_WRITE \ + (2ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_BAD_STRUCTURE \ + (3ul << GSS_C_CALLING_ERROR_OFFSET) + +/* + * Routine errors: + */ +#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET) + +#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MIC GSS_S_BAD_SIG +#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MECH_ATTR (19ul << GSS_C_ROUTINE_ERROR_OFFSET) + +/* + * Apparently awating spec fix. + */ +#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE + +/* + * Supplementary info bits: + */ +#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) + +/* + * Finally, function prototypes for the GSS-API routines. + */ + +#define GSS_C_OPTION_MASK 0xffff +#define GSS_C_CRED_NO_UI 0x10000 + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_acquire_cred + (OM_uint32 * /*minor_status*/, + gss_const_name_t /*desired_name*/, + OM_uint32 /*time_req*/, + const gss_OID_set /*desired_mechs*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*time_rec*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_cred + (OM_uint32 * /*minor_status*/, + gss_cred_id_t * /*cred_handle*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_init_sec_context + (OM_uint32 * /*minor_status*/, + gss_const_cred_id_t /*initiator_cred_handle*/, + gss_ctx_id_t * /*context_handle*/, + gss_const_name_t /*target_name*/, + const gss_OID /*mech_type*/, + OM_uint32 /*req_flags*/, + OM_uint32 /*time_req*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const gss_buffer_t /*input_token*/, + gss_OID * /*actual_mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * /*time_rec*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_accept_sec_context + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_const_cred_id_t /*acceptor_cred_handle*/, + const gss_buffer_t /*input_token_buffer*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + gss_name_t * /*src_name*/, + gss_OID * /*mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * /*time_rec*/, + gss_cred_id_t * /*delegated_cred_handle*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_process_context_token + (OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + const gss_buffer_t /*token_buffer*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_delete_sec_context + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t /*output_token*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_context_time + (OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + OM_uint32 * /*time_rec*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_get_mic + (OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_verify_mic + (OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * /*qop_state*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_wrap + (OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t /*output_message_buffer*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_unwrap + (OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + gss_qop_t * /*qop_state*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_display_status + (OM_uint32 * /*minor_status*/, + OM_uint32 /*status_value*/, + int /*status_type*/, + const gss_OID /*mech_type*/, + OM_uint32 * /*message_context*/, + gss_buffer_t /*status_string*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_indicate_mechs + (OM_uint32 * /*minor_status*/, + gss_OID_set * /*mech_set*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_compare_name + (OM_uint32 * /*minor_status*/, + gss_const_name_t /*name1*/, + gss_const_name_t /*name2*/, + int * /*name_equal*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_display_name + (OM_uint32 * /*minor_status*/, + gss_const_name_t /*input_name*/, + gss_buffer_t /*output_name_buffer*/, + gss_OID * /*output_name_type*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_import_name + (OM_uint32 * /*minor_status*/, + const gss_buffer_t /*input_name_buffer*/, + const gss_OID /*input_name_type*/, + gss_name_t * /*output_name*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_export_name + (OM_uint32 * /*minor_status*/, + gss_const_name_t /*input_name*/, + gss_buffer_t /*exported_name*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_name + (OM_uint32 * /*minor_status*/, + gss_name_t * /*input_name*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_buffer + (OM_uint32 * /*minor_status*/, + gss_buffer_t /*buffer*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_oid_set + (OM_uint32 * /*minor_status*/, + gss_OID_set * /*set*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_cred + (OM_uint32 * /*minor_status*/, + gss_const_cred_id_t /*cred_handle*/, + gss_name_t * /*name*/, + OM_uint32 * /*lifetime*/, + gss_cred_usage_t * /*cred_usage*/, + gss_OID_set * /*mechanisms*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_context ( + OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + gss_name_t * /*src_name*/, + gss_name_t * /*targ_name*/, + OM_uint32 * /*lifetime_rec*/, + gss_OID * /*mech_type*/, + OM_uint32 * /*ctx_flags*/, + int * /*locally_initiated*/, + int * /*open_context*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_wrap_size_limit ( + OM_uint32 * /*minor_status*/, + gss_const_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 * /*max_input_size*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_add_cred ( + OM_uint32 * /*minor_status*/, + gss_const_cred_id_t /*input_cred_handle*/, + gss_const_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + gss_cred_usage_t /*cred_usage*/, + OM_uint32 /*initiator_time_req*/, + OM_uint32 /*acceptor_time_req*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*initiator_time_rec*/, + OM_uint32 * /*acceptor_time_rec*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_cred_by_mech ( + OM_uint32 * /*minor_status*/, + gss_const_cred_id_t /*cred_handle*/, + const gss_OID /*mech_type*/, + gss_name_t * /*name*/, + OM_uint32 * /*initiator_lifetime*/, + OM_uint32 * /*acceptor_lifetime*/, + gss_cred_usage_t * /*cred_usage*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_export_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t /*interprocess_token*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_import_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*interprocess_token*/, + gss_ctx_id_t * /*context_handle*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_create_empty_oid_set ( + OM_uint32 * /*minor_status*/, + gss_OID_set * /*oid_set*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_add_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member_oid*/, + gss_OID_set * /*oid_set*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_test_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member*/, + const gss_OID_set /*set*/, + int * /*present*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_names_for_mech ( + OM_uint32 * /*minor_status*/, + const gss_OID /*mechanism*/, + gss_OID_set * /*name_types*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_mechs_for_name ( + OM_uint32 * /*minor_status*/, + gss_const_name_t /*input_name*/, + gss_OID_set * /*mech_types*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_canonicalize_name ( + OM_uint32 * /*minor_status*/, + gss_const_name_t /*input_name*/, + const gss_OID /*mech_type*/, + gss_name_t * /*output_name*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_duplicate_name ( + OM_uint32 * /*minor_status*/, + gss_const_name_t /*src_name*/, + gss_name_t * /*dest_name*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_duplicate_oid ( + OM_uint32 * /* minor_status */, + gss_OID /* src_oid */, + gss_OID * /* dest_oid */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_duplicate_oid_set ( + OM_uint32 * /* minor_status */, + gss_OID_set /* src_oid */, + gss_OID_set * /* dest_oid */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_oid + (OM_uint32 * /*minor_status*/, + gss_OID * /* oid */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_oid_to_str( + OM_uint32 * /*minor_status*/, + gss_OID /* oid */, + gss_buffer_t /* str */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_sec_context_by_oid( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_set_cred_option (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID object, + const gss_buffer_t value); + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_oid_equal(gss_const_OID a, gss_const_OID b); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_cred_by_oid(OM_uint32 *minor_status, + gss_const_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +/* + * RFC 4401 + */ + +#define GSS_C_PRF_KEY_FULL 0 +#define GSS_C_PRF_KEY_PARTIAL 1 + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_pseudo_random + (OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_store_cred(OM_uint32 * /* minor_status */, + gss_cred_id_t /* input_cred_handle */, + gss_cred_usage_t /* cred_usage */, + const gss_OID /* desired_mech */, + OM_uint32 /* overwrite_cred */, + OM_uint32 /* default_cred */, + gss_OID_set * /* elements_stored */, + gss_cred_usage_t * /* cred_usage_stored */); + + +/* + * Query functions + */ + +typedef struct { + size_t header; /**< size of header */ + size_t trailer; /**< size of trailer */ + size_t max_msg_size; /**< maximum message size */ + size_t buffers; /**< extra GSS_IOV_BUFFER_TYPE_EMPTY buffer to pass */ + size_t blocksize; /**< Specificed optimal size of messages, also + is the maximum padding size + (GSS_IOV_BUFFER_TYPE_PADDING) */ +} gss_context_stream_sizes; + +extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_attr_stream_sizes_oid_desc; +#define GSS_C_ATTR_STREAM_SIZES (&__gss_c_attr_stream_sizes_oid_desc) + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_context_query_attributes(OM_uint32 * /* minor_status */, + gss_const_ctx_id_t /* context_handle */, + const gss_OID /* attribute */, + void * /*data*/, + size_t /* len */); +/* + * The following routines are obsolete variants of gss_get_mic, + * gss_verify_mic, gss_wrap and gss_unwrap. They should be + * provided by GSSAPI V2 implementations for backwards + * compatibility with V1 applications. Distinct entrypoints + * (as opposed to #defines) should be provided, both to allow + * GSSAPI V1 applications to link against GSSAPI V2 implementations, + * and to retain the slight parameter type differences between the + * obsolete versions of these routines and their current forms. + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_sign + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*qop_req*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/ + ) GSSAPI_DEPRECATED_FUNCTION("Use gss_get_mic"); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_verify + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*token_buffer*/, + int * /*qop_state*/ + ) GSSAPI_DEPRECATED_FUNCTION("Use gss_verify_mic"); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_seal + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + int /*qop_req*/, + gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t /*output_message_buffer*/ + ) GSSAPI_DEPRECATED_FUNCTION("Use gss_wrap"); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_unseal + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + int * /*qop_state*/ + ) GSSAPI_DEPRECATED_FUNCTION("Use gss_unwrap"); + +/** + * + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_encapsulate_token(gss_const_buffer_t /* input_token */, + gss_const_OID /* oid */, + gss_buffer_t /* output_token */); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_decapsulate_token(gss_const_buffer_t /* input_token */, + gss_const_OID /* oid */, + gss_buffer_t /* output_token */); + + + +/* + * AEAD support + */ + +/* + * GSS_IOV + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_iov(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *, + gss_iov_buffer_desc *, int); + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_unwrap_iov(OM_uint32 *, gss_ctx_id_t, int *, gss_qop_t *, + gss_iov_buffer_desc *, int); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_iov_length(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *, + gss_iov_buffer_desc *, int); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_iov_buffer(OM_uint32 *, gss_iov_buffer_desc *, int); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_aead(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, + gss_buffer_t, gss_buffer_t, int *, gss_buffer_t); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_unwrap_aead(OM_uint32 *, gss_ctx_id_t, gss_buffer_t, + gss_buffer_t, gss_buffer_t, int *, gss_qop_t *); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_export_cred(OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred_handle */, + gss_buffer_t /* cred_token */); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_import_cred(OM_uint32 * /* minor_status */, + gss_buffer_t /* cred_token */, + gss_cred_id_t * /* cred_handle */); + +/* + * mech option + */ + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_mo_set(gss_const_OID mech, gss_const_OID option, + int enable, gss_buffer_t value); + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_mo_get(gss_const_OID mech, gss_const_OID option, gss_buffer_t value); + +GSSAPI_LIB_FUNCTION void GSSAPI_LIB_CALL +gss_mo_list(gss_const_OID mech, gss_OID_set *options); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_mo_name(gss_const_OID mech, gss_const_OID options, gss_buffer_t name); + +/* + * SASL glue functions and mech inquire + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_saslname_for_mech(OM_uint32 *minor_status, + const gss_OID desired_mech, + gss_buffer_t sasl_mech_name, + gss_buffer_t mech_name, + gss_buffer_t mech_description); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_mech_for_saslname(OM_uint32 *minor_status, + const gss_buffer_t sasl_mech_name, + gss_OID *mech_type); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_indicate_mechs_by_attrs(OM_uint32 * minor_status, + gss_const_OID_set desired_mech_attrs, + gss_const_OID_set except_mech_attrs, + gss_const_OID_set critical_mech_attrs, + gss_OID_set *mechs); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_attrs_for_mech(OM_uint32 * minor_status, + gss_const_OID mech, + gss_OID_set *mech_attr, + gss_OID_set *known_mech_attrs); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_display_mech_attr(OM_uint32 * minor_status, + gss_const_OID mech_attr, + gss_buffer_t name, + gss_buffer_t short_desc, + gss_buffer_t long_desc); + +/* + * Solaris compat + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_acquire_cred_with_password + (OM_uint32 * /*minor_status*/, + gss_const_name_t /*desired_name*/, + const gss_buffer_t /*password*/, + OM_uint32 /*time_req*/, + const gss_OID_set /*desired_mechs*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*time_rec*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_add_cred_with_password ( + OM_uint32 * /*minor_status*/, + gss_const_cred_id_t /*input_cred_handle*/, + gss_const_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + const gss_buffer_t /*password*/, + gss_cred_usage_t /*cred_usage*/, + OM_uint32 /*initiator_time_req*/, + OM_uint32 /*acceptor_time_req*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*initiator_time_rec*/, + OM_uint32 * /*acceptor_time_rec*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_localname( + OM_uint32 *minor, + gss_const_name_t name, + const gss_OID mech_type, + gss_buffer_t localname); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_pname_to_uid( + OM_uint32 *minor, + gss_const_name_t name, + const gss_OID mech_type, + uid_t *uidOut); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_authorize_localname( + OM_uint32 *minor, + gss_const_name_t name, + gss_const_name_t user); + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_userok(gss_const_name_t name, + const char *user); + +extern GSSAPI_LIB_VARIABLE gss_buffer_desc __gss_c_attr_local_login_user; +#define GSS_C_ATTR_LOCAL_LOGIN_USER (&__gss_c_attr_local_login_user) + +/* + * Naming extensions + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_display_name_ext ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_OID, /* display_as_name_type */ + gss_buffer_t /* display_name */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_name ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int *, /* name_is_MN */ + gss_OID *, /* MN_mech */ + gss_buffer_set_t * /* attrs */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_get_name_attribute ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* attr */ + int *, /* authenticated */ + int *, /* complete */ + gss_buffer_t, /* value */ + gss_buffer_t, /* display_value */ + int * /* more */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_set_name_attribute ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int, /* complete */ + gss_buffer_t, /* attr */ + gss_buffer_t /* value */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_delete_name_attribute ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* attr */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_export_name_composite ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* exp_composite_name */ + ); + +/* + * Other extensions + */ + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_duplicate_cred ( + OM_uint32 * /*minor_status*/, + gss_const_cred_id_t /*input_cred_handle*/, + gss_cred_id_t * /*output_cred_handle*/ + ); + +/* Return a mechanism short name from an OID */ +GSSAPI_LIB_FUNCTION const char * GSSAPI_LIB_CALL +gss_oid_to_name(gss_const_OID oid); + +/* Return a mechanism OID from a short name or dotted OID */ +GSSAPI_LIB_FUNCTION gss_OID GSSAPI_LIB_CALL +gss_name_to_oid(const char *name); + +/* + * Credential store extensions + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_acquire_cred_from( + OM_uint32 * /* minor_status */, + gss_const_name_t /* desired_name */, + OM_uint32 /* time_req */, + const gss_OID_set /* desired_mechs */, + gss_cred_usage_t /* cred_usage */, + gss_const_key_value_set_t /* cred_store */, + gss_cred_id_t * /* output_cred_handle */, + gss_OID_set * /* actual_mechs */, + OM_uint32 * /* time_rec */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_add_cred_from( + OM_uint32 * /* minor_status */, + gss_cred_id_t /* input_cred_handle */, + gss_const_name_t /* desired_name */, + const gss_OID /* desired_mech */, + gss_cred_usage_t /* cred_usage */, + OM_uint32 /* initiator_time_req */, + OM_uint32 /* acceptor_time_req */, + gss_const_key_value_set_t /* cred_store */, + gss_cred_id_t * /* output_cred_handle */, + gss_OID_set * /* actual_mechs */, + OM_uint32 * /* initiator_time_rec */, + OM_uint32 * /*acceptor_time_rec */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_store_cred_into( + OM_uint32 * /* minor_status */, + gss_const_cred_id_t /* input_cred_handle */, + gss_cred_usage_t /* input_usage */, + const gss_OID /* desired_mech */, + OM_uint32 /* overwrite_cred */, + OM_uint32 /* default_cred */, + gss_const_key_value_set_t /* cred_store */, + gss_OID_set * /* elements_stored */, + gss_cred_usage_t * /* cred_usage_stored */ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_store_cred_into2( + OM_uint32 * /* minor_status */, + gss_const_cred_id_t /* input_cred_handle */, + gss_cred_usage_t /* input_usage */, + const gss_OID /* desired_mech */, + OM_uint32 /* store_cred_flags */, + gss_const_key_value_set_t /* cred_store */, + gss_OID_set * /* elements_stored */, + gss_cred_usage_t * /* cred_usage_stored */, + gss_buffer_set_t * /* env */ + ); + +enum gss_store_cred_flags { + GSS_C_STORE_CRED_DEFAULT = 1, + GSS_C_STORE_CRED_OVERWRITE = 2, + GSS_C_STORE_CRED_SET_PROCESS = 4, +}; +#define GSS_C_STORE_CRED_DEFAULT GSS_C_STORE_CRED_DEFAULT +#define GSS_C_STORE_CRED_OVERWRITE GSS_C_STORE_CRED_OVERWRITE +#define GSS_C_STORE_CRED_SET_PROCESS GSS_C_STORE_CRED_SET_PROCESS + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_CALLCONV +gss_set_neg_mechs( + OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred_handle */, + const gss_OID_set /* mech_list */); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_CALLCONV +gss_get_neg_mechs( + OM_uint32 * /* minor_status */, + gss_const_cred_id_t /* cred_handle */, + gss_OID_set * /* mech_list */); + +GSSAPI_LIB_FUNCTION void GSSAPI_LIB_CALL +gss_set_log_function(void *ctx, void (*func)(void * ctx, int level, const char *fmt, va_list)); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_destroy_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle); + +/* + * S4UProxy and S4USelf extensions. + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_CALLCONV +gss_acquire_cred_impersonate_name( + OM_uint32 * /* minor_status */, + gss_const_cred_id_t /* icred */, + gss_const_name_t /* desired_name */, + OM_uint32 /* time_req */, + gss_OID_set /* desired_mechs */, + gss_cred_usage_t /* cred_usage */, + gss_cred_id_t * /* output_cred */, + gss_OID_set * /* actual_mechs */, + OM_uint32 * /* time_rec */ + ); + +GSSAPI_CPP_END + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(pop) +#endif + +#undef GSSAPI_DEPRECATED_FUNCTION + +#endif /* GSSAPI_GSSAPI_H_ */ diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h new file mode 100644 index 0000000..818042f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef GSSAPI_KRB5_H_ +#define GSSAPI_KRB5_H_ + +#include <gssapi.h> +#include <gssapi/gssapi_oid.h> + +GSSAPI_CPP_START + +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif + +#ifndef GSSKRB5_FUNCTION_DEPRECATED +#define GSSKRB5_FUNCTION_DEPRECATED __attribute__((deprecated)) +#endif + + +/* + * This is for kerberos5 names. + */ + +extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_nt_principal_name_oid_desc; +#define GSS_KRB5_NT_PRINCIPAL_NAME (&__gss_krb5_nt_principal_name_oid_desc) + +#define GSS_KRB5_NT_USER_NAME (&__gss_c_nt_user_name_oid_desc) +#define GSS_KRB5_NT_MACHINE_UID_NAME (&__gss_c_nt_machine_uid_name_oid_desc) +#define GSS_KRB5_NT_STRING_UID_NAME (&__gss_c_nt_string_uid_name_oid_desc) + +/* for compatibility with MIT api */ + +#define gss_mech_krb5 GSS_KRB5_MECHANISM +#define gss_krb5_nt_general_name GSS_KRB5_NT_PRINCIPAL_NAME + +/* + * kerberos mechanism specific functions + */ + +struct krb5_keytab_data; +struct krb5_ccache_data; +struct Principal; + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_ccache_name(OM_uint32 * /*minor_status*/, + const char * /*name */, + const char ** /*out_name */); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gsskrb5_register_acceptor_identity + (const char * /*identity*/); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL krb5_gss_register_acceptor_identity + (const char * /*identity*/); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_krb5_copy_ccache + (OM_uint32 * /*minor*/, + gss_cred_id_t /*cred*/, + struct krb5_ccache_data * /*out*/); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_import_cred(OM_uint32 * /*minor*/, + struct krb5_ccache_data * /*in*/, + struct Principal * /*keytab_principal*/, + struct krb5_keytab_data * /*keytab*/, + gss_cred_id_t * /*out*/); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_krb5_get_tkt_flags + (OM_uint32 * /*minor*/, + gss_ctx_id_t /*context_handle*/, + OM_uint32 * /*tkt_flags*/); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_extract_authz_data_from_sec_context + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*ad_type*/, + gss_buffer_t /*ad_data*/); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_dns_canonicalize(int); + +struct gsskrb5_send_to_kdc { + void *func; + void *ptr; +}; + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *) + GSSKRB5_FUNCTION_DEPRECATED; + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_default_realm(const char *); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *, gss_ctx_id_t, time_t *); + +struct EncryptionKey; + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_extract_service_keyblock(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + struct EncryptionKey **out); +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + struct EncryptionKey **out); +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_get_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + struct EncryptionKey **out); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_time_offset(int); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_get_time_offset(int *); + +struct gsskrb5_krb5_plugin { + int type; + char *name; + void *symbol; +}; + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_plugin_register(struct gsskrb5_krb5_plugin *); + + +/* + * Lucid - NFSv4 interface to GSS-API KRB5 to expose key material to + * do GSS content token handling in-kernel. + */ + +typedef struct gss_krb5_lucid_key { + OM_uint32 type; + OM_uint32 length; + void * data; +} gss_krb5_lucid_key_t; + +typedef struct gss_krb5_rfc1964_keydata { + OM_uint32 sign_alg; + OM_uint32 seal_alg; + gss_krb5_lucid_key_t ctx_key; +} gss_krb5_rfc1964_keydata_t; + +typedef struct gss_krb5_cfx_keydata { + OM_uint32 have_acceptor_subkey; + gss_krb5_lucid_key_t ctx_key; + gss_krb5_lucid_key_t acceptor_subkey; +} gss_krb5_cfx_keydata_t; + +typedef struct gss_krb5_lucid_context_v1 { + OM_uint32 version; + OM_uint32 initiate; + OM_uint32 endtime; + OM_uint64 send_seq; + OM_uint64 recv_seq; + OM_uint32 protocol; + gss_krb5_rfc1964_keydata_t rfc1964_kd; + gss_krb5_cfx_keydata_t cfx_kd; +} gss_krb5_lucid_context_v1_t; + +typedef struct gss_krb5_lucid_context_version { + OM_uint32 version; /* Structure version number */ +} gss_krb5_lucid_context_version_t; + +/* + * Function declarations + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx); + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, + void *kctx); + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t cred, + OM_uint32 num_enctypes, + int32_t *enctypes); + +#define GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "urn:ietf:kerberos:nameattr-" + +GSSAPI_CPP_END + +#endif /* GSSAPI_SPNEGO_H_ */ diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi_netlogon.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi_netlogon.h new file mode 100644 index 0000000..52201a6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi_netlogon.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006 - 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef GSSAPI_NETLOGON_H_ +#define GSSAPI_NETLOGON_H_ + +#include <gssapi.h> + +GSSAPI_CPP_START + +extern GSSAPI_LIB_VARIABLE gss_OID GSS_NETLOGON_MECHANISM; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_NETLOGON_NT_NETBIOS_DNS_NAME; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_NETLOGON_SET_SESSION_KEY_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_NETLOGON_SET_SIGN_ALGORITHM_X; + +GSSAPI_CPP_END + +#endif /* GSSAPI_NETLOGON_H_ */ diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi_ntlm.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi_ntlm.h new file mode 100644 index 0000000..e37c003 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi_ntlm.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006 - 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef GSSAPI_NTLM_H_ +#define GSSAPI_NTLM_H_ + +#include <gssapi.h> + +#endif /* GSSAPI_NTLM_H_ */ diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi_oid.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi_oid.h new file mode 100644 index 0000000..fabd090 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi_oid.h @@ -0,0 +1,262 @@ +/* Generated file */ +#ifndef GSSAPI_GSSAPI_OID +#define GSSAPI_GSSAPI_OID 1 + + /* contact Love Hörnquist Ã…strand <lha@h5l.org> for new oid arcs */ + /* + * 1.2.752.43.13 Heimdal GSS-API Extensions + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_copy_ccache_x_oid_desc; +#define GSS_KRB5_COPY_CCACHE_X (&__gss_krb5_copy_ccache_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_tkt_flags_x_oid_desc; +#define GSS_KRB5_GET_TKT_FLAGS_X (&__gss_krb5_get_tkt_flags_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_extract_authz_data_from_sec_context_x_oid_desc; +#define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X (&__gss_krb5_extract_authz_data_from_sec_context_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_compat_des3_mic_x_oid_desc; +#define GSS_KRB5_COMPAT_DES3_MIC_X (&__gss_krb5_compat_des3_mic_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_register_acceptor_identity_x_oid_desc; +#define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X (&__gss_krb5_register_acceptor_identity_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_export_lucid_context_x_oid_desc; +#define GSS_KRB5_EXPORT_LUCID_CONTEXT_X (&__gss_krb5_export_lucid_context_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_export_lucid_context_v1_x_oid_desc; +#define GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X (&__gss_krb5_export_lucid_context_v1_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_dns_canonicalize_x_oid_desc; +#define GSS_KRB5_SET_DNS_CANONICALIZE_X (&__gss_krb5_set_dns_canonicalize_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_subkey_x_oid_desc; +#define GSS_KRB5_GET_SUBKEY_X (&__gss_krb5_get_subkey_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_initiator_subkey_x_oid_desc; +#define GSS_KRB5_GET_INITIATOR_SUBKEY_X (&__gss_krb5_get_initiator_subkey_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_acceptor_subkey_x_oid_desc; +#define GSS_KRB5_GET_ACCEPTOR_SUBKEY_X (&__gss_krb5_get_acceptor_subkey_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_send_to_kdc_x_oid_desc; +#define GSS_KRB5_SEND_TO_KDC_X (&__gss_krb5_send_to_kdc_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_authtime_x_oid_desc; +#define GSS_KRB5_GET_AUTHTIME_X (&__gss_krb5_get_authtime_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_service_keyblock_x_oid_desc; +#define GSS_KRB5_GET_SERVICE_KEYBLOCK_X (&__gss_krb5_get_service_keyblock_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_allowable_enctypes_x_oid_desc; +#define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X (&__gss_krb5_set_allowable_enctypes_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_default_realm_x_oid_desc; +#define GSS_KRB5_SET_DEFAULT_REALM_X (&__gss_krb5_set_default_realm_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_ccache_name_x_oid_desc; +#define GSS_KRB5_CCACHE_NAME_X (&__gss_krb5_ccache_name_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_time_offset_x_oid_desc; +#define GSS_KRB5_SET_TIME_OFFSET_X (&__gss_krb5_set_time_offset_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_time_offset_x_oid_desc; +#define GSS_KRB5_GET_TIME_OFFSET_X (&__gss_krb5_get_time_offset_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_plugin_register_x_oid_desc; +#define GSS_KRB5_PLUGIN_REGISTER_X (&__gss_krb5_plugin_register_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_ntlm_get_session_key_x_oid_desc; +#define GSS_NTLM_GET_SESSION_KEY_X (&__gss_ntlm_get_session_key_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_ntlm_oid_desc; +#define GSS_C_NT_NTLM (&__gss_c_nt_ntlm_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_dn_oid_desc; +#define GSS_C_NT_DN (&__gss_c_nt_dn_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_nt_principal_name_referral_oid_desc; +#define GSS_KRB5_NT_PRINCIPAL_NAME_REFERRAL (&__gss_krb5_nt_principal_name_referral_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_avguest_oid_desc; +#define GSS_C_NTLM_AVGUEST (&__gss_c_ntlm_avguest_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_v1_oid_desc; +#define GSS_C_NTLM_V1 (&__gss_c_ntlm_v1_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_v2_oid_desc; +#define GSS_C_NTLM_V2 (&__gss_c_ntlm_v2_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_session_key_oid_desc; +#define GSS_C_NTLM_SESSION_KEY (&__gss_c_ntlm_session_key_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_force_v1_oid_desc; +#define GSS_C_NTLM_FORCE_V1 (&__gss_c_ntlm_force_v1_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_cred_no_ci_flags_x_oid_desc; +#define GSS_KRB5_CRED_NO_CI_FLAGS_X (&__gss_krb5_cred_no_ci_flags_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_import_cred_x_oid_desc; +#define GSS_KRB5_IMPORT_CRED_X (&__gss_krb5_import_cred_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_import_rfc4121_context_x_oid_desc; +#define GSS_KRB5_IMPORT_RFC4121_CONTEXT_X (&__gss_krb5_import_rfc4121_context_x_oid_desc) + + /* glue for gss_inquire_saslname_for_mech */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_sasl_mech_name_oid_desc; +#define GSS_C_MA_SASL_MECH_NAME (&__gss_c_ma_sasl_mech_name_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_name_oid_desc; +#define GSS_C_MA_MECH_NAME (&__gss_c_ma_mech_name_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_description_oid_desc; +#define GSS_C_MA_MECH_DESCRIPTION (&__gss_c_ma_mech_description_oid_desc) + +/* Heimdal mechanisms - 1.2.752.43.14 */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_sasl_digest_md5_mechanism_oid_desc; +#define GSS_SASL_DIGEST_MD5_MECHANISM (&__gss_sasl_digest_md5_mechanism_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_netlogon_mechanism_oid_desc; +#define GSS_NETLOGON_MECHANISM (&__gss_netlogon_mechanism_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_netlogon_set_session_key_x_oid_desc; +#define GSS_NETLOGON_SET_SESSION_KEY_X (&__gss_netlogon_set_session_key_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_netlogon_set_sign_algorithm_x_oid_desc; +#define GSS_NETLOGON_SET_SIGN_ALGORITHM_X (&__gss_netlogon_set_sign_algorithm_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_netlogon_nt_netbios_dns_name_oid_desc; +#define GSS_NETLOGON_NT_NETBIOS_DNS_NAME (&__gss_netlogon_nt_netbios_dns_name_oid_desc) + +/* GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X.128 */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_win2k_pac_x_oid_desc; +#define GSS_C_INQ_WIN2K_PAC_X (&__gss_c_inq_win2k_pac_x_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_sspi_session_key_oid_desc; +#define GSS_C_INQ_SSPI_SESSION_KEY (&__gss_c_inq_sspi_session_key_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_negoex_key_oid_desc; +#define GSS_C_INQ_NEGOEX_KEY (&__gss_c_inq_negoex_key_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_negoex_verify_key_oid_desc; +#define GSS_C_INQ_NEGOEX_VERIFY_KEY (&__gss_c_inq_negoex_verify_key_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_require_mechlist_mic_oid_desc; +#define GSS_C_INQ_REQUIRE_MECHLIST_MIC (&__gss_c_inq_require_mechlist_mic_oid_desc) + +/* + * "Standard" mechs + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_mechanism_oid_desc; +#define GSS_KRB5_MECHANISM (&__gss_krb5_mechanism_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_ntlm_mechanism_oid_desc; +#define GSS_NTLM_MECHANISM (&__gss_ntlm_mechanism_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_spnego_mechanism_oid_desc; +#define GSS_SPNEGO_MECHANISM (&__gss_spnego_mechanism_oid_desc) + + /* From Luke Howard */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_peer_has_buggy_spnego_oid_desc; +#define GSS_C_INQ_PEER_HAS_BUGGY_SPNEGO (&__gss_c_inq_peer_has_buggy_spnego_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_reset_crypto_oid_desc; +#define GSS_C_NTLM_RESET_CRYPTO (&__gss_c_ntlm_reset_crypto_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_negoex_mechanism_oid_desc; +#define GSS_NEGOEX_MECHANISM (&__gss_negoex_mechanism_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_sanon_x25519_mechanism_oid_desc; +#define GSS_SANON_X25519_MECHANISM (&__gss_sanon_x25519_mechanism_oid_desc) + +/* + * OID mappings with name and short description and and slightly longer description + */ +/* + * RFC5587 + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_concrete_oid_desc; +#define GSS_C_MA_MECH_CONCRETE (&__gss_c_ma_mech_concrete_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_pseudo_oid_desc; +#define GSS_C_MA_MECH_PSEUDO (&__gss_c_ma_mech_pseudo_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_composite_oid_desc; +#define GSS_C_MA_MECH_COMPOSITE (&__gss_c_ma_mech_composite_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_nego_oid_desc; +#define GSS_C_MA_MECH_NEGO (&__gss_c_ma_mech_nego_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_glue_oid_desc; +#define GSS_C_MA_MECH_GLUE (&__gss_c_ma_mech_glue_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_not_mech_oid_desc; +#define GSS_C_MA_NOT_MECH (&__gss_c_ma_not_mech_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_deprecated_oid_desc; +#define GSS_C_MA_DEPRECATED (&__gss_c_ma_deprecated_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_not_dflt_mech_oid_desc; +#define GSS_C_MA_NOT_DFLT_MECH (&__gss_c_ma_not_dflt_mech_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_itok_framed_oid_desc; +#define GSS_C_MA_ITOK_FRAMED (&__gss_c_ma_itok_framed_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_auth_init_oid_desc; +#define GSS_C_MA_AUTH_INIT (&__gss_c_ma_auth_init_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_auth_targ_oid_desc; +#define GSS_C_MA_AUTH_TARG (&__gss_c_ma_auth_targ_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_auth_init_init_oid_desc; +#define GSS_C_MA_AUTH_INIT_INIT (&__gss_c_ma_auth_init_init_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_auth_targ_init_oid_desc; +#define GSS_C_MA_AUTH_TARG_INIT (&__gss_c_ma_auth_targ_init_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_auth_init_anon_oid_desc; +#define GSS_C_MA_AUTH_INIT_ANON (&__gss_c_ma_auth_init_anon_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_auth_targ_anon_oid_desc; +#define GSS_C_MA_AUTH_TARG_ANON (&__gss_c_ma_auth_targ_anon_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_deleg_cred_oid_desc; +#define GSS_C_MA_DELEG_CRED (&__gss_c_ma_deleg_cred_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_integ_prot_oid_desc; +#define GSS_C_MA_INTEG_PROT (&__gss_c_ma_integ_prot_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_conf_prot_oid_desc; +#define GSS_C_MA_CONF_PROT (&__gss_c_ma_conf_prot_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mic_oid_desc; +#define GSS_C_MA_MIC (&__gss_c_ma_mic_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_wrap_oid_desc; +#define GSS_C_MA_WRAP (&__gss_c_ma_wrap_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_prot_ready_oid_desc; +#define GSS_C_MA_PROT_READY (&__gss_c_ma_prot_ready_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_replay_det_oid_desc; +#define GSS_C_MA_REPLAY_DET (&__gss_c_ma_replay_det_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_oos_det_oid_desc; +#define GSS_C_MA_OOS_DET (&__gss_c_ma_oos_det_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_cbindings_oid_desc; +#define GSS_C_MA_CBINDINGS (&__gss_c_ma_cbindings_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_pfs_oid_desc; +#define GSS_C_MA_PFS (&__gss_c_ma_pfs_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_compress_oid_desc; +#define GSS_C_MA_COMPRESS (&__gss_c_ma_compress_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_ctx_trans_oid_desc; +#define GSS_C_MA_CTX_TRANS (&__gss_c_ma_ctx_trans_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_negoex_and_spnego_oid_desc; +#define GSS_C_MA_NEGOEX_AND_SPNEGO (&__gss_c_ma_negoex_and_spnego_oid_desc) + +#endif /* GSSAPI_GSSAPI_OID */ diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi_spnego.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi_spnego.h new file mode 100644 index 0000000..8b4519e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi_spnego.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef GSSAPI_SPNEGO_H_ +#define GSSAPI_SPNEGO_H_ + +#include <gssapi.h> + +GSSAPI_CPP_START + +/* + * RFC2478, SPNEGO: + * The security mechanism of the initial + * negotiation token is identified by the Object Identifier + * iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). + */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_spnego_mechanism_oid_desc; +#define GSS_SPNEGO_MECHANISM (&__gss_spnego_mechanism_oid_desc) +#define gss_mech_spnego GSS_SPNEGO_MECHANISM + +/* + * NegoEx extensions, to be implemented by mechanisms + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gssspi_query_mechanism_info( + OM_uint32 * /* minor_status */, + gss_const_OID /* mech_oid */, + unsigned char[16] /* auth_scheme */ +); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gssspi_query_meta_data( + OM_uint32 * /* minor_status */, + gss_const_OID /* mech_oid */, + gss_cred_id_t /* cred_handle */, + gss_ctx_id_t * /* context_handle */, + gss_const_name_t /* targ_name */, + OM_uint32 /* req_flags */, + gss_buffer_t /* meta_data */ +); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gssspi_exchange_meta_data( + OM_uint32 * /* minor_status */, + gss_const_OID /* mech_oid */, + gss_cred_id_t /* cred_handle */, + gss_ctx_id_t * /* context_handle */, + gss_const_name_t /* targ_name */, + OM_uint32 /* req_flags */, + gss_const_buffer_t /* meta_data */ +); + +GSSAPI_CPP_END + +#endif /* GSSAPI_SPNEGO_H_ */ diff --git a/third_party/heimdal/lib/gssapi/gssapi_mech.h b/third_party/heimdal/lib/gssapi/gssapi_mech.h new file mode 100644 index 0000000..ced27b5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gssapi_mech.h @@ -0,0 +1,725 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * Copyright (c) 2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/mech_switch.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#ifndef GSSAPI_MECH_H +#define GSSAPI_MECH_H 1 + +#include <gssapi.h> + +typedef OM_uint32 GSSAPI_CALLCONV _gss_acquire_cred_t + (OM_uint32 *, /* minor_status */ + gss_const_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_release_cred_t + (OM_uint32 *, /* minor_status */ + gss_cred_id_t * /* cred_handle */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_init_sec_context_t + (OM_uint32 *, /* minor_status */ + gss_const_cred_id_t, /* initiator_cred_handle */ + gss_ctx_id_t *, /* context_handle */ + gss_const_name_t, /* target_name */ + const gss_OID, /* mech_type */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + const gss_channel_bindings_t, + /* input_chan_bindings */ + const gss_buffer_t, /* input_token */ + gss_OID *, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 * /* time_rec */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_accept_sec_context_t + (OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_const_cred_id_t, /* acceptor_cred_handle */ + const gss_buffer_t, /* input_token_buffer */ + const gss_channel_bindings_t, + /* input_chan_bindings */ + gss_name_t *, /* src_name */ + gss_OID *, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 *, /* time_rec */ + gss_cred_id_t * /* delegated_cred_handle */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_process_context_token_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + const gss_buffer_t /* token_buffer */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_delete_sec_context_t + (OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t /* output_token */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_context_time_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + OM_uint32 * /* time_rec */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_get_mic_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + const gss_buffer_t, /* message_buffer */ + gss_buffer_t /* message_token */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_verify_mic_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + const gss_buffer_t, /* message_buffer */ + const gss_buffer_t, /* token_buffer */ + gss_qop_t * /* qop_state */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_wrap_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + const gss_buffer_t, /* input_message_buffer */ + int *, /* conf_state */ + gss_buffer_t /* output_message_buffer */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_unwrap_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + const gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* output_message_buffer */ + int *, /* conf_state */ + gss_qop_t * /* qop_state */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_display_status_t + (OM_uint32 *, /* minor_status */ + OM_uint32, /* status_value */ + int, /* status_type */ + const gss_OID, /* mech_type */ + OM_uint32 *, /* message_context */ + gss_buffer_t /* status_string */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_indicate_mechs_t + (OM_uint32 *, /* minor_status */ + gss_OID_set * /* mech_set */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_compare_name_t + (OM_uint32 *, /* minor_status */ + gss_const_name_t, /* name1 */ + gss_const_name_t, /* name2 */ + int * /* name_equal */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_display_name_t + (OM_uint32 *, /* minor_status */ + gss_const_name_t, /* input_name */ + gss_buffer_t, /* output_name_buffer */ + gss_OID * /* output_name_type */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_import_name_t + (OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* input_name_buffer */ + const gss_OID, /* input_name_type */ + gss_name_t * /* output_name */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_export_name_t + (OM_uint32 *, /* minor_status */ + gss_const_name_t, /* input_name */ + gss_buffer_t /* exported_name */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_release_name_t + (OM_uint32 *, /* minor_status */ + gss_name_t * /* input_name */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_cred_t + (OM_uint32 *, /* minor_status */ + gss_const_cred_id_t, /* cred_handle */ + gss_name_t *, /* name */ + OM_uint32 *, /* lifetime */ + gss_cred_usage_t *, /* cred_usage */ + gss_OID_set * /* mechanisms */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_context_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + gss_name_t *, /* src_name */ + gss_name_t *, /* targ_name */ + OM_uint32 *, /* lifetime_rec */ + gss_OID *, /* mech_type */ + OM_uint32 *, /* ctx_flags */ + int *, /* locally_initiated */ + int * /* open */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_wrap_size_limit_t + (OM_uint32 *, /* minor_status */ + gss_const_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + OM_uint32, /* req_output_size */ + OM_uint32 * /* max_input_size */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_add_cred_t ( + OM_uint32 *, /* minor_status */ + gss_const_cred_id_t, /* input_cred_handle */ + gss_const_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 * /* acceptor_time_rec */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_duplicate_cred_t ( + OM_uint32 *, /* minor_status */ + gss_const_cred_id_t, /* input_cred_handle */ + gss_cred_id_t * /* output_cred_handle */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_cred_by_mech_t ( + OM_uint32 *, /* minor_status */ + gss_const_cred_id_t, /* cred_handle */ + const gss_OID, /* mech_type */ + gss_name_t *, /* name */ + OM_uint32 *, /* initiator_lifetime */ + OM_uint32 *, /* acceptor_lifetime */ + gss_cred_usage_t * /* cred_usage */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_export_sec_context_t ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t /* interprocess_token */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_import_sec_context_t ( + OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* interprocess_token */ + gss_ctx_id_t * /* context_handle */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_names_for_mech_t ( + OM_uint32 *, /* minor_status */ + const gss_OID, /* mechanism */ + gss_OID_set * /* name_types */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_mechs_for_name_t ( + OM_uint32 *, /* minor_status */ + gss_const_name_t, /* input_name */ + gss_OID_set * /* mech_types */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_canonicalize_name_t ( + OM_uint32 *, /* minor_status */ + gss_const_name_t, /* input_name */ + const gss_OID, /* mech_type */ + gss_name_t * /* output_name */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_duplicate_name_t ( + OM_uint32 *, /* minor_status */ + gss_const_name_t, /* src_name */ + gss_name_t * /* dest_name */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_sec_context_by_oid_t ( + OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_cred_by_oid_t ( + OM_uint32 *minor_status, + gss_const_cred_id_t cred, + const gss_OID desired_object, + gss_buffer_set_t *data_set + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_set_sec_context_option_t ( + OM_uint32 *minor_status, + gss_ctx_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_set_cred_option_t ( + OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value + ); + + +typedef OM_uint32 GSSAPI_CALLCONV _gss_pseudo_random_t ( + OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out + ); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_wrap_iov_t(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int * conf_state, + gss_iov_buffer_desc *iov, + int iov_count); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_unwrap_iov_t(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_wrap_iov_length_t(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_store_cred_t(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_export_cred_t(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t cred_token); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_import_cred_t(OM_uint32 * minor_status, + gss_buffer_t cred_token, + gss_cred_id_t * cred_handle); + +typedef void GSSAPI_CALLCONV +_gss_iter_creds_t(OM_uint32 /* flags */, + void * /* userctx */, + void (* /*cred_iter */ )(void *, gss_OID, gss_cred_id_t)); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_destroy_cred_t(OM_uint32 * /* minor_status */, + gss_cred_id_t * /* cred */); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_cred_hold_t(OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred */); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_cred_unhold_t(OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred */); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_cred_label_set_t(OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred */, + const char * /* label */, + gss_buffer_t /* value */); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_cred_label_get_t(OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred */, + const char * /* label */, + gss_buffer_t /* value */); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_display_name_ext_t ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_OID, /* display_as_name_type */ + gss_buffer_t /* display_name */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_name_t ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int *, /* name_is_MN */ + gss_OID *, /* MN_mech */ + gss_buffer_set_t * /* attrs */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_get_name_attribute_t ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* attr */ + int *, /* authenticated */ + int *, /* complete */ + gss_buffer_t, /* value */ + gss_buffer_t, /* display_value */ + int * /* more */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_set_name_attribute_t ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int, /* complete */ + gss_buffer_t, /* attr */ + gss_buffer_t /* value */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_delete_name_attribute_t ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* attr */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_export_name_composite_t ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* exp_composite_name */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_acquire_cred_from_t(OM_uint32 *minor_status, + gss_const_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_acquire_cred_impersonate_name_t(OM_uint32 *minor_status, + gss_const_cred_id_t icred, + gss_const_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_add_cred_from_t(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_store_cred_into_t(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_usage_t input_usage, + gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_store_cred_into2_t(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_usage_t input_usage, + gss_OID desired_mech, + OM_uint32 store_cred_flags, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored, + gss_buffer_set_t *env); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_query_mechanism_info_t(OM_uint32 *minor_status, + gss_const_OID mech_oid, + unsigned char auth_scheme[16]); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_query_meta_data_t(OM_uint32 *minor_status, + gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *ctx_handle, + gss_const_name_t targ_name, + OM_uint32 req_flags, + gss_buffer_t meta_data); + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_exchange_meta_data_t(OM_uint32 *minor_status, + gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *ctx_handle, + gss_const_name_t targ_name, + OM_uint32 req_flags, + gss_const_buffer_t meta_data); + +/* + * + */ + +typedef struct gss_mo_desc_struct gss_mo_desc; + +typedef OM_uint32 GSSAPI_CALLCONV +_gss_mo_init (OM_uint32 *, gss_OID, gss_mo_desc **, size_t *); + + +struct gss_mo_desc_struct { + gss_OID option; + OM_uint32 flags; +#define GSS_MO_MA 1 +#define GSS_MO_MA_CRITICAL 2 + const char *name; + void *ctx; + int (*get)(gss_const_OID, gss_mo_desc *, gss_buffer_t); + int (*set)(gss_const_OID, gss_mo_desc *, int, gss_buffer_t); +}; + +typedef OM_uint32 GSSAPI_CALLCONV _gss_localname_t ( + OM_uint32 *, /* minor_status */ + gss_const_name_t, /* name */ + const gss_OID, /* mech_type */ + gss_buffer_t /* localname */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_authorize_localname_t ( + OM_uint32 *, /* minor_status */ + gss_const_name_t, /* name */ + gss_const_buffer_t, /* user */ + gss_const_OID /* user_name_type */ + ); + +struct _gss_name; +struct _gss_cred; + +/* mechglue internal */ +struct gss_mech_compat_desc_struct; + +#define GMI_VERSION 6 + +/* gm_flags */ +#define GM_USE_MG_CRED 1 /* uses mech glue credentials */ +#define GM_USE_MG_NAME 2 /* uses mech glue names */ + +typedef struct gssapi_mech_interface_desc { + unsigned gm_version; + const char *gm_name; + gss_OID_desc gm_mech_oid; + unsigned gm_flags; + _gss_acquire_cred_t *gm_acquire_cred; + _gss_release_cred_t *gm_release_cred; + _gss_init_sec_context_t *gm_init_sec_context; + _gss_accept_sec_context_t *gm_accept_sec_context; + _gss_process_context_token_t *gm_process_context_token; + _gss_delete_sec_context_t *gm_delete_sec_context; + _gss_context_time_t *gm_context_time; + _gss_get_mic_t *gm_get_mic; + _gss_verify_mic_t *gm_verify_mic; + _gss_wrap_t *gm_wrap; + _gss_unwrap_t *gm_unwrap; + _gss_display_status_t *gm_display_status; + _gss_indicate_mechs_t *gm_indicate_mechs; + _gss_compare_name_t *gm_compare_name; + _gss_display_name_t *gm_display_name; + _gss_import_name_t *gm_import_name; + _gss_export_name_t *gm_export_name; + _gss_release_name_t *gm_release_name; + _gss_inquire_cred_t *gm_inquire_cred; + _gss_inquire_context_t *gm_inquire_context; + _gss_wrap_size_limit_t *gm_wrap_size_limit; + _gss_add_cred_t *gm_add_cred; + _gss_inquire_cred_by_mech_t *gm_inquire_cred_by_mech; + _gss_export_sec_context_t *gm_export_sec_context; + _gss_import_sec_context_t *gm_import_sec_context; + _gss_inquire_names_for_mech_t *gm_inquire_names_for_mech; + _gss_inquire_mechs_for_name_t *gm_inquire_mechs_for_name; + _gss_canonicalize_name_t *gm_canonicalize_name; + _gss_duplicate_name_t *gm_duplicate_name; + _gss_inquire_sec_context_by_oid_t *gm_inquire_sec_context_by_oid; + _gss_inquire_cred_by_oid_t *gm_inquire_cred_by_oid; + _gss_set_sec_context_option_t *gm_set_sec_context_option; + _gss_set_cred_option_t *gm_set_cred_option; + _gss_pseudo_random_t *gm_pseudo_random; + _gss_wrap_iov_t *gm_wrap_iov; + _gss_unwrap_iov_t *gm_unwrap_iov; + _gss_wrap_iov_length_t *gm_wrap_iov_length; + _gss_store_cred_t *gm_store_cred; + _gss_export_cred_t *gm_export_cred; + _gss_import_cred_t *gm_import_cred; + _gss_acquire_cred_from_t *gm_acquire_cred_from; /* was acquire_cred_ext */ + _gss_acquire_cred_impersonate_name_t *gm_acquire_cred_impersonate_name; + _gss_iter_creds_t *gm_iter_creds; + _gss_destroy_cred_t *gm_destroy_cred; + _gss_cred_hold_t *gm_cred_hold; + _gss_cred_unhold_t *gm_cred_unhold; + _gss_cred_label_get_t *gm_cred_label_get; + _gss_cred_label_set_t *gm_cred_label_set; + gss_mo_desc *gm_mo; + size_t gm_mo_num; + _gss_localname_t *gm_localname; + _gss_authorize_localname_t *gm_authorize_localname; + _gss_display_name_ext_t *gm_display_name_ext; + _gss_inquire_name_t *gm_inquire_name; + _gss_get_name_attribute_t *gm_get_name_attribute; + _gss_set_name_attribute_t *gm_set_name_attribute; + _gss_delete_name_attribute_t *gm_delete_name_attribute; + _gss_export_name_composite_t *gm_export_name_composite; + _gss_duplicate_cred_t *gm_duplicate_cred; + _gss_add_cred_from_t *gm_add_cred_from; + _gss_store_cred_into_t *gm_store_cred_into; + _gss_query_mechanism_info_t *gm_query_mechanism_info; + _gss_query_meta_data_t *gm_query_meta_data; + _gss_exchange_meta_data_t *gm_exchange_meta_data; + _gss_store_cred_into2_t *gm_store_cred_into2; + struct gss_mech_compat_desc_struct *gm_compat; +} gssapi_mech_interface_desc, *gssapi_mech_interface; + +gssapi_mech_interface +__gss_get_mechanism(gss_const_OID /* oid */); + +gss_OID +_gss_mg_support_mechanism(gss_const_OID mech); + +gssapi_mech_interface __gss_spnego_initialize(void); +gssapi_mech_interface __gss_krb5_initialize(void); +gssapi_mech_interface __gss_ntlm_initialize(void); +gssapi_mech_interface __gss_sanon_initialize(void); + +void gss_mg_collect_error(gss_OID, OM_uint32, OM_uint32); + +int _gss_mo_get_option_1(gss_const_OID, gss_mo_desc *, gss_buffer_t); +int _gss_mo_get_option_0(gss_const_OID, gss_mo_desc *, gss_buffer_t); +int _gss_mo_get_ctx_as_string(gss_const_OID, gss_mo_desc *, gss_buffer_t); + +struct _gss_name_type { + gss_OID gnt_name_type; + OM_uint32 (*gnt_parse)(OM_uint32 *, gss_const_OID, const gss_buffer_t, + gss_const_OID, gss_name_t *); +}; + +struct _gss_oid_name_table { + gss_OID oid; + const char *name; + const char *short_desc; + const char *long_desc; +}; + +extern struct _gss_oid_name_table _gss_ont_mech[]; +extern struct _gss_oid_name_table _gss_ont_ma[]; + +int +_gss_mg_log_level(int level); + +void +_gss_mg_log(int level, const char *fmt, ...) + HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 3)); + +void +_gss_mg_log_name(int level, + struct _gss_name *name, + gss_OID mech_type, + const char *fmt, ...); + +void +_gss_mg_log_cred(int level, + struct _gss_cred *cred, + const char *fmt, ...); + + +void +_gss_load_plugins(void); + +gss_iov_buffer_desc * +_gss_mg_find_buffer(gss_iov_buffer_desc *iov, + int iov_count, + OM_uint32 type); + +OM_uint32 +_gss_mg_allocate_buffer(OM_uint32 *minor_status, + gss_iov_buffer_desc *buffer, + size_t size); + +OM_uint32 +gss_mg_set_error_string(gss_OID mech, + OM_uint32 maj, OM_uint32 min, + const char *fmt, ...); + +gss_cred_id_t +_gss_mg_find_mech_cred(gss_const_cred_id_t cred_handle, + gss_const_OID mech_type); + +#include <krb5.h> + +/* + * Mechglue krb5 context for use by NegoEx. This is not shared with the + * krb5 GSS mechanism so we don't clobber its error state. + */ +krb5_context +_gss_mg_krb5_context(void); + +#endif /* GSSAPI_MECH_H */ diff --git a/third_party/heimdal/lib/gssapi/gsstool.c b/third_party/heimdal/lib/gssapi/gsstool.c new file mode 100644 index 0000000..8df3953 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/gsstool.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <config.h> +#include <roken.h> + +#include <stdio.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <gssapi_ntlm.h> +#include <err.h> +#include <getarg.h> +#include <rtbl.h> +#include <gss-commands.h> + + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, "service@host"); + exit (ret); +} + +#define COL_OID "OID" +#define COL_NAME "Name" +#define COL_DESC "Description" +#define COL_VALUE "Value" +#define COL_MECH "Mech" +#define COL_EXPIRE "Expire" +#define COL_SASL "SASL" + +int +mechanisms(void *argptr, int argc, char **argv) +{ + OM_uint32 maj_stat, min_stat; + gss_OID_set mechs; + rtbl_t ct; + size_t i; + + maj_stat = gss_indicate_mechs(&min_stat, &mechs); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_indicate_mechs failed"); + + printf("Supported mechanisms:\n"); + + ct = rtbl_create(); + if (ct == NULL) + errx(1, "rtbl_create"); + + rtbl_set_separator(ct, " "); + rtbl_add_column(ct, COL_OID, 0); + rtbl_add_column(ct, COL_NAME, 0); + rtbl_add_column(ct, COL_DESC, 0); + rtbl_add_column(ct, COL_SASL, 0); + + for (i = 0; i < mechs->count; i++) { + gss_buffer_desc str, sasl_name, mech_name, mech_desc; + + maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &str); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_oid_to_str failed"); + + rtbl_add_column_entryv(ct, COL_OID, "%.*s", + (int)str.length, (char *)str.value); + gss_release_buffer(&min_stat, &str); + + (void)gss_inquire_saslname_for_mech(&min_stat, + &mechs->elements[i], + &sasl_name, + &mech_name, + &mech_desc); + + rtbl_add_column_entryv(ct, COL_NAME, "%.*s", + (int)mech_name.length, (char *)mech_name.value); + rtbl_add_column_entryv(ct, COL_DESC, "%.*s", + (int)mech_desc.length, (char *)mech_desc.value); + rtbl_add_column_entryv(ct, COL_SASL, "%.*s", + (int)sasl_name.length, (char *)sasl_name.value); + + gss_release_buffer(&min_stat, &mech_name); + gss_release_buffer(&min_stat, &mech_desc); + gss_release_buffer(&min_stat, &sasl_name); + + } + gss_release_oid_set(&min_stat, &mechs); + + rtbl_format(ct, stdout); + rtbl_destroy(ct); + + return 0; +} + +static void +print_mech_attr(const char *mechname, gss_const_OID mech, gss_OID_set set) +{ + gss_buffer_desc name, desc; + OM_uint32 major, minor; + rtbl_t ct; + size_t n; + + ct = rtbl_create(); + if (ct == NULL) + errx(1, "rtbl_create"); + + rtbl_set_separator(ct, " "); + rtbl_add_column(ct, COL_OID, 0); + rtbl_add_column(ct, COL_DESC, 0); + if (mech) + rtbl_add_column(ct, COL_VALUE, 0); + + for (n = 0; n < set->count; n++) { + major = gss_display_mech_attr(&minor, &set->elements[n], &name, &desc, NULL); + if (major) + continue; + + rtbl_add_column_entryv(ct, COL_OID, "%.*s", + (int)name.length, (char *)name.value); + rtbl_add_column_entryv(ct, COL_DESC, "%.*s", + (int)desc.length, (char *)desc.value); + if (mech) { + gss_buffer_desc value; + + if (gss_mo_get(mech, &set->elements[n], &value) != 0) + value.length = 0; + + if (value.length) + rtbl_add_column_entryv(ct, COL_VALUE, "%.*s", + (int)value.length, (char *)value.value); + else + rtbl_add_column_entryv(ct, COL_VALUE, "<>"); + gss_release_buffer(&minor, &value); + } + + gss_release_buffer(&minor, &name); + gss_release_buffer(&minor, &desc); + } + + printf("attributes for: %s\n", mechname); + rtbl_format(ct, stdout); + rtbl_destroy(ct); +} + + +int +attributes(struct attributes_options *opt, int argc, char **argv) +{ + gss_OID_set mech_attr = NULL, known_mech_attrs = NULL; + gss_OID mech = GSS_C_NO_OID; + OM_uint32 major, minor; + + if (opt->mech_string) { + mech = gss_name_to_oid(opt->mech_string); + if (mech == NULL) + errx(1, "mech %s is unknown", opt->mech_string); + } + + major = gss_inquire_attrs_for_mech(&minor, mech, &mech_attr, &known_mech_attrs); + if (major) + errx(1, "gss_inquire_attrs_for_mech"); + + if (mech) { + print_mech_attr(opt->mech_string, mech, mech_attr); + } + + if (opt->all_flag) { + print_mech_attr("all mechs", NULL, known_mech_attrs); + } + + gss_release_oid_set(&minor, &mech_attr); + gss_release_oid_set(&minor, &known_mech_attrs); + + return 0; +} + + +/* + * + */ + +int +help(void *opt, int argc, char **argv) +{ + sl_slc_help(commands, argc, argv); + return 0; +} + +int +main(int argc, char **argv) +{ + int exit_status = 0, ret, optidx = 0; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc != 0) { + ret = sl_command(commands, argc, argv); + if(ret == -1) + sl_did_you_mean(commands, argv[0]); + else if (ret == -2) + ret = 0; + if(ret != 0) + exit_status = 1; + } else { + sl_slc_help(commands, argc, argv); + exit_status = 1; + } + + return exit_status; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/8003.c b/third_party/heimdal/lib/gssapi/krb5/8003.c new file mode 100644 index 0000000..3e21336 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/8003.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +krb5_error_code +_gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p) +{ + p[0] = (n >> 0) & 0xFF; + p[1] = (n >> 8) & 0xFF; + p[2] = (n >> 16) & 0xFF; + p[3] = (n >> 24) & 0xFF; + return 0; +} + +krb5_error_code +_gsskrb5_encode_be_om_uint32(OM_uint32 n, u_char *p) +{ + p[0] = (n >> 24) & 0xFF; + p[1] = (n >> 16) & 0xFF; + p[2] = (n >> 8) & 0xFF; + p[3] = (n >> 0) & 0xFF; + return 0; +} + +krb5_error_code +_gsskrb5_decode_om_uint32(const void *ptr, OM_uint32 *n) +{ + const u_char *p = ptr; + *n = ((uint32_t)p[0]) + | ((uint32_t)p[1] << 8) + | ((uint32_t)p[2] << 16) + | ((uint32_t)p[3] << 24); + return 0; +} + +krb5_error_code +_gsskrb5_decode_be_om_uint32(const void *ptr, OM_uint32 *n) +{ + const u_char *p = ptr; + *n = ((uint32_t)p[0] <<24) + | ((uint32_t)p[1] << 16) + | ((uint32_t)p[2] << 8) + | ((uint32_t)p[3]); + return 0; +} + +static krb5_error_code +hash_input_chan_bindings (const gss_channel_bindings_t b, + u_char *p) +{ + u_char num[4]; + EVP_MD_CTX *ctx; + + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, EVP_md5(), NULL); + + _gsskrb5_encode_om_uint32 (b->initiator_addrtype, num); + EVP_DigestUpdate(ctx, num, sizeof(num)); + _gsskrb5_encode_om_uint32 (b->initiator_address.length, num); + EVP_DigestUpdate(ctx, num, sizeof(num)); + if (b->initiator_address.length) + EVP_DigestUpdate(ctx, + b->initiator_address.value, + b->initiator_address.length); + _gsskrb5_encode_om_uint32 (b->acceptor_addrtype, num); + EVP_DigestUpdate(ctx, num, sizeof(num)); + _gsskrb5_encode_om_uint32 (b->acceptor_address.length, num); + EVP_DigestUpdate(ctx, num, sizeof(num)); + if (b->acceptor_address.length) + EVP_DigestUpdate(ctx, + b->acceptor_address.value, + b->acceptor_address.length); + _gsskrb5_encode_om_uint32 (b->application_data.length, num); + EVP_DigestUpdate(ctx, num, sizeof(num)); + if (b->application_data.length) + EVP_DigestUpdate(ctx, + b->application_data.value, + b->application_data.length); + EVP_DigestFinal_ex(ctx, p, NULL); + EVP_MD_CTX_destroy(ctx); + + return 0; +} + +/* + * create a checksum over the chanel bindings in + * `input_chan_bindings', `flags' and `fwd_data' and return it in + * `result' + */ + +OM_uint32 +_gsskrb5_create_8003_checksum ( + OM_uint32 *minor_status, + const gss_channel_bindings_t input_chan_bindings, + OM_uint32 flags, + const krb5_data *fwd_data, + Checksum *result) +{ + u_char *p; + + /* + * see rfc1964 (section 1.1.1 (Initial Token), and the checksum value + * field's format) */ + result->cksumtype = CKSUMTYPE_GSSAPI; + if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) + result->checksum.length = 24 + 4 + fwd_data->length; + else + result->checksum.length = 24; + result->checksum.data = malloc (result->checksum.length); + if (result->checksum.data == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = result->checksum.data; + _gsskrb5_encode_om_uint32 (16, p); + p += 4; + if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS) { + memset (p, 0, 16); + } else { + hash_input_chan_bindings (input_chan_bindings, p); + } + p += 16; + _gsskrb5_encode_om_uint32 (flags, p); + p += 4; + + if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) { + + *p++ = (1 >> 0) & 0xFF; /* DlgOpt */ /* == 1 */ + *p++ = (1 >> 8) & 0xFF; /* DlgOpt */ /* == 0 */ + *p++ = (fwd_data->length >> 0) & 0xFF; /* Dlgth */ + *p++ = (fwd_data->length >> 8) & 0xFF; /* Dlgth */ + memcpy(p, (unsigned char *) fwd_data->data, fwd_data->length); + + /* p += fwd_data->length; */ /* commented out to quiet warning */ + } + + return GSS_S_COMPLETE; +} + +static krb5_error_code +check_ap_options_cbt(void *ad_data, size_t ad_len, + krb5_boolean *client_asserted_cb) +{ + uint32_t ad_ap_options; + + *client_asserted_cb = FALSE; + + if (ad_len != sizeof(uint32_t)) + return KRB5KRB_AP_ERR_MSG_TYPE; + + _gss_mg_decode_le_uint32(ad_data, &ad_ap_options); + + if (ad_ap_options & KERB_AP_OPTIONS_CBT) + *client_asserted_cb = TRUE; + + return 0; +} + +static krb5_error_code +find_ap_options(krb5_context context, + krb5_authenticator authenticator, + krb5_boolean *client_asserted_cb) +{ + krb5_error_code ret; + krb5_authdata *ad; + krb5_data data; + + *client_asserted_cb = FALSE; + + ad = authenticator->authorization_data; + if (ad == NULL) + return 0; + + ret = _krb5_get_ad(context, ad, NULL, KRB5_AUTHDATA_AP_OPTIONS, &data); + if (ret) + return ret == ENOENT ? 0 : ret; + + ret = check_ap_options_cbt(data.data, data.length, client_asserted_cb); + krb5_data_free(&data); + + return ret; +} + +/* + * verify the checksum in `cksum' over `input_chan_bindings' + * returning `flags' and `fwd_data' + */ + +OM_uint32 +_gsskrb5_verify_8003_checksum( + krb5_context context, + OM_uint32 *minor_status, + const gss_channel_bindings_t input_chan_bindings, + krb5_authenticator authenticator, + OM_uint32 *flags, + krb5_data *fwd_data) +{ + unsigned char hash[16]; + unsigned char *p; + OM_uint32 length; + int DlgOpt; + static unsigned char zeros[16]; + krb5_boolean channel_bound = FALSE; + const Checksum *cksum = authenticator->cksum; + krb5_boolean client_asserted_cb; + krb5_error_code ret; + + /* XXX should handle checksums > 24 bytes */ + if(cksum->cksumtype != CKSUMTYPE_GSSAPI || cksum->checksum.length < 24) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + p = cksum->checksum.data; + _gsskrb5_decode_om_uint32(p, &length); + if(length != sizeof(hash)) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + p += 4; + + ret = find_ap_options(context, authenticator, &client_asserted_cb); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS + && (memcmp(p, zeros, sizeof(zeros)) != 0 || client_asserted_cb)) { + if(hash_input_chan_bindings(input_chan_bindings, hash) != 0) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + if(ct_memcmp(hash, p, sizeof(hash)) != 0) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + channel_bound = TRUE; + } + + p += sizeof(hash); + + _gsskrb5_decode_om_uint32(p, flags); + p += 4; + + if (cksum->checksum.length > 24 && (*flags & GSS_C_DELEG_FLAG)) { + if(cksum->checksum.length < 28) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + DlgOpt = (p[0] << 0) | (p[1] << 8); + p += 2; + if (DlgOpt != 1) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + fwd_data->length = (p[0] << 0) | (p[1] << 8); + p += 2; + if(cksum->checksum.length < 28 + fwd_data->length) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + fwd_data->data = malloc(fwd_data->length); + if (fwd_data->data == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(fwd_data->data, p, fwd_data->length); + } + + if (channel_bound) { + *flags |= GSS_C_CHANNEL_BOUND_FLAG; + } else { + *flags &= ~GSS_C_CHANNEL_BOUND_FLAG; + } + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c new file mode 100644 index 0000000..3f8e274 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -0,0 +1,978 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER; +krb5_keytab _gsskrb5_keytab; + +static krb5_error_code +validate_keytab(krb5_context context, const char *name, krb5_keytab *id) +{ + krb5_error_code ret; + + ret = krb5_kt_resolve(context, name, id); + if (ret) + return ret; + + ret = krb5_kt_have_content(context, *id); + if (ret) { + krb5_kt_close(context, *id); + *id = NULL; + } + + return ret; +} + +OM_uint32 +_gsskrb5_register_acceptor_identity(OM_uint32 *min_stat, const char *identity) +{ + krb5_context context; + krb5_error_code ret; + + *min_stat = 0; + + ret = _gsskrb5_init(&context); + if(ret) + return GSS_S_FAILURE; + + HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + + if(_gsskrb5_keytab != NULL) { + krb5_kt_close(context, _gsskrb5_keytab); + _gsskrb5_keytab = NULL; + } + if (identity == NULL) { + ret = krb5_kt_default(context, &_gsskrb5_keytab); + } else { + /* + * First check if we can the keytab as is and if it has content... + */ + ret = validate_keytab(context, identity, &_gsskrb5_keytab); + /* + * if it doesn't, lets prepend FILE: and try again + */ + if (ret) { + char *p = NULL; + ret = asprintf(&p, "FILE:%s", identity); + if(ret < 0 || p == NULL) { + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + return GSS_S_FAILURE; + } + ret = validate_keytab(context, p, &_gsskrb5_keytab); + free(p); + } + } + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + if(ret) { + *min_stat = ret; + return GSS_S_FAILURE; + } + return GSS_S_COMPLETE; +} + +void +_gsskrb5i_is_cfx(krb5_context context, gsskrb5_ctx ctx, int acceptor) +{ + krb5_keyblock *key; + + if (acceptor) { + if (ctx->auth_context->local_subkey) + key = ctx->auth_context->local_subkey; + else + key = ctx->auth_context->remote_subkey; + } else { + if (ctx->auth_context->remote_subkey) + key = ctx->auth_context->remote_subkey; + else + key = ctx->auth_context->local_subkey; + } + if (key == NULL) + key = ctx->auth_context->keyblock; + + if (key == NULL) + return; + + switch (key->keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + case ETYPE_DES3_CBC_MD5: + case ETYPE_OLD_DES3_CBC_SHA1: + case ETYPE_DES3_CBC_SHA1: + case ETYPE_ARCFOUR_HMAC_MD5: + case ETYPE_ARCFOUR_HMAC_MD5_56: + break; + default : + ctx->more_flags |= IS_CFX; + + if ((acceptor && ctx->auth_context->local_subkey) || + (!acceptor && ctx->auth_context->remote_subkey)) + ctx->more_flags |= ACCEPTOR_SUBKEY; + break; + } + if (ctx->crypto) + krb5_crypto_destroy(context, ctx->crypto); + /* XXX We really shouldn't ignore this; will come back to this */ + (void) krb5_crypto_init(context, key, 0, &ctx->crypto); +} + + +static OM_uint32 +gsskrb5_accept_delegated_token(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + gss_cred_id_t *delegated_cred_handle) +{ + krb5_ccache ccache = NULL; + krb5_error_code kret; + int32_t ac_flags, ret = GSS_S_COMPLETE; + gsskrb5_cred handle; + + *minor_status = 0; + + /* XXX Create a new delegated_cred_handle? */ + if (delegated_cred_handle == NULL) + return GSS_S_COMPLETE; + + *delegated_cred_handle = NULL; + kret = krb5_cc_resolve(context, "MEMORY:anonymous", &ccache); + if (kret == 0) + kret = krb5_cc_initialize(context, ccache, ctx->source); + if (kret == 0) { + (void) krb5_auth_con_removeflags(context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_TIME, + &ac_flags); + kret = krb5_rd_cred2(context, + ctx->auth_context, + ccache, + &ctx->fwd_data); + (void) krb5_auth_con_setflags(context, + ctx->auth_context, + ac_flags); + } + if (kret) { + ctx->flags &= ~GSS_C_DELEG_FLAG; + ret = GSS_S_FAILURE; + *minor_status = kret; + goto out; + } + + ret = _gsskrb5_krb5_import_cred(minor_status, + &ccache, + NULL, + NULL, + delegated_cred_handle); + if (ret != GSS_S_COMPLETE) + goto out; + + handle = (gsskrb5_cred) *delegated_cred_handle; + handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + + /* + * A root TGT is one of the form krbtgt/REALM@SAME-REALM. + * + * A destination TGT is a root TGT for the same realm as the acceptor + * service's realm. + * + * Normally clients delegate a root TGT for the client's realm. + * + * In some deployments clients may want to delegate destination TGTs as + * a form of constrained delegation: so that the destination service + * cannot use the delegated credential to impersonate the client + * principal to services in its home realm (due to KDC lineage/transit + * checks). In those deployments there may not even be a route back to + * the KDCs of the client's realm, and attempting to use a + * non-destination TGT might even lead to timeouts. + * + * We could simply pretend not to have obtained a credential, except + * that a) we don't (yet) have an app name here for the appdefault we + * need to check, b) the application really wants to be able to log a + * message about the delegated credential being no good. + * + * Thus we leave it to _gsskrb5_store_cred_into2() to decide what to do + * with non-destination TGTs. To do that, it needs the realm of the + * acceptor service, which we record here. + */ + handle->destination_realm = + strdup(krb5_principal_get_realm(context, ctx->target)); + if (handle->destination_realm == NULL) { + _gsskrb5_release_cred(minor_status, delegated_cred_handle); + *minor_status = krb5_enomem(context); + ret = GSS_S_FAILURE; + goto out; + } + +out: + if (ccache) { + krb5_cc_close(context, ccache); + } + return ret; +} + +static OM_uint32 +gsskrb5_acceptor_ready(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + krb5_context context, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 ret; + int32_t seq_number; + int is_cfx = 0; + + krb5_auth_con_getremoteseqnumber (context, + ctx->auth_context, + &seq_number); + + _gsskrb5i_is_cfx(context, ctx, 1); + is_cfx = (ctx->more_flags & IS_CFX); + + ret = _gssapi_msg_order_create(minor_status, + &ctx->order, + _gssapi_msg_order_f(ctx->flags), + seq_number, 0, is_cfx); + if (ret) + return ret; + + /* + * If requested, set local sequence num to remote sequence if this + * isn't a mutual authentication context + */ + if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) { + krb5_auth_con_setlocalseqnumber(context, + ctx->auth_context, + seq_number); + } + + /* + * We should handle the delegation ticket, in case it's there + */ + if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) { + ret = gsskrb5_accept_delegated_token(minor_status, + ctx, + context, + delegated_cred_handle); + if (ret != GSS_S_COMPLETE) + return ret; + } else { + /* Well, looks like it wasn't there after all */ + ctx->flags &= ~GSS_C_DELEG_FLAG; + } + + ctx->state = ACCEPTOR_READY; + ctx->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +send_error_token(OM_uint32 *minor_status, + krb5_context context, + krb5_error_code kret, + krb5_principal server, + krb5_data *indata, + gss_buffer_t output_token) +{ + krb5_principal ap_req_server = NULL; + krb5_error_code ret; + krb5_data outbuf; + /* this e_data value encodes KERB_AP_ERR_TYPE_SKEW_RECOVERY which + tells windows to try again with the corrected timestamp. See + [MS-KILE] 2.2.1 KERB-ERROR-DATA */ + krb5_data e_data = { 7, rk_UNCONST("\x30\x05\xa1\x03\x02\x01\x02") }; + + /* build server from request if the acceptor had not selected one */ + if (server == NULL) { + AP_REQ ap_req; + + ret = krb5_decode_ap_req(context, indata, &ap_req); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + ret = _krb5_principalname2krb5_principal(context, + &ap_req_server, + ap_req.ticket.sname, + ap_req.ticket.realm); + free_AP_REQ(&ap_req); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + server = ap_req_server; + } + + ret = krb5_mk_error(context, kret, NULL, &e_data, NULL, + server, NULL, NULL, &outbuf); + if (ap_req_server) + krb5_free_principal(context, ap_req_server); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = _gsskrb5_encapsulate(minor_status, + &outbuf, + output_token, + "\x03\x00", + GSS_KRB5_MECHANISM); + krb5_data_free (&outbuf); + if (ret) + return ret; + + *minor_status = 0; + return GSS_S_CONTINUE_NEEDED; +} + + +static OM_uint32 +gsskrb5_acceptor_start(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + krb5_context context, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle) +{ + krb5_error_code kret; + OM_uint32 ret = GSS_S_COMPLETE; + krb5_data indata; + krb5_flags ap_options; + krb5_keytab keytab = NULL; + int is_cfx = 0; + int close_kt = 0; + const gsskrb5_cred acceptor_cred = (gsskrb5_cred)acceptor_cred_handle; + + /* + * We may, or may not, have an escapsulation. + */ + ret = _gsskrb5_decapsulate (minor_status, + input_token_buffer, + &indata, + "\x01\x00", + GSS_KRB5_MECHANISM); + + if (ret) { + /* Could be a raw AP-REQ (check for APPLICATION tag) */ + if (input_token_buffer->length == 0 || + ((const uint8_t *)input_token_buffer->value)[0] != 0x6E) { + *minor_status = ASN1_MISPLACED_FIELD; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Assume that there is no OID wrapping. */ + indata.length = input_token_buffer->length; + indata.data = input_token_buffer->value; + } + + /* + * We need to get our keytab + */ + if (acceptor_cred == NULL) { + HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + if (_gsskrb5_keytab != NULL) { + char *name = NULL; + kret = krb5_kt_get_full_name(context, _gsskrb5_keytab, &name); + if (kret == 0) { + kret = krb5_kt_resolve(context, name, &keytab); + krb5_xfree(name); + } + if (kret == 0) + close_kt = 1; + else + keytab = NULL; + } + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + } else if (acceptor_cred->keytab != NULL) { + keytab = acceptor_cred->keytab; + } + + /* + * We need to check the ticket and create the AP-REP packet + */ + + { + krb5_rd_req_in_ctx in = NULL; + krb5_rd_req_out_ctx out = NULL; + krb5_principal server = NULL; + + if (acceptor_cred) + server = acceptor_cred->principal; + + kret = krb5_rd_req_in_ctx_alloc(context, &in); + if (kret == 0) + kret = krb5_rd_req_in_set_keytab(context, in, keytab); + if (kret) { + if (in) + krb5_rd_req_in_ctx_free(context, in); + if (close_kt) + krb5_kt_close(context, keytab); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_rd_req_ctx(context, + &ctx->auth_context, + &indata, + server, + in, &out); + krb5_rd_req_in_ctx_free(context, in); + if (close_kt) + krb5_kt_close(context, keytab); + if (kret == KRB5KRB_AP_ERR_SKEW || kret == KRB5KRB_AP_ERR_TKT_NYV) { + /* + * No reply in non-MUTUAL mode, but we don't know that its + * non-MUTUAL mode yet, thats inside the 8003 checksum, so + * lets only send the error token on clock skew, that + * limit when send error token for non-MUTUAL. + */ + krb5_auth_con_free(context, ctx->auth_context); + krb5_auth_con_free(context, ctx->deleg_auth_context); + ctx->deleg_auth_context = NULL; + ctx->auth_context = NULL; + return send_error_token(minor_status, context, kret, + server, &indata, output_token); + } else if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + /* + * we need to remember some data on the context_handle. + */ + kret = krb5_rd_req_out_get_ap_req_options(context, out, + &ap_options); + if (kret == 0) + kret = krb5_rd_req_out_get_ticket(context, out, + &ctx->ticket); + if (kret == 0) + kret = krb5_rd_req_out_get_keyblock(context, out, + &ctx->service_keyblock); + ctx->endtime = ctx->ticket->ticket.endtime; + + krb5_rd_req_out_ctx_free(context, out); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + return ret; + } + } + + + /* + * We need to copy the principal names to the context and the + * calling layer. + */ + kret = krb5_copy_principal(context, + ctx->ticket->client, + &ctx->source); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + return ret; + } + + kret = krb5_copy_principal(context, + ctx->ticket->server, + &ctx->target); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + return ret; + } + + /* + * We need to setup some compat stuff, this assumes that + * context_handle->target is already set. + */ + ret = _gss_DES3_get_mic_compat(minor_status, ctx, context); + if (ret) + return ret; + + if (src_name != NULL) { + kret = krb5_copy_principal (context, + ctx->ticket->client, + (gsskrb5_name*)src_name); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + return ret; + } + } + + /* + * We need to get the flags out of the 8003 checksum. + */ + + { + krb5_authenticator authenticator; + + kret = krb5_auth_con_getauthenticator(context, + ctx->auth_context, + &authenticator); + if(kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + return ret; + } + + if (authenticator->cksum != NULL + && authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) { + ret = _gsskrb5_verify_8003_checksum(context, + minor_status, + input_chan_bindings, + authenticator, + &ctx->flags, + &ctx->fwd_data); + + if (ret) { + krb5_free_authenticator(context, &authenticator); + return ret; + } + } else { + if (authenticator->cksum != NULL) { + krb5_crypto crypto; + + kret = krb5_crypto_init(context, + ctx->auth_context->keyblock, + 0, &crypto); + if (kret) { + krb5_free_authenticator(context, &authenticator); + ret = GSS_S_FAILURE; + *minor_status = kret; + return ret; + } + + /* + * Windows accepts Samba3's use of a kerberos, rather than + * GSSAPI checksum here + */ + + _krb5_crypto_set_flags(context, crypto, KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM); + kret = krb5_verify_checksum(context, + crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0, + authenticator->cksum); + krb5_crypto_destroy(context, crypto); + + if (kret) { + krb5_free_authenticator(context, &authenticator); + ret = GSS_S_BAD_SIG; + *minor_status = kret; + return ret; + } + } + + /* + * If there is no checksum or a kerberos checksum (which Windows + * and Samba accept), we use the ap_options to guess the mutual + * flag. + */ + + ctx->flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + if (ap_options & AP_OPTS_MUTUAL_REQUIRED) + ctx->flags |= GSS_C_MUTUAL_FLAG; + } + krb5_free_authenticator(context, &authenticator); + } + + if(ctx->flags & GSS_C_MUTUAL_FLAG) { + krb5_data outbuf; + int use_subkey = 0; + + _gsskrb5i_is_cfx(context, ctx, 1); + is_cfx = (ctx->more_flags & IS_CFX); + + if (is_cfx || (ap_options & AP_OPTS_USE_SUBKEY)) { + use_subkey = 1; + } else { + krb5_keyblock *rkey; + + /* + * If there is a initiator subkey, copy that to acceptor + * subkey to match Windows behavior + */ + kret = krb5_auth_con_getremotesubkey(context, + ctx->auth_context, + &rkey); + if (kret == 0) { + kret = krb5_auth_con_setlocalsubkey(context, + ctx->auth_context, + rkey); + if (kret == 0) + use_subkey = 1; + } + krb5_free_keyblock(context, rkey); + } + if (use_subkey) { + ctx->more_flags |= ACCEPTOR_SUBKEY; + krb5_auth_con_addflags(context, ctx->auth_context, + KRB5_AUTH_CONTEXT_USE_SUBKEY, + NULL); + } + + kret = krb5_mk_rep(context, + ctx->auth_context, + &outbuf); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (IS_DCE_STYLE(ctx)) { + output_token->length = outbuf.length; + output_token->value = outbuf.data; + } else { + ret = _gsskrb5_encapsulate(minor_status, + &outbuf, + output_token, + "\x02\x00", + GSS_KRB5_MECHANISM); + krb5_data_free (&outbuf); + if (ret) + return ret; + } + } + + ctx->flags |= GSS_C_TRANS_FLAG; + + /* Remember the flags */ + + ctx->endtime = ctx->ticket->ticket.endtime; + ctx->more_flags |= OPEN; + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (time_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + context, + ctx->endtime, + time_rec); + if (ret) { + return ret; + } + } + + /* + * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from + * the client. + */ + if (IS_DCE_STYLE(ctx)) { + /* + * Return flags to caller, but we haven't processed + * delgations yet + */ + if (ret_flags) + *ret_flags = (ctx->flags & ~GSS_C_DELEG_FLAG); + + ctx->state = ACCEPTOR_WAIT_FOR_DCESTYLE; + return GSS_S_CONTINUE_NEEDED; + } + + ret = gsskrb5_acceptor_ready(minor_status, ctx, context, + delegated_cred_handle); + + if (ret_flags) + *ret_flags = ctx->flags; + + return ret; +} + +static OM_uint32 +acceptor_wait_for_dcestyle(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + krb5_context context, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data inbuf; + int32_t r_seq_number, l_seq_number; + + /* + * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP + */ + + inbuf.length = input_token_buffer->length; + inbuf.data = input_token_buffer->value; + + /* + * We need to remeber the old remote seq_number, then check if the + * client has replied with our local seq_number, and then reset + * the remote seq_number to the old value + */ + { + kret = krb5_auth_con_getlocalseqnumber(context, + ctx->auth_context, + &l_seq_number); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_getremoteseqnumber(context, + ctx->auth_context, + &r_seq_number); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_setremoteseqnumber(context, + ctx->auth_context, + l_seq_number); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + /* + * We need to verify the AP_REP, but we need to flag that this is + * DCE_STYLE, so don't check the timestamps this time, but put the + * flag DO_TIME back afterward. + */ + { + krb5_ap_rep_enc_part *repl; + int32_t auth_flags; + + krb5_auth_con_removeflags(context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_TIME, + &auth_flags); + + kret = krb5_rd_rep(context, ctx->auth_context, &inbuf, &repl); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + krb5_free_ap_rep_enc_part(context, repl); + krb5_auth_con_setflags(context, ctx->auth_context, auth_flags); + } + + /* We need to check the liftime */ + { + OM_uint32 lifetime_rec; + + ret = _gsskrb5_lifetime_left(minor_status, + context, + ctx->endtime, + &lifetime_rec); + if (ret) { + return ret; + } + if (lifetime_rec == 0) { + return GSS_S_CONTEXT_EXPIRED; + } + + if (time_rec) *time_rec = lifetime_rec; + } + + /* We need to give the caller the flags which are in use */ + if (ret_flags) *ret_flags = ctx->flags; + + if (src_name) { + kret = krb5_copy_principal(context, + ctx->source, + (gsskrb5_name*)src_name); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + /* + * After the krb5_rd_rep() the remote and local seq_number should + * be the same, because the client just replies the seq_number + * from our AP-REP in its AP-REP, but then the client uses the + * seq_number from its AP-REQ for GSS_wrap() + */ + { + int32_t tmp_r_seq_number, tmp_l_seq_number; + + kret = krb5_auth_con_getremoteseqnumber(context, + ctx->auth_context, + &tmp_r_seq_number); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_getlocalseqnumber(context, + ctx->auth_context, + &tmp_l_seq_number); + if (kret) { + + *minor_status = kret; + return GSS_S_FAILURE; + } + + /* + * Here we check if the client has responsed with our local seq_number, + */ + if (tmp_r_seq_number != tmp_l_seq_number) { + return GSS_S_UNSEQ_TOKEN; + } + } + + /* + * We need to reset the remote seq_number, because the client will use, + * the old one for the GSS_wrap() calls + */ + { + kret = krb5_auth_con_setremoteseqnumber(context, + ctx->auth_context, + r_seq_number); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + return gsskrb5_acceptor_ready(minor_status, ctx, context, + delegated_cred_handle); +} + + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_accept_sec_context(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle) +{ + krb5_context context; + OM_uint32 ret; + gsskrb5_ctx ctx; + + GSSAPI_KRB5_INIT(&context); + + output_token->length = 0; + output_token->value = NULL; + + if (src_name != NULL) + *src_name = NULL; + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (*context_handle == GSS_C_NO_CONTEXT) { + ret = _gsskrb5_create_ctx(minor_status, + context_handle, + context, + input_chan_bindings, + ACCEPTOR_START); + if (ret) + return ret; + } + + ctx = (gsskrb5_ctx)*context_handle; + + + /* + * TODO: check the channel_bindings + * (above just sets them to krb5 layer) + */ + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + switch (ctx->state) { + case ACCEPTOR_START: + ret = gsskrb5_acceptor_start(minor_status, + ctx, + context, + acceptor_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + delegated_cred_handle); + break; + case ACCEPTOR_WAIT_FOR_DCESTYLE: + ret = acceptor_wait_for_dcestyle(minor_status, + ctx, + context, + acceptor_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + delegated_cred_handle); + break; + case ACCEPTOR_READY: + /* + * If we get there, the caller have called + * gss_accept_sec_context() one time too many. + */ + ret = GSS_S_BAD_STATUS; + break; + default: + /* TODO: is this correct here? --metze */ + ret = GSS_S_BAD_STATUS; + break; + } + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (GSS_ERROR(ret)) { + OM_uint32 min2; + _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); + } + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c b/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c new file mode 100644 index 0000000..211dcaa --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c @@ -0,0 +1,686 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +/* + * Find an element in a cred store. Returns GSS_S_COMPLETE if the cred store + * is absent or well formed, irrespective of whether the element exists. The + * caller should check for *value != NULL before using; values are typically + * optional, hence this behavior. (The caller should validate the return + * value at least once though, to check it is well-formed.) + */ +OM_uint32 +__gsskrb5_cred_store_find(OM_uint32 *minor_status, + gss_const_key_value_set_t cred_store, + const char *key, + const char **value) +{ + size_t i; + + *value = NULL; + + if (cred_store == GSS_C_NO_CRED_STORE) + return GSS_S_COMPLETE; + else if (cred_store->count == 0) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_NO_CRED; + } + + for (i = 0; i < cred_store->count; i++) { + if (strcmp(key, cred_store->elements[i].key) == 0) { + if (*value) { + *value = NULL; + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_DUPLICATE_ELEMENT; + } + *value = cred_store->elements[i].value; + } + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +__gsskrb5_ccache_lifetime(OM_uint32 *minor_status, + krb5_context context, + krb5_ccache id, + krb5_principal principal, + OM_uint32 *lifetime) +{ + krb5_error_code kret; + time_t left; + + kret = krb5_cc_get_lifetime(context, id, &left); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + *lifetime = left; + + return GSS_S_COMPLETE; +} + + + + +static krb5_error_code +get_system_keytab(krb5_context context, + gss_const_key_value_set_t cred_store, + krb5_keytab *keytab) +{ + krb5_error_code kret; + const char *cs_ktname; + OM_uint32 tmp; + + __gsskrb5_cred_store_find(&tmp, cred_store, "keytab", &cs_ktname); + + HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + + if (cs_ktname) + kret = krb5_kt_resolve(context, cs_ktname, keytab); + else if (_gsskrb5_keytab != NULL) { + char *name = NULL; + + kret = krb5_kt_get_full_name(context, _gsskrb5_keytab, &name); + if (kret == 0) { + kret = krb5_kt_resolve(context, name, keytab); + krb5_xfree(name); + } + } else + kret = krb5_kt_default(context, keytab); + + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + + return (kret); +} + +static krb5_error_code +get_client_keytab(krb5_context context, + gss_const_key_value_set_t cred_store, + krb5_const_principal principal, + krb5_keytab *keytab) +{ + krb5_error_code ret; + const char *cs_ktname; + OM_uint32 tmp; + + __gsskrb5_cred_store_find(&tmp, cred_store, "client_keytab", &cs_ktname); + + if (cs_ktname) + ret = krb5_kt_resolve(context, cs_ktname, keytab); + else { + char *name = NULL; + ret = _krb5_kt_client_default_name(context, &name); + if (ret == 0) + ret = krb5_kt_resolve(context, name, keytab); + krb5_xfree(name); + } + + if (ret == 0 && principal) { + krb5_keytab_entry entry; + + ret = krb5_kt_get_entry(context, *keytab, principal, + 0, 0, &entry); + if (ret == 0) + krb5_kt_free_entry(context, &entry); + } + + if (ret) { + if (*keytab) { + krb5_kt_close(context, *keytab); + *keytab = NULL; + } + + ret = get_system_keytab(context, GSS_C_NO_CRED_STORE, keytab); + } + + return ret; +} + +static krb5_boolean +is_valid_password_cred_store(gss_const_key_value_set_t cred_store) +{ + size_t i; + + if (cred_store == GSS_C_NO_CRED_STORE) + return TRUE; + + /* XXX don't check keytab, someday we will allow password+acceptor creds */ + for (i = 0; i < cred_store->count; i++) { + if (strcmp(cred_store->elements[i].key, "ccache") == 0 || + strcmp(cred_store->elements[i].key, "client_keytab") == 0) + return FALSE; + } + + return TRUE; +} + +/* + * This function produces a cred with a MEMORY ccache containing a TGT + * acquired with a password. + */ +static OM_uint32 +acquire_cred_with_password(OM_uint32 *minor_status, + krb5_context context, + const char *password, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gsskrb5_cred handle) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_creds cred; + krb5_init_creds_context ctx = NULL; + krb5_get_init_creds_opt *opt = NULL; + krb5_ccache ccache = NULL; + krb5_error_code kret; + time_t now; + OM_uint32 left; + const char *realm; + + if (!is_valid_password_cred_store(cred_store)) { + *minor_status = GSS_KRB5_S_G_BAD_PASSWORD_CRED_STORE; + return GSS_S_NO_CRED; + } + + if (cred_usage == GSS_C_ACCEPT) { + /* + * TODO: Here we should eventually support user2user (when we get + * support for that via an extension to the mechanism + * allowing for more than two security context tokens), + * and/or new unique MEMORY keytabs (we have MEMORY keytab + * support, but we don't have a keytab equivalent of + * krb5_cc_new_unique()). Either way, for now we can't + * support this. + */ + *minor_status = ENOTSUP; /* XXX Better error? */ + return GSS_S_FAILURE; + } + + memset(&cred, 0, sizeof(cred)); + + if (handle->principal == NULL) { + kret = krb5_get_default_principal(context, &handle->principal); + if (kret) + goto end; + } + realm = krb5_principal_get_realm(context, handle->principal); + + kret = krb5_get_init_creds_opt_alloc(context, &opt); + if (kret == 0) { + krb5_get_init_creds_opt_set_default_flags(context, "gss_krb5", realm, + opt); + kret = krb5_init_creds_init(context, handle->principal, NULL, NULL, 0, + opt, &ctx); + } + if (kret == 0) + kret = _krb5_init_creds_set_fast_anon_pkinit_optimistic(context, ctx); + if (kret == 0) + kret = krb5_init_creds_set_password(context, ctx, password); + + /* + * Get the current time before the AS exchange so we don't + * accidentally end up returning a value that puts advertised + * expiration past the real expiration. + * + * We need to do this because krb5_cc_get_lifetime() returns a + * relative time that we need to add to the current time. We ought + * to have a version of krb5_cc_get_lifetime() that returns absolute + * time... + */ + krb5_timeofday(context, &now); + + if (kret == 0) + kret = krb5_init_creds_get(context, ctx); + if (kret == 0) + kret = krb5_init_creds_get_creds(context, ctx, &cred); + if (kret == 0) + kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); + if (kret == 0) + kret = krb5_cc_initialize(context, ccache, cred.client); + if (kret == 0) + kret = krb5_init_creds_store(context, ctx, ccache); + if (kret == 0) + kret = krb5_cc_store_cred(context, ccache, &cred); + if (kret) + goto end; + + handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + + ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, + handle->principal, &left); + if (ret != GSS_S_COMPLETE) + goto end; + handle->endtime = now + left; + handle->ccache = ccache; + ccache = NULL; + ret = GSS_S_COMPLETE; + +end: + krb5_get_init_creds_opt_free(context, opt); + if (ctx) + krb5_init_creds_free(context, ctx); + if (ccache != NULL) + krb5_cc_destroy(context, ccache); + if (cred.client != NULL) + krb5_free_cred_contents(context, &cred); + if (ret != GSS_S_COMPLETE) + *minor_status = kret; + return (ret); +} + +/* + * Acquires an initiator credential from a ccache or using a keytab. + */ +static OM_uint32 +acquire_initiator_cred(OM_uint32 *minor_status, + krb5_context context, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gsskrb5_cred handle) +{ + OM_uint32 ret; + krb5_creds cred; + krb5_get_init_creds_opt *opt; + krb5_principal def_princ = NULL; + krb5_ccache def_ccache = NULL; + krb5_ccache ccache = NULL; /* we may store into this ccache */ + krb5_keytab keytab = NULL; + krb5_error_code kret = 0; + OM_uint32 left; + const char *cs_ccache_name; + time_t lifetime = 0; + time_t now; + + memset(&cred, 0, sizeof(cred)); + + ret = __gsskrb5_cred_store_find(minor_status, cred_store, + "ccache", &cs_ccache_name); + if (GSS_ERROR(ret)) + return ret; + + ret = GSS_S_FAILURE; + + /* + * Get current time early so we can set handle->endtime to a value that + * cannot accidentally be past the real endtime. We need a variant of + * krb5_cc_get_lifetime() that returns absolute endtime. + */ + krb5_timeofday(context, &now); + + /* + * First look for a ccache that has the desired_name (which may be + * the default credential name), unless a specific credential cache + * was included in cred_store. + * + * If we don't have an unexpired credential, acquire one with a + * keytab. + * + * If we acquire one with a keytab, save it in the ccache we found + * with the expired credential, if any. + * + * If we don't have any such ccache, then use a MEMORY ccache. + */ + + if (handle->principal != NULL && cs_ccache_name == NULL) { + /* + * Not default credential case. See if we can find a ccache in + * the cccol for the desired_name. + */ + kret = krb5_cc_cache_match(context, + handle->principal, + &ccache); + if (kret == 0) { + kret = krb5_cc_get_lifetime(context, ccache, &lifetime); + if (kret == 0) { + if (lifetime > 0) + goto found; + else + goto try_keytab; + } + } + /* + * Fall through. We shouldn't find this in the default ccache + * either, but we'll give it a try, then we'll try using a keytab. + */ + } + + /* + * Either desired_name was GSS_C_NO_NAME (default cred) or + * krb5_cc_cache_match() failed (or found expired). + */ + if (cs_ccache_name) + kret = krb5_cc_resolve(context, cs_ccache_name, &def_ccache); + else + kret = krb5_cc_default(context, &def_ccache); + if (kret != 0) + goto try_keytab; + kret = krb5_cc_get_lifetime(context, def_ccache, &lifetime); + if (kret != 0) + lifetime = 0; + kret = krb5_cc_get_principal(context, def_ccache, &def_princ); + if (kret != 0) + goto try_keytab; + /* + * Have a default ccache; see if it matches desired_name. + */ + if (handle->principal == NULL || + krb5_principal_compare(context, handle->principal, + def_princ) == TRUE) { + /* + * It matches. + * + * If we end up trying a keytab then we can write the result to + * the default ccache. + */ + if (handle->principal == NULL) { + kret = krb5_copy_principal(context, def_princ, &handle->principal); + if (kret) + goto end; + } + if (ccache != NULL) + krb5_cc_close(context, ccache); + ccache = def_ccache; + def_ccache = NULL; + if (lifetime > 0) + goto found; + /* else we fall through and try using a keytab */ + } + +try_keytab: + if (handle->principal == NULL) { + /* We need to know what client principal to use */ + kret = krb5_get_default_principal(context, &handle->principal); + if (kret) + goto end; + } + kret = get_client_keytab(context, cred_store, handle->principal, &keytab); + if (kret) + goto end; + + kret = krb5_get_init_creds_opt_alloc(context, &opt); + if (kret) + goto end; + krb5_timeofday(context, &now); + kret = krb5_get_init_creds_keytab(context, &cred, handle->principal, + keytab, 0, NULL, opt); + krb5_get_init_creds_opt_free(context, opt); + if (kret) + goto end; + + /* + * We got a credential with a keytab. Save it if we can. + */ + if (ccache == NULL) { + /* + * There's no ccache we can overwrite with the credentials we acquired + * with a keytab. We'll use a MEMORY ccache then. + * + * Note that an application that falls into this repeatedly will do an + * AS exchange every time it acquires a credential handle. Hopefully + * this doesn't happen much. A workaround is to kinit -k once so that + * we always re-initialize the matched/default ccache here. I.e., once + * there's a FILE/DIR ccache, we'll keep it frash automatically if we + * have a keytab, but if there's no FILE/DIR ccache, then we'll + * get a fresh credential *every* time we're asked. + */ + kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); + if (kret) + goto end; + handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + } /* else we'll re-initialize whichever ccache we matched above */ + + kret = krb5_cc_initialize(context, ccache, cred.client); + if (kret) + goto end; + kret = krb5_cc_store_cred(context, ccache, &cred); + if (kret) + goto end; + +found: + assert(handle->principal != NULL); + ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, + handle->principal, &left); + if (ret != GSS_S_COMPLETE) + goto end; + handle->endtime = now + left; + handle->ccache = ccache; + ccache = NULL; + ret = GSS_S_COMPLETE; + kret = 0; + +end: + if (ccache != NULL) { + if ((handle->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) != 0) + krb5_cc_destroy(context, ccache); + else + krb5_cc_close(context, ccache); + } + if (def_ccache != NULL) + krb5_cc_close(context, def_ccache); + if (cred.client != NULL) + krb5_free_cred_contents(context, &cred); + if (def_princ != NULL) + krb5_free_principal(context, def_princ); + if (keytab != NULL) + krb5_kt_close(context, keytab); + if (ret != GSS_S_COMPLETE && kret != 0) + *minor_status = kret; + return (ret); +} + +static OM_uint32 +acquire_acceptor_cred(OM_uint32 * minor_status, + krb5_context context, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gsskrb5_cred handle) +{ + OM_uint32 ret; + krb5_error_code kret; + + ret = GSS_S_FAILURE; + + kret = get_system_keytab(context, cred_store, &handle->keytab); + if (kret) + goto end; + + /* check that the requested principal exists in the keytab */ + if (handle->principal) { + krb5_keytab_entry entry; + + kret = krb5_kt_get_entry(context, handle->keytab, + handle->principal, 0, 0, &entry); + if (kret) + goto end; + krb5_kt_free_entry(context, &entry); + ret = GSS_S_COMPLETE; + } else { + /* + * Check if there is at least one entry in the keytab before + * declaring it as an useful keytab. + */ + krb5_keytab_entry tmp; + krb5_kt_cursor c; + + kret = krb5_kt_start_seq_get (context, handle->keytab, &c); + if (kret) + goto end; + if (krb5_kt_next_entry(context, handle->keytab, &tmp, &c) == 0) { + krb5_kt_free_entry(context, &tmp); + ret = GSS_S_COMPLETE; /* ok found one entry */ + } + krb5_kt_end_seq_get (context, handle->keytab, &c); + } +end: + if (ret != GSS_S_COMPLETE) { + if (handle->keytab != NULL) + krb5_kt_close(context, handle->keytab); + if (kret != 0) { + *minor_status = kret; + } + } + return (ret); +} + + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_from +(OM_uint32 * minor_status, + gss_const_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t * output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec + ) +{ + krb5_context context; + gsskrb5_cred handle; + OM_uint32 ret; + const char *password = NULL; + + if (desired_mechs) { + int present = 0; + + ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + desired_mechs, &present); + if (ret) + return ret; + if (!present) { + *minor_status = 0; + return GSS_S_BAD_MECH; + } + } + + cred_usage &= GSS_C_OPTION_MASK; + + if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && + cred_usage != GSS_C_BOTH) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_FAILURE; + } + + ret = __gsskrb5_cred_store_find(minor_status, cred_store, + "password", &password); + if (GSS_ERROR(ret)) + return ret; + + GSSAPI_KRB5_INIT(&context); + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + handle->destination_realm = NULL; + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + if (desired_name != GSS_C_NO_NAME) { + ret = _gsskrb5_canon_name(minor_status, context, + desired_name, &handle->principal); + if (ret) { + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + free(handle); + return ret; + } + } + + if (password) { + ret = acquire_cred_with_password(minor_status, context, password, time_req, + desired_mechs, cred_usage, cred_store, handle); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + krb5_free_principal(context, handle->principal); + free(handle); + return (ret); + } + } else { + /* + * Acquire a credential from the specified or background credential + * store (ccache, keytab). + */ + if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { + ret = acquire_initiator_cred(minor_status, context, time_req, + desired_mechs, cred_usage, + cred_store, handle); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + krb5_free_principal(context, handle->principal); + free(handle); + return (ret); + } + } + if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { + ret = acquire_acceptor_cred(minor_status, context, time_req, + desired_mechs, cred_usage, + cred_store, handle); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + krb5_free_principal(context, handle->principal); + free(handle); + return (ret); + } + } + } + ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); + if (ret == GSS_S_COMPLETE) + ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); + handle->usage = cred_usage; + if (ret == GSS_S_COMPLETE) + ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)handle, + NULL, time_rec, NULL, actual_mechs); + if (ret != GSS_S_COMPLETE) { + if (handle->mechanisms != NULL) + gss_release_oid_set(NULL, &handle->mechanisms); + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + krb5_free_principal(context, handle->principal); + free(handle); + return (ret); + } + *minor_status = 0; + *output_cred_handle = (gss_cred_id_t)handle; + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/krb5/add_cred.c b/third_party/heimdal/lib/gssapi/krb5/add_cred.c new file mode 100644 index 0000000..0bc61a7 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/add_cred.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred_from ( + OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + krb5_context context; + OM_uint32 major, lifetime; + gsskrb5_cred cred, handle; + krb5_const_principal dname; + + handle = NULL; + cred = (gsskrb5_cred)input_cred_handle; + dname = (krb5_const_principal)desired_name; + + if (cred == NULL && output_cred_handle == NULL) { + *minor_status = EINVAL; + return GSS_S_CALL_INACCESSIBLE_WRITE; + } + + GSSAPI_KRB5_INIT (&context); + + if (desired_mech != GSS_C_NO_OID && + gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) { + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + if (cred == NULL) { + /* + * Acquire a credential; output_cred_handle can't be NULL, see above. + */ + heim_assert(output_cred_handle != NULL, + "internal error in _gsskrb5_add_cred()"); + + major = _gsskrb5_acquire_cred_from(minor_status, desired_name, + min(initiator_time_req, + acceptor_time_req), + GSS_C_NO_OID_SET, + cred_usage, + cred_store, + output_cred_handle, + actual_mechs, &lifetime); + if (major != GSS_S_COMPLETE) + goto failure; + + } else { + /* + * Check that we're done or copy input to output if + * output_cred_handle != NULL. + */ + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + /* Check if requested output usage is compatible with output usage */ + if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return(GSS_S_FAILURE); + } + + /* Check that we have the same name */ + if (dname != NULL && + krb5_principal_compare(context, dname, + cred->principal) != FALSE) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = 0; + return GSS_S_BAD_NAME; + } + + if (output_cred_handle == NULL) { + /* + * This case is basically useless as we implement a single + * mechanism here, so we can't add elements to the + * input_cred_handle. + */ + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = 0; + return GSS_S_COMPLETE; + } + + /* + * Copy input to output -- this works as if we were a + * GSS_Duplicate_cred() for one mechanism element. + */ + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + if (cred != NULL) + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + handle->usage = cred_usage; + handle->endtime = cred->endtime; + handle->principal = NULL; + handle->destination_realm = NULL; + handle->keytab = NULL; + handle->ccache = NULL; + handle->mechanisms = NULL; + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + major = GSS_S_FAILURE; + + *minor_status = krb5_copy_principal(context, cred->principal, + &handle->principal); + if (*minor_status) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + free(handle); + return GSS_S_FAILURE; + } + + if (cred->keytab) { + char *name = NULL; + + *minor_status = krb5_kt_get_full_name(context, cred->keytab, + &name); + if (*minor_status) + goto failure; + + *minor_status = krb5_kt_resolve(context, name, &handle->keytab); + krb5_xfree(name); + if (*minor_status) + goto failure; + } + + if (cred->ccache) { + const char *type, *name; + char *type_name = NULL; + + type = krb5_cc_get_type(context, cred->ccache); + if (type == NULL){ + *minor_status = ENOMEM; + goto failure; + } + + if (strcmp(type, "MEMORY") == 0) { + *minor_status = krb5_cc_new_unique(context, type, + NULL, &handle->ccache); + if (*minor_status) + goto failure; + + *minor_status = krb5_cc_copy_cache(context, cred->ccache, + handle->ccache); + if (*minor_status) + goto failure; + + } else { + name = krb5_cc_get_name(context, cred->ccache); + if (name == NULL) { + *minor_status = ENOMEM; + goto failure; + } + + if (asprintf(&type_name, "%s:%s", type, name) == -1 || + type_name == NULL) { + *minor_status = ENOMEM; + goto failure; + } + + *minor_status = krb5_cc_resolve(context, type_name, + &handle->ccache); + free(type_name); + if (*minor_status) + goto failure; + } + } + major = gss_create_empty_oid_set(minor_status, &handle->mechanisms); + if (major != GSS_S_COMPLETE) + goto failure; + + major = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); + if (major != GSS_S_COMPLETE) + goto failure; + + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + + major = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred, + NULL, &lifetime, NULL, actual_mechs); + if (major != GSS_S_COMPLETE) + goto failure; + + *output_cred_handle = (gss_cred_id_t)handle; + } + + if (initiator_time_rec) + *initiator_time_rec = lifetime; + if (acceptor_time_rec) + *acceptor_time_rec = lifetime; + + *minor_status = 0; + return major; + +failure: + if (handle) { + if (handle->principal) + krb5_free_principal(context, handle->principal); + if (handle->keytab) + krb5_kt_close(context, handle->keytab); + if (handle->ccache) + krb5_cc_destroy(context, handle->ccache); + if (handle->mechanisms) + gss_release_oid_set(NULL, &handle->mechanisms); + free(handle); + } + if (cred && output_cred_handle) + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + return major; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/address_to_krb5addr.c b/third_party/heimdal/lib/gssapi/krb5/address_to_krb5addr.c new file mode 100644 index 0000000..fa115d9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/address_to_krb5addr.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +#include <roken.h> + +krb5_error_code +_gsskrb5i_address_to_krb5addr(krb5_context context, + OM_uint32 gss_addr_type, + gss_buffer_desc *gss_addr, + int16_t port, + krb5_address *address) +{ + int addr_type; + struct sockaddr sa; + krb5_socklen_t sa_size = sizeof(sa); + krb5_error_code problem; + + if (gss_addr == NULL) + return GSS_S_FAILURE; + + switch (gss_addr_type) { +#ifdef HAVE_IPV6 + case GSS_C_AF_INET6: addr_type = AF_INET6; + break; +#endif /* HAVE_IPV6 */ + + case GSS_C_AF_INET: addr_type = AF_INET; + break; + default: + return GSS_S_FAILURE; + } + + problem = krb5_h_addr2sockaddr (context, + addr_type, + gss_addr->value, + &sa, + &sa_size, + port); + if (problem) + return GSS_S_FAILURE; + + problem = krb5_sockaddr2address (context, &sa, address); + + return problem; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/aeap.c b/third_party/heimdal/lib/gssapi/krb5/aeap.c new file mode 100644 index 0000000..fe95ecf --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/aeap.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +#include <roken.h> + +OM_uint32 GSSAPI_CALLCONV +_gk_wrap_iov(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int * conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + krb5_context context; + OM_uint32 ret; + krb5_keyblock *key; + krb5_keytype keytype; + + GSSAPI_KRB5_INIT (&context); + + if (ctx->more_flags & IS_CFX) + return _gssapi_wrap_cfx_iov(minor_status, ctx, context, + conf_req_flag, conf_state, + iov, iov_count); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype(context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_wrap_iov_arcfour(minor_status, ctx, context, + conf_req_flag, conf_state, + iov, iov_count, key); + break; + + default: + ret = GSS_S_FAILURE; + break; + } + + krb5_free_keyblock(context, key); + return ret; +} + +OM_uint32 GSSAPI_CALLCONV +_gk_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + krb5_context context; + OM_uint32 ret; + krb5_keytype keytype; + krb5_keyblock *key; + + GSSAPI_KRB5_INIT (&context); + + if (ctx->more_flags & IS_CFX) + return _gssapi_unwrap_cfx_iov(minor_status, ctx, context, + conf_state, qop_state, iov, iov_count); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype(context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_unwrap_iov_arcfour(minor_status, ctx, context, + conf_state, qop_state, + iov, iov_count, key); + break; + + default: + ret = GSS_S_FAILURE; + break; + } + + krb5_free_keyblock(context, key); + return ret; +} + +OM_uint32 GSSAPI_CALLCONV +_gk_wrap_iov_length(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + krb5_context context; + OM_uint32 ret; + krb5_keytype keytype; + krb5_keyblock *key; + + GSSAPI_KRB5_INIT (&context); + + if (ctx->more_flags & IS_CFX) + return _gssapi_wrap_iov_length_cfx(minor_status, ctx, context, + conf_req_flag, qop_req, conf_state, + iov, iov_count); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype(context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_wrap_iov_length_arcfour(minor_status, ctx, context, + conf_req_flag, qop_req, conf_state, + iov, iov_count); + break; + + default: + ret = GSS_S_FAILURE; + break; + } + + krb5_free_keyblock(context, key); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/arcfour.c b/third_party/heimdal/lib/gssapi/krb5/arcfour.c new file mode 100644 index 0000000..5c754bc --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/arcfour.c @@ -0,0 +1,1391 @@ +/* + * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +/* + * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt + * + * The arcfour message have the following formats: + * + * MIC token + * TOK_ID[2] = 01 01 + * SGN_ALG[2] = 11 00 + * Filler[4] + * SND_SEQ[8] + * SGN_CKSUM[8] + * + * WRAP token + * TOK_ID[2] = 02 01 + * SGN_ALG[2]; + * SEAL_ALG[2] + * Filler[2] + * SND_SEQ[2] + * SGN_CKSUM[8] + * Confounder[8] + */ + +/* + * WRAP in DCE-style have a fixed size header, the oid and length over + * the WRAP header is a total of + * GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE + + * GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead, + * remember the 2 bytes from APPL [0] SEQ). + */ + +#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32 +#define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13 + + +static krb5_error_code +arcfour_mic_key(krb5_context context, krb5_keyblock *key, + const void *cksum_data, size_t cksum_size, + void *key6_data, size_t key6_size) +{ + krb5_error_code ret; + + Checksum cksum_k5; + krb5_keyblock key5; + char k5_data[16]; + + Checksum cksum_k6; + + char T[4]; + + memset(T, 0, 4); + cksum_k5.checksum.data = k5_data; + cksum_k5.checksum.length = sizeof(k5_data); + + if (key->keytype == KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56) { + char L40[14] = "fortybits"; + + memcpy(L40 + 10, T, sizeof(T)); + ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, + L40, 14, 0, key, &cksum_k5); + memset(&k5_data[7], 0xAB, 9); + } else { + ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, + T, 4, 0, key, &cksum_k5); + } + if (ret) + return ret; + + key5.keytype = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5; + key5.keyvalue = cksum_k5.checksum; + + cksum_k6.checksum.data = key6_data; + cksum_k6.checksum.length = key6_size; + + return krb5_hmac(context, CKSUMTYPE_RSA_MD5, + cksum_data, cksum_size, 0, &key5, &cksum_k6); +} + + +static krb5_error_code +arcfour_mic_cksum_iov(krb5_context context, + krb5_keyblock *key, unsigned usage, + u_char *sgn_cksum, size_t sgn_cksum_sz, + const u_char *v1, size_t l1, + const void *v2, size_t l2, + const gss_iov_buffer_desc *iov, + int iov_count, + const gss_iov_buffer_desc *padding) +{ + Checksum CKSUM; + u_char *ptr; + size_t len; + size_t ofs = 0; + int i; + krb5_crypto crypto; + krb5_error_code ret; + + assert(sgn_cksum_sz == 8); + + len = l1 + l2; + + for (i=0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + break; + default: + continue; + } + + len += iov[i].buffer.length; + } + + if (padding) { + len += padding->buffer.length; + } + + ptr = malloc(len); + if (ptr == NULL) + return ENOMEM; + + memcpy(ptr + ofs, v1, l1); + ofs += l1; + memcpy(ptr + ofs, v2, l2); + ofs += l2; + + for (i=0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + break; + default: + continue; + } + + if (iov[i].buffer.length > 0) { + assert(iov[i].buffer.value != NULL); + memcpy(ptr + ofs, + iov[i].buffer.value, + iov[i].buffer.length); + ofs += iov[i].buffer.length; + } + } + + if (padding) { + memcpy(ptr + ofs, + padding->buffer.value, + padding->buffer.length); + /* ofs += padding->buffer.length; */ + } + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free(ptr); + return ret; + } + + ret = krb5_create_checksum(context, + crypto, + usage, + 0, + ptr, len, + &CKSUM); + memset(ptr, 0, len); + free(ptr); + if (ret == 0) { + memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz); + free_Checksum(&CKSUM); + } + krb5_crypto_destroy(context, crypto); + + return ret; +} + +static krb5_error_code +arcfour_mic_cksum(krb5_context context, + krb5_keyblock *key, unsigned usage, + u_char *sgn_cksum, size_t sgn_cksum_sz, + const u_char *v1, size_t l1, + const void *v2, size_t l2, + const void *v3, size_t l3) +{ + gss_iov_buffer_desc iov; + + iov.type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov.buffer.value = rk_UNCONST(v3); + iov.buffer.length = l3; + + return arcfour_mic_cksum_iov(context, key, usage, + sgn_cksum, sgn_cksum_sz, + v1, l1, v2, l2, + &iov, 1, NULL); +} + + +OM_uint32 +_gssapi_get_mic_arcfour(OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key) +{ + krb5_error_code ret; + int32_t seq_number; + size_t len, total_len; + u_char k6_data[16], *p0, *p; + EVP_CIPHER_CTX rc4_key; + + _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); + + message_token->length = total_len; + message_token->value = malloc (total_len); + if (message_token->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p0 = _gssapi_make_mech_header(message_token->value, + len, + GSS_KRB5_MECHANISM); + p = p0; + + *p++ = 0x01; /* TOK_ID */ + *p++ = 0x01; + *p++ = 0x11; /* SGN_ALG */ + *p++ = 0x00; + *p++ = 0xff; /* Filler */ + *p++ = 0xff; + *p++ = 0xff; + *p++ = 0xff; + + p = NULL; + + ret = arcfour_mic_cksum(context, + key, KRB5_KU_USAGE_SIGN, + p0 + 16, 8, /* SGN_CKSUM */ + p0, 8, /* TOK_ID, SGN_ALG, Filer */ + message_buffer->value, message_buffer->length, + NULL, 0); + if (ret) { + _gsskrb5_release_buffer(minor_status, message_token); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = arcfour_mic_key(context, key, + p0 + 16, 8, /* SGN_CKSUM */ + k6_data, sizeof(k6_data)); + if (ret) { + _gsskrb5_release_buffer(minor_status, message_token); + *minor_status = ret; + return GSS_S_FAILURE; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber (context, + context_handle->auth_context, + &seq_number); + p = p0 + 8; /* SND_SEQ */ + _gsskrb5_encode_be_om_uint32(seq_number, p); + + krb5_auth_con_setlocalseqnumber (context, + context_handle->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4); + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + EVP_Cipher(&rc4_key, p, p, 8); + EVP_CIPHER_CTX_cleanup(&rc4_key); + + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + + +OM_uint32 +_gssapi_verify_mic_arcfour(OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + krb5_keyblock *key, + const char *type) +{ + krb5_error_code ret; + uint32_t seq_number; + OM_uint32 omret; + u_char SND_SEQ[8], cksum_data[8], *p; + char k6_data[16]; + int cmp; + + if (qop_state) + *qop_state = 0; + + p = token_buffer->value; + omret = _gsskrb5_verify_header (&p, + token_buffer->length, + type, + GSS_KRB5_MECHANISM); + if (omret) + return omret; + + if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + + ret = arcfour_mic_cksum(context, + key, KRB5_KU_USAGE_SIGN, + cksum_data, sizeof(cksum_data), + p - 8, 8, + message_buffer->value, message_buffer->length, + NULL, 0); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = arcfour_mic_key(context, key, + cksum_data, sizeof(cksum_data), + k6_data, sizeof(k6_data)); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + cmp = (ct_memcmp(cksum_data, p + 8, 8) != 0); + if (cmp) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0); + EVP_Cipher(&rc4_key, SND_SEQ, p, 8); + EVP_CIPHER_CTX_cleanup(&rc4_key); + + memset(k6_data, 0, sizeof(k6_data)); + } + + _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0); + else + cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0); + + memset_s(SND_SEQ, sizeof(SND_SEQ), 0, sizeof(SND_SEQ)); + if (cmp != 0) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + omret = _gssapi_msg_order_check(context_handle->order, seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (omret) + return omret; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_arcfour(OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer, + krb5_keyblock *key) +{ + u_char Klocaldata[16], k6_data[16], *p, *p0; + size_t len, total_len, datalen; + krb5_keyblock Klocal; + krb5_error_code ret; + int32_t seq_number; + + if (conf_state) + *conf_state = 0; + + datalen = input_message_buffer->length; + + if (IS_DCE_STYLE(context_handle)) { + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + total_len += datalen; + } else { + datalen += 1; /* padding */ + len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + } + + output_message_buffer->length = total_len; + output_message_buffer->value = malloc (total_len); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p0 = _gssapi_make_mech_header(output_message_buffer->value, + len, + GSS_KRB5_MECHANISM); + p = p0; + + *p++ = 0x02; /* TOK_ID */ + *p++ = 0x01; + *p++ = 0x11; /* SGN_ALG */ + *p++ = 0x00; + if (conf_req_flag) { + *p++ = 0x10; /* SEAL_ALG */ + *p++ = 0x00; + } else { + *p++ = 0xff; /* SEAL_ALG */ + *p++ = 0xff; + } + *p++ = 0xff; /* Filler */ + *p++ = 0xff; + + p = NULL; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber (context, + context_handle->auth_context, + &seq_number); + + _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8); + + krb5_auth_con_setlocalseqnumber (context, + context_handle->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + memset (p0 + 8 + 4, + (context_handle->more_flags & LOCAL) ? 0 : 0xff, + 4); + + krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */ + + /* p points to data */ + p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + memcpy(p, input_message_buffer->value, input_message_buffer->length); + + if (!IS_DCE_STYLE(context_handle)) + p[input_message_buffer->length] = 1; /* padding */ + + ret = arcfour_mic_cksum(context, + key, KRB5_KU_USAGE_SEAL, + p0 + 16, 8, /* SGN_CKSUM */ + p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */ + p0 + 24, 8, /* Confounder */ + p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, + datalen); + if (ret) { + *minor_status = ret; + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_FAILURE; + } + + { + int i; + + Klocal.keytype = key->keytype; + Klocal.keyvalue.data = Klocaldata; + Klocal.keyvalue.length = sizeof(Klocaldata); + + for (i = 0; i < 16; i++) + Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; + } + ret = arcfour_mic_key(context, &Klocal, + p0 + 8, 4, /* SND_SEQ */ + k6_data, sizeof(k6_data)); + memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata)); + if (ret) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = ret; + return GSS_S_FAILURE; + } + + + if(conf_req_flag) { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen); + EVP_CIPHER_CTX_cleanup(&rc4_key); + } + memset(k6_data, 0, sizeof(k6_data)); + + ret = arcfour_mic_key(context, key, + p0 + 16, 8, /* SGN_CKSUM */ + k6_data, sizeof(k6_data)); + if (ret) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = ret; + return GSS_S_FAILURE; + } + + { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8); + EVP_CIPHER_CTX_cleanup(&rc4_key); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); + } + + if (conf_state) + *conf_state = conf_req_flag; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state, + krb5_keyblock *key) +{ + u_char Klocaldata[16]; + krb5_keyblock Klocal; + krb5_error_code ret; + uint32_t seq_number; + size_t datalen; + OM_uint32 omret; + u_char k6_data[16], SND_SEQ[8], Confounder[8]; + u_char cksum_data[8]; + u_char *p, *p0; + int cmp; + int conf_flag; + size_t padlen = 0, len; + + if (conf_state) + *conf_state = 0; + if (qop_state) + *qop_state = 0; + + p0 = input_message_buffer->value; + + if (IS_DCE_STYLE(context_handle)) { + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + + GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; + if (input_message_buffer->length < len) + return GSS_S_BAD_MECH; + } else { + len = input_message_buffer->length; + } + + omret = _gssapi_verify_mech_header(&p0, + len, + GSS_KRB5_MECHANISM); + if (omret) + return omret; + + /* length of mech header */ + len = (p0 - (u_char *)input_message_buffer->value) + + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + + if (len > input_message_buffer->length) + return GSS_S_BAD_MECH; + + /* length of data */ + datalen = input_message_buffer->length - len; + + p = p0; + + if (memcmp(p, "\x02\x01", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ + return GSS_S_BAD_SIG; + p += 2; + + if (memcmp (p, "\x10\x00", 2) == 0) + conf_flag = 1; + else if (memcmp (p, "\xff\xff", 2) == 0) + conf_flag = 0; + else + return GSS_S_BAD_SIG; + + p += 2; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_BAD_MIC; + p = NULL; + + ret = arcfour_mic_key(context, key, + p0 + 16, 8, /* SGN_CKSUM */ + k6_data, sizeof(k6_data)); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8); + EVP_CIPHER_CTX_cleanup(&rc4_key); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); + } + + _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0); + else + cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0); + + if (cmp != 0) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + { + int i; + + Klocal.keytype = key->keytype; + Klocal.keyvalue.data = Klocaldata; + Klocal.keyvalue.length = sizeof(Klocaldata); + + for (i = 0; i < 16; i++) + Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; + } + ret = arcfour_mic_key(context, &Klocal, + SND_SEQ, 4, + k6_data, sizeof(k6_data)); + memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata)); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + output_message_buffer->value = malloc(datalen); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + output_message_buffer->length = datalen; + + if(conf_flag) { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8); + EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); + EVP_CIPHER_CTX_cleanup(&rc4_key); + } else { + memcpy(Confounder, p0 + 24, 8); /* Confounder */ + memcpy(output_message_buffer->value, + p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, + datalen); + } + memset(k6_data, 0, sizeof(k6_data)); + + if (!IS_DCE_STYLE(context_handle)) { + ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); + if (ret) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = 0; + return ret; + } + output_message_buffer->length -= padlen; + } + + ret = arcfour_mic_cksum(context, + key, KRB5_KU_USAGE_SEAL, + cksum_data, sizeof(cksum_data), + p0, 8, + Confounder, sizeof(Confounder), + output_message_buffer->value, + output_message_buffer->length + padlen); + if (ret) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = ret; + return GSS_S_FAILURE; + } + + cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ + if (cmp) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + omret = _gssapi_msg_order_check(context_handle->order, seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (omret) + return omret; + + if (conf_state) + *conf_state = conf_flag; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +max_wrap_length_arcfour(const gsskrb5_ctx ctx, + krb5_crypto crypto, + size_t input_length, + OM_uint32 *max_input_size) +{ + /* + * if GSS_C_DCE_STYLE is in use: + * - we only need to encapsulate the WRAP token + * However, since this is a fixed since, we just + */ + if (IS_DCE_STYLE(ctx)) { + size_t len, total_len; + + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + if (input_length < len) + *max_input_size = 0; + else + *max_input_size = input_length - len; + + } else { + size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + size_t blocksize = 8; + size_t len, total_len; + + len = 8 + input_length + blocksize + extrasize; + + _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + total_len -= input_length; /* token length */ + if (total_len < input_length) { + *max_input_size = (input_length - total_len); + (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); + } else { + *max_input_size = 0; + } + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_size_arcfour(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret != 0) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = max_wrap_length_arcfour(ctx, crypto, + req_output_size, max_input_size); + if (ret != 0) { + *minor_status = ret; + krb5_crypto_destroy(context, crypto); + return GSS_S_FAILURE; + } + + krb5_crypto_destroy(context, crypto); + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_iov_length_arcfour(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + size_t data_len = 0; + int i; + gss_iov_buffer_desc *header = NULL; + gss_iov_buffer_desc *padding = NULL; + gss_iov_buffer_desc *trailer = NULL; + + *minor_status = 0; + + for (i = 0; i < iov_count; i++) { + switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_EMPTY: + break; + case GSS_IOV_BUFFER_TYPE_DATA: + data_len += iov[i].buffer.length; + break; + case GSS_IOV_BUFFER_TYPE_HEADER: + if (header != NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + header = &iov[i]; + break; + case GSS_IOV_BUFFER_TYPE_TRAILER: + if (trailer != NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + trailer = &iov[i]; + break; + case GSS_IOV_BUFFER_TYPE_PADDING: + if (padding != NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + padding = &iov[i]; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + break; + default: + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + major_status = _gk_verify_buffers(minor_status, ctx, header, + padding, trailer, FALSE); + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + if (IS_DCE_STYLE(ctx)) { + size_t len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + size_t total_len; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + header->buffer.length = total_len; + } else { + size_t len; + size_t total_len; + if (padding) { + data_len += 1; /* padding */ + } + len = data_len + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + header->buffer.length = total_len - data_len; + } + + if (trailer) { + trailer->buffer.length = 0; + } + + if (padding) { + padding->buffer.length = 1; + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_iov_arcfour(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + krb5_keyblock *key) +{ + OM_uint32 major_status, junk; + gss_iov_buffer_desc *header, *padding, *trailer; + krb5_error_code kret; + int32_t seq_number; + u_char Klocaldata[16], k6_data[16], *p, *p0; + size_t make_len = 0; + size_t header_len = 0; + size_t data_len = 0; + krb5_keyblock Klocal; + int i; + + header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + major_status = _gk_verify_buffers(minor_status, ctx, header, + padding, trailer, FALSE); + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + for (i = 0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + break; + default: + continue; + } + + data_len += iov[i].buffer.length; + } + + if (padding) { + data_len += 1; + } + + if (IS_DCE_STYLE(ctx)) { + size_t unwrapped_len; + unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(unwrapped_len, + &make_len, + &header_len, + GSS_KRB5_MECHANISM); + } else { + size_t unwrapped_len; + unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + data_len; + _gssapi_encap_length(unwrapped_len, + &make_len, + &header_len, + GSS_KRB5_MECHANISM); + header_len -= data_len; + } + + if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + major_status = _gk_allocate_buffer(minor_status, header, + header_len); + if (major_status != GSS_S_COMPLETE) + goto failure; + } else if (header->buffer.length < header_len) { + *minor_status = KRB5_BAD_MSIZE; + major_status = GSS_S_FAILURE; + goto failure; + } else { + header->buffer.length = header_len; + } + + if (padding) { + if (GSS_IOV_BUFFER_FLAGS(padding->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + major_status = _gk_allocate_buffer(minor_status, padding, 1); + if (major_status != GSS_S_COMPLETE) + goto failure; + } else if (padding->buffer.length < 1) { + *minor_status = KRB5_BAD_MSIZE; + major_status = GSS_S_FAILURE; + goto failure; + } else { + padding->buffer.length = 1; + } + memset(padding->buffer.value, 1, 1); + } + + if (trailer) { + trailer->buffer.length = 0; + trailer->buffer.value = NULL; + } + + p0 = _gssapi_make_mech_header(header->buffer.value, + make_len, + GSS_KRB5_MECHANISM); + p = p0; + + *p++ = 0x02; /* TOK_ID */ + *p++ = 0x01; + *p++ = 0x11; /* SGN_ALG */ + *p++ = 0x00; + if (conf_req_flag) { + *p++ = 0x10; /* SEAL_ALG */ + *p++ = 0x00; + } else { + *p++ = 0xff; /* SEAL_ALG */ + *p++ = 0xff; + } + *p++ = 0xff; /* Filler */ + *p++ = 0xff; + + p = NULL; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber(context, + ctx->auth_context, + &seq_number); + _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8); + + krb5_auth_con_setlocalseqnumber(context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + memset(p0 + 8 + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xff, + 4); + + krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */ + + /* Sign Data */ + kret = arcfour_mic_cksum_iov(context, + key, KRB5_KU_USAGE_SEAL, + p0 + 16, 8, /* SGN_CKSUM */ + p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */ + p0 + 24, 8, /* Confounder */ + iov, iov_count, /* Data + SignOnly */ + padding); /* padding */ + if (kret) { + *minor_status = kret; + major_status = GSS_S_FAILURE; + goto failure; + } + + Klocal.keytype = key->keytype; + Klocal.keyvalue.data = Klocaldata; + Klocal.keyvalue.length = sizeof(Klocaldata); + + for (i = 0; i < 16; i++) { + Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; + } + kret = arcfour_mic_key(context, &Klocal, + p0 + 8, 4, /* SND_SEQ */ + k6_data, sizeof(k6_data)); + memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata)); + if (kret) { + *minor_status = kret; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (conf_req_flag) { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + + /* Confounder */ + EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8); + + /* Seal Data */ + for (i=0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + break; + default: + continue; + } + + EVP_Cipher(&rc4_key, iov[i].buffer.value, + iov[i].buffer.value, iov[i].buffer.length); + } + + /* Padding */ + if (padding) { + EVP_Cipher(&rc4_key, padding->buffer.value, + padding->buffer.value, padding->buffer.length); + } + + EVP_CIPHER_CTX_cleanup(&rc4_key); + } + memset(k6_data, 0, sizeof(k6_data)); + + kret = arcfour_mic_key(context, key, + p0 + 16, 8, /* SGN_CKSUM */ + k6_data, sizeof(k6_data)); + if (kret) { + *minor_status = kret; + major_status = GSS_S_FAILURE; + return major_status; + } + + { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + EVP_Cipher(&rc4_key, p0 + 8, p0 + 8, 8); /* SND_SEQ */ + EVP_CIPHER_CTX_cleanup(&rc4_key); + + memset(k6_data, 0, sizeof(k6_data)); + } + + if (conf_state) + *conf_state = conf_req_flag; + + *minor_status = 0; + return GSS_S_COMPLETE; + +failure: + + gss_release_iov_buffer(&junk, iov, iov_count); + + return major_status; +} + +OM_uint32 +_gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int *pconf_state, + gss_qop_t *pqop_state, + gss_iov_buffer_desc *iov, + int iov_count, + krb5_keyblock *key) +{ + OM_uint32 major_status; + gss_iov_buffer_desc *header, *padding, *trailer; + krb5_keyblock Klocal; + uint8_t Klocaldata[16]; + uint8_t k6_data[16], snd_seq[8], Confounder[8]; + uint8_t cksum_data[8]; + uint8_t *_p = NULL; + const uint8_t *p, *p0; + size_t verify_len = 0; + uint32_t seq_number; + size_t hlen = 0; + int conf_state; + int cmp; + size_t i; + krb5_error_code kret; + OM_uint32 ret; + + if (pconf_state != NULL) { + *pconf_state = 0; + } + if (pqop_state != NULL) { + *pqop_state = 0; + } + + header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + /* Check if the packet is correct */ + major_status = _gk_verify_buffers(minor_status, + ctx, + header, + padding, + trailer, + FALSE); /* behaves as stream cipher */ + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + if (padding != NULL && padding->buffer.length != 1) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + verify_len = header->buffer.length; + + if (!IS_DCE_STYLE(ctx)) { + for (i = 0; i < iov_count; i++) { + /* length in header also includes data and padding */ + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) + verify_len += iov[i].buffer.length; + } + + if (padding) + verify_len += padding->buffer.length; + } + + _p = header->buffer.value; + + ret = _gssapi_verify_mech_header(&_p, + verify_len, + GSS_KRB5_MECHANISM); + if (ret) { + return ret; + } + p0 = _p; + + /* length of mech header */ + hlen = (p0 - (uint8_t *)header->buffer.value); + hlen += GSS_ARCFOUR_WRAP_TOKEN_SIZE; + + if (hlen > header->buffer.length) { + return GSS_S_BAD_MECH; + } + + p = p0; + + if (memcmp(p, "\x02\x01", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ + return GSS_S_BAD_SIG; + p += 2; + + if (memcmp (p, "\x10\x00", 2) == 0) + conf_state = 1; + else if (memcmp (p, "\xff\xff", 2) == 0) + conf_state = 0; + else + return GSS_S_BAD_SIG; + + p += 2; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_BAD_MIC; + p = NULL; + + kret = arcfour_mic_key(context, + key, + p0 + 16, /* SGN_CKSUM */ + 8, /* SGN_CKSUM_LEN */ + k6_data, + sizeof(k6_data)); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + EVP_Cipher(&rc4_key, snd_seq, p0 + 8, 8); /* SND_SEQ */ + EVP_CIPHER_CTX_cleanup(&rc4_key); + + memset(k6_data, 0, sizeof(k6_data)); + } + + _gsskrb5_decode_be_om_uint32(snd_seq, &seq_number); + + if (ctx->more_flags & LOCAL) { + cmp = (ct_memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4) != 0); + } else { + cmp = (ct_memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4) != 0); + } + if (cmp != 0) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + /* keyblock */ + Klocal.keytype = key->keytype; + Klocal.keyvalue.data = Klocaldata; + Klocal.keyvalue.length = sizeof(Klocaldata); + + for (i = 0; i < 16; i++) { + Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; + } + + kret = arcfour_mic_key(context, + &Klocal, + snd_seq, + 4, + k6_data, sizeof(k6_data)); + memset_s(Klocaldata, sizeof(Klocaldata), 0, sizeof(Klocaldata)); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (conf_state == 1) { + EVP_CIPHER_CTX rc4_key; + + EVP_CIPHER_CTX_init(&rc4_key); + EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); + + /* Confounder */ + EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8); + + /* Data */ + for (i = 0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + break; + default: + continue; + } + + EVP_Cipher(&rc4_key, iov[i].buffer.value, + iov[i].buffer.value, iov[i].buffer.length); + } + + /* Padding */ + if (padding) { + EVP_Cipher(&rc4_key, padding->buffer.value, + padding->buffer.value, padding->buffer.length); + } + + EVP_CIPHER_CTX_cleanup(&rc4_key); + } else { + /* Confounder */ + memcpy(Confounder, p0 + 24, 8); + } + memset(k6_data, 0, sizeof(k6_data)); + + /* Prepare the buffer for signing */ + kret = arcfour_mic_cksum_iov(context, + key, KRB5_KU_USAGE_SEAL, + cksum_data, sizeof(cksum_data), + p0, 8, + Confounder, sizeof(Confounder), + iov, iov_count, + padding); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + cmp = (ct_memcmp(cksum_data, p0 + 16, 8) != 0); /* SGN_CKSUM */ + if (cmp) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + if (padding) { + size_t plen; + + ret = _gssapi_verify_pad(&padding->buffer, 1, &plen); + if (ret) { + *minor_status = 0; + return ret; + } + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gssapi_msg_order_check(ctx->order, seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret != 0) { + return ret; + } + + if (pconf_state) { + *pconf_state = conf_state; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/authorize_localname.c b/third_party/heimdal/lib/gssapi/krb5/authorize_localname.c new file mode 100644 index 0000000..5621c1f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/authorize_localname.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_authorize_localname(OM_uint32 *minor_status, + gss_const_name_t input_name, + gss_const_buffer_t user_name, + gss_const_OID user_name_type) +{ + krb5_context context; + krb5_principal princ = (krb5_principal)input_name; + char *user; + int user_ok; + + if (!gss_oid_equal(user_name_type, GSS_C_NT_USER_NAME)) + return GSS_S_BAD_NAMETYPE; + + GSSAPI_KRB5_INIT(&context); + + user = malloc(user_name->length + 1); + if (user == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy(user, user_name->value, user_name->length); + user[user_name->length] = '\0'; + + *minor_status = 0; + user_ok = krb5_kuserok(context, princ, user); + + free(user); + + return user_ok ? GSS_S_COMPLETE : GSS_S_UNAUTHORIZED; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/canonicalize_name.c b/third_party/heimdal/lib/gssapi/krb5/canonicalize_name.c new file mode 100644 index 0000000..62de423 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/canonicalize_name.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_canonicalize_name ( + OM_uint32 * minor_status, + gss_const_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ) +{ + krb5_context context; + krb5_principal name; + OM_uint32 ret; + + *output_name = NULL; + + GSSAPI_KRB5_INIT (&context); + + ret = _gsskrb5_canon_name(minor_status, context, input_name, &name); + if (ret) + return ret; + + *output_name = (gss_name_t)name; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/ccache_name.c b/third_party/heimdal/lib/gssapi/krb5/ccache_name.c new file mode 100644 index 0000000..0a2d596 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/ccache_name.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static heim_base_atomic(char *) last_out_name; /* XXX should be thread-specific */ + +OM_uint32 +_gsskrb5_krb5_ccache_name(OM_uint32 *minor_status, + const char *name, + const char **out_name) +{ + krb5_context context; + krb5_error_code kret; + + *minor_status = 0; + + GSSAPI_KRB5_INIT(&context); + + if (out_name) { + const char *def_name; + + *out_name = NULL; + + def_name = krb5_cc_default_name(context); + if (def_name) { + char *s = strdup(def_name); + if (s) { + s = heim_base_exchange_pointer(&last_out_name, s); + free(s); + + *out_name = last_out_name; + } + } + + if (*out_name == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + } + + kret = krb5_cc_set_default_name(context, name); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/cfx.c b/third_party/heimdal/lib/gssapi/krb5/cfx.c new file mode 100644 index 0000000..8d806f9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/cfx.c @@ -0,0 +1,1797 @@ +/* + * Copyright (c) 2003, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +/* + * Implementation of RFC 4121 + */ + +#define CFXSentByAcceptor (1 << 0) +#define CFXSealed (1 << 1) +#define CFXAcceptorSubkey (1 << 2) + +krb5_error_code +_gsskrb5cfx_wrap_length_cfx(krb5_context context, + krb5_crypto crypto, + int conf_req_flag, + int dce_style, + size_t input_length, + size_t *output_length, + size_t *cksumsize, + uint16_t *padlength) +{ + krb5_error_code ret; + krb5_cksumtype type; + + /* 16-byte header is always first */ + *output_length = sizeof(gss_cfx_wrap_token_desc); + *padlength = 0; + + ret = krb5_crypto_get_checksum_type(context, crypto, &type); + if (ret) + return ret; + + ret = krb5_checksumsize(context, type, cksumsize); + if (ret) + return ret; + + if (conf_req_flag) { + size_t padsize; + + /* Header is concatenated with data before encryption */ + input_length += sizeof(gss_cfx_wrap_token_desc); + + if (dce_style) { + ret = krb5_crypto_getblocksize(context, crypto, &padsize); + } else { + ret = krb5_crypto_getpadsize(context, crypto, &padsize); + } + if (ret) { + return ret; + } + if (padsize > 1) { + /* XXX check this */ + *padlength = padsize - (input_length % padsize); + + /* We add the pad ourselves (noted here for completeness only) */ + input_length += *padlength; + } + + *output_length += krb5_get_wrapped_length(context, + crypto, input_length); + } else { + /* Checksum is concatenated with data */ + *output_length += input_length + *cksumsize; + } + + assert(*output_length > input_length); + + return 0; +} + +OM_uint32 +_gssapi_wrap_size_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + krb5_error_code ret; + + *max_input_size = 0; + + /* 16-byte header is always first */ + if (req_output_size < 16) + return 0; + req_output_size -= 16; + + if (conf_req_flag) { + size_t wrapped_size, sz; + + wrapped_size = req_output_size + 1; + do { + wrapped_size--; + sz = krb5_get_wrapped_length(context, + ctx->crypto, wrapped_size); + } while (wrapped_size && sz > req_output_size); + if (wrapped_size == 0) + return 0; + + /* inner header */ + if (wrapped_size < 16) + return 0; + + wrapped_size -= 16; + + *max_input_size = wrapped_size; + } else { + krb5_cksumtype type; + size_t cksumsize; + + ret = krb5_crypto_get_checksum_type(context, ctx->crypto, &type); + if (ret) + return ret; + + ret = krb5_checksumsize(context, type, &cksumsize); + if (ret) + return ret; + + if (req_output_size < cksumsize) + return 0; + + /* Checksum is concatenated with data */ + *max_input_size = req_output_size - cksumsize; + } + + return 0; +} + +/* + * Rotate "rrc" bytes to the front or back + */ + +static krb5_error_code +rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate) +{ + u_char *tmp, buf[256]; + size_t left; + + if (len == 0) + return 0; + + rrc %= len; + + if (rrc == 0) + return 0; + + left = len - rrc; + + if (rrc <= sizeof(buf)) { + tmp = buf; + } else { + tmp = malloc(rrc); + if (tmp == NULL) + return ENOMEM; + } + + if (unrotate) { + memcpy(tmp, data, rrc); + memmove(data, (u_char *)data + rrc, left); + memcpy((u_char *)data + left, tmp, rrc); + } else { + memcpy(tmp, (u_char *)data + left, rrc); + memmove((u_char *)data + rrc, data, left); + memcpy(data, tmp, rrc); + } + + if (rrc > sizeof(buf)) + free(tmp); + + return 0; +} + +gss_iov_buffer_desc * +_gk_find_buffer(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type) +{ + int i; + gss_iov_buffer_t iovp = GSS_C_NO_IOV_BUFFER; + + if (iov == GSS_C_NO_IOV_BUFFER) + return GSS_C_NO_IOV_BUFFER; + + /* + * This function is used to find header, padding or trailer buffers + * which are singletons; return NULL if multiple instances are found. + */ + for (i = 0; i < iov_count; i++) { + if (type == GSS_IOV_BUFFER_TYPE(iov[i].type)) { + if (iovp == GSS_C_NO_IOV_BUFFER) + iovp = &iov[i]; + else + return GSS_C_NO_IOV_BUFFER; + } + } + + /* + * For compatibility with SSPI, an empty padding buffer is treated + * equivalent to an absent padding buffer (unless the caller is + * requesting that a padding buffer be allocated). + */ + if (iovp && + iovp->buffer.length == 0 && + type == GSS_IOV_BUFFER_TYPE_PADDING && + (GSS_IOV_BUFFER_FLAGS(iovp->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) == 0) + iovp = NULL; + + return iovp; +} + +OM_uint32 +_gk_allocate_buffer(OM_uint32 *minor_status, gss_iov_buffer_desc *buffer, size_t size) +{ + if (buffer->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + if (buffer->buffer.length == size) + return GSS_S_COMPLETE; + free(buffer->buffer.value); + } + + buffer->buffer.value = malloc(size); + buffer->buffer.length = size; + if (buffer->buffer.value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + buffer->type |= GSS_IOV_BUFFER_FLAG_ALLOCATED; + + return GSS_S_COMPLETE; +} + + +OM_uint32 +_gk_verify_buffers(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + const gss_iov_buffer_desc *header, + const gss_iov_buffer_desc *padding, + const gss_iov_buffer_desc *trailer, + int block_cipher) +{ + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (IS_DCE_STYLE(ctx)) { + /* + * In DCE style mode we reject having a padding or trailer buffer + */ + if (padding) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + if (trailer) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } else { + /* + * In non-DCE style mode we require having a padding buffer for + * encryption types that do not behave as stream ciphers. This + * check is superfluous for now, as only RC4 and RFC4121 enctypes + * are presently implemented for the IOV APIs; be defensive. + */ + if (block_cipher && padding == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_cfx_iov(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status, junk; + gss_iov_buffer_desc *header, *trailer, *padding; + size_t gsshsize, k5hsize; + size_t gsstsize, k5tsize; + size_t rrc = 0, ec = 0; + int i; + gss_cfx_wrap_token token; + krb5_error_code ret; + int32_t seq_number; + unsigned usage; + krb5_crypto_iov *data = NULL; + + header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding != NULL) { + padding->buffer.length = 0; + } + + trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + major_status = _gk_verify_buffers(minor_status, ctx, header, + padding, trailer, FALSE); + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + if (conf_req_flag) { + size_t k5psize = 0; + size_t k5pbase = 0; + size_t k5bsize = 0; + size_t size = 0; + + for (i = 0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + size += iov[i].buffer.length; + break; + default: + break; + } + } + + size += sizeof(gss_cfx_wrap_token_desc); + + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_HEADER, + &k5hsize); + if (*minor_status) + return GSS_S_FAILURE; + + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_TRAILER, + &k5tsize); + if (*minor_status) + return GSS_S_FAILURE; + + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_PADDING, + &k5pbase); + if (*minor_status) + return GSS_S_FAILURE; + + if (k5pbase > 1) { + k5psize = k5pbase - (size % k5pbase); + } else { + k5psize = 0; + } + + if (k5psize == 0 && IS_DCE_STYLE(ctx)) { + *minor_status = krb5_crypto_getblocksize(context, ctx->crypto, + &k5bsize); + if (*minor_status) + return GSS_S_FAILURE; + ec = k5bsize; + } else { + ec = k5psize; + } + + gsshsize = sizeof(gss_cfx_wrap_token_desc) + k5hsize; + gsstsize = sizeof(gss_cfx_wrap_token_desc) + ec + k5tsize; + } else { + if (IS_DCE_STYLE(ctx)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + k5hsize = 0; + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_CHECKSUM, + &k5tsize); + if (*minor_status) + return GSS_S_FAILURE; + + gsshsize = sizeof(gss_cfx_wrap_token_desc); + gsstsize = k5tsize; + } + + /* + * + */ + + if (trailer == NULL) { + rrc = gsstsize; + if (IS_DCE_STYLE(ctx)) + rrc -= ec; + gsshsize += gsstsize; + } else if (GSS_IOV_BUFFER_FLAGS(trailer->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + major_status = _gk_allocate_buffer(minor_status, trailer, gsstsize); + if (major_status) + goto failure; + } else if (trailer->buffer.length < gsstsize) { + *minor_status = KRB5_BAD_MSIZE; + major_status = GSS_S_FAILURE; + goto failure; + } else + trailer->buffer.length = gsstsize; + + /* + * + */ + + if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + major_status = _gk_allocate_buffer(minor_status, header, gsshsize); + if (major_status != GSS_S_COMPLETE) + goto failure; + } else if (header->buffer.length < gsshsize) { + *minor_status = KRB5_BAD_MSIZE; + major_status = GSS_S_FAILURE; + goto failure; + } else + header->buffer.length = gsshsize; + + token = (gss_cfx_wrap_token)header->buffer.value; + + token->TOK_ID[0] = 0x05; + token->TOK_ID[1] = 0x04; + token->Flags = 0; + token->Filler = 0xFF; + + if ((ctx->more_flags & LOCAL) == 0) + token->Flags |= CFXSentByAcceptor; + + if (ctx->more_flags & ACCEPTOR_SUBKEY) + token->Flags |= CFXAcceptorSubkey; + + if (ctx->more_flags & LOCAL) + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + else + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + + if (conf_req_flag) { + /* + * In Wrap tokens with confidentiality, the EC field is + * used to encode the size (in bytes) of the random filler. + */ + token->Flags |= CFXSealed; + token->EC[0] = (ec >> 8) & 0xFF; + token->EC[1] = (ec >> 0) & 0xFF; + + } else { + /* + * In Wrap tokens without confidentiality, the EC field is + * used to encode the size (in bytes) of the trailing + * checksum. + * + * This is not used in the checksum calcuation itself, + * because the checksum length could potentially vary + * depending on the data length. + */ + token->EC[0] = 0; + token->EC[1] = 0; + } + + /* + * In Wrap tokens that provide for confidentiality, the RRC + * field in the header contains the hex value 00 00 before + * encryption. + * + * In Wrap tokens that do not provide for confidentiality, + * both the EC and RRC fields in the appended checksum + * contain the hex value 00 00 for the purpose of calculating + * the checksum. + */ + token->RRC[0] = 0; + token->RRC[1] = 0; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber(context, + ctx->auth_context, + &seq_number); + _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); + _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); + krb5_auth_con_setlocalseqnumber(context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + data = calloc(iov_count + 3, sizeof(data[0])); + if (data == NULL) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (conf_req_flag) { + /* + plain packet: + + {"header" | encrypt(plaintext-data | ec-padding | E"header")} + + Expanded, this is with with RRC = 0: + + {"header" | krb5-header | plaintext-data | ec-padding | E"header" | krb5-trailer } + + In DCE-RPC mode == no trailer: RRC = gss "trailer" == length(ec-padding | E"header" | krb5-trailer) + + {"header" | ec-padding | E"header" | krb5-trailer | krb5-header | plaintext-data } + */ + + i = 0; + data[i].flags = KRB5_CRYPTO_TYPE_HEADER; + data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize; + data[i].data.length = k5hsize; + + for (i = 1; i < iov_count + 1; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i - 1].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[i - 1].buffer.length; + data[i].data.data = iov[i - 1].buffer.value; + } + + /* + * Any necessary padding is added here to ensure that the + * encrypted token header is always at the end of the + * ciphertext. + */ + + /* encrypted CFX header in trailer (or after the header if in + DCE mode). Copy in header into E"header" + */ + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + if (trailer) + data[i].data.data = trailer->buffer.value; + else + data[i].data.data = ((uint8_t *)header->buffer.value) + sizeof(*token); + + data[i].data.length = ec + sizeof(*token); + memset(data[i].data.data, 0xFF, ec); + memcpy(((uint8_t *)data[i].data.data) + ec, token, sizeof(*token)); + i++; + + /* Kerberos trailer comes after the gss trailer */ + data[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + data[i].data.data = ((uint8_t *)data[i-1].data.data) + ec + sizeof(*token); + data[i].data.length = k5tsize; + i++; + + ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL); + if (ret != 0) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (rrc) { + token->RRC[0] = (rrc >> 8) & 0xFF; + token->RRC[1] = (rrc >> 0) & 0xFF; + } + + } else { + /* + plain packet: + + {data | "header" | gss-trailer (krb5 checksum) + + don't do RRC != 0 + + */ + + for (i = 0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[i].buffer.length; + data[i].data.data = iov[i].buffer.value; + } + + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + data[i].data.data = header->buffer.value; + data[i].data.length = sizeof(gss_cfx_wrap_token_desc); + i++; + + data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + if (trailer) { + data[i].data.data = trailer->buffer.value; + } else { + data[i].data.data = (uint8_t *)header->buffer.value + + sizeof(gss_cfx_wrap_token_desc); + } + data[i].data.length = k5tsize; + i++; + + ret = krb5_create_checksum_iov(context, ctx->crypto, usage, data, i, NULL); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (rrc) { + token->RRC[0] = (rrc >> 8) & 0xFF; + token->RRC[1] = (rrc >> 0) & 0xFF; + } + + token->EC[0] = (k5tsize >> 8) & 0xFF; + token->EC[1] = (k5tsize >> 0) & 0xFF; + } + + if (conf_state != NULL) + *conf_state = conf_req_flag; + + free(data); + + *minor_status = 0; + return GSS_S_COMPLETE; + + failure: + if (data) + free(data); + + gss_release_iov_buffer(&junk, iov, iov_count); + + return major_status; +} + +/* This is slowpath */ +static OM_uint32 +unrotate_iov(OM_uint32 *minor_status, size_t rrc, gss_iov_buffer_desc *iov, int iov_count) +{ + uint8_t *p, *q; + size_t len = 0, skip; + int i; + + for (i = 0; i < iov_count; i++) + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + len += iov[i].buffer.length; + + p = malloc(len); + if (p == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + q = p; + + /* copy up */ + + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + { + memcpy(q, iov[i].buffer.value, iov[i].buffer.length); + q += iov[i].buffer.length; + } + } + assert((size_t)(q - p) == len); + + /* unrotate first part */ + q = p + rrc; + skip = rrc; + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + { + if (iov[i].buffer.length <= skip) { + skip -= iov[i].buffer.length; + } else { + /* copy back to original buffer */ + memcpy(((uint8_t *)iov[i].buffer.value) + skip, q, iov[i].buffer.length - skip); + q += iov[i].buffer.length - skip; + skip = 0; + } + } + } + /* copy trailer */ + q = p; + skip = rrc; + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + { + memcpy(iov[i].buffer.value, q, min(iov[i].buffer.length, skip)); + if (iov[i].buffer.length > skip) + break; + skip -= iov[i].buffer.length; + q += iov[i].buffer.length; + } + } + free(p); + return GSS_S_COMPLETE; +} + + +OM_uint32 +_gssapi_unwrap_cfx_iov(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 seq_number_lo, seq_number_hi, major_status, junk; + gss_iov_buffer_desc *header, *trailer, *padding; + gss_cfx_wrap_token token, ttoken; + u_char token_flags; + krb5_error_code ret; + unsigned usage; + uint16_t ec, rrc; + krb5_crypto_iov *data = NULL; + int i, j; + + *minor_status = 0; + + header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (header->buffer.length < sizeof(*token)) /* we check exact below */ + return GSS_S_DEFECTIVE_TOKEN; + + padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding != NULL && padding->buffer.length != 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + major_status = _gk_verify_buffers(minor_status, ctx, header, + padding, trailer, FALSE); + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + token = (gss_cfx_wrap_token)header->buffer.value; + + if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) + return GSS_S_DEFECTIVE_TOKEN; + + /* Ignore unknown flags */ + token_flags = token->Flags & + (CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey); + + if (token_flags & CFXSentByAcceptor) { + if ((ctx->more_flags & LOCAL) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ctx->more_flags & ACCEPTOR_SUBKEY) { + if ((token_flags & CFXAcceptorSubkey) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } else { + if (token_flags & CFXAcceptorSubkey) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (token->Filler != 0xFF) + return GSS_S_DEFECTIVE_TOKEN; + + if (conf_state != NULL) + *conf_state = (token_flags & CFXSealed) ? 1 : 0; + + ec = (token->EC[0] << 8) | token->EC[1]; + rrc = (token->RRC[0] << 8) | token->RRC[1]; + + /* + * Check sequence number + */ + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); + if (seq_number_hi) { + /* no support for 64-bit sequence numbers */ + *minor_status = ERANGE; + return GSS_S_UNSEQ_TOKEN; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); + if (ret != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* + * Decrypt and/or verify checksum + */ + + if (ctx->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + } else { + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + } + + data = calloc(iov_count + 3, sizeof(data[0])); + if (data == NULL) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (token_flags & CFXSealed) { + size_t k5tsize, k5hsize; + + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &k5hsize); + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5tsize); + + /* Rotate by RRC; bogus to do this in-place XXX */ + /* Check RRC */ + + if (trailer == NULL) { + size_t gsstsize = k5tsize + sizeof(*token); + size_t gsshsize = k5hsize + sizeof(*token); + + if (rrc != gsstsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } + + if (IS_DCE_STYLE(ctx)) + gsstsize += ec; + + gsshsize += gsstsize; + + if (header->buffer.length != gsshsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } + } else if (trailer->buffer.length != sizeof(*token) + k5tsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } else if (header->buffer.length != sizeof(*token) + k5hsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } else if (rrc != 0) { + /* go though slowpath */ + major_status = unrotate_iov(minor_status, rrc, iov, iov_count); + if (major_status) + goto failure; + } + + i = 0; + data[i].flags = KRB5_CRYPTO_TYPE_HEADER; + data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize; + data[i].data.length = k5hsize; + i++; + + for (j = 0; j < iov_count; i++, j++) { + switch (GSS_IOV_BUFFER_TYPE(iov[j].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[j].buffer.length; + data[i].data.data = iov[j].buffer.value; + } + + /* encrypted CFX header in trailer (or after the header if in + DCE mode). Copy in header into E"header" + */ + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + if (trailer) { + data[i].data.data = trailer->buffer.value; + } else { + data[i].data.data = ((uint8_t *)header->buffer.value) + + header->buffer.length - k5hsize - k5tsize - ec- sizeof(*token); + } + + data[i].data.length = ec + sizeof(*token); + ttoken = (gss_cfx_wrap_token)(((uint8_t *)data[i].data.data) + ec); + i++; + + /* Kerberos trailer comes after the gss trailer */ + data[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + data[i].data.data = ((uint8_t *)data[i-1].data.data) + ec + sizeof(*token); + data[i].data.length = k5tsize; + i++; + + ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL); + if (ret != 0) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + + ttoken->RRC[0] = token->RRC[0]; + ttoken->RRC[1] = token->RRC[1]; + + /* Check the integrity of the header */ + if (ct_memcmp(ttoken, token, sizeof(*token)) != 0) { + major_status = GSS_S_BAD_MIC; + goto failure; + } + } else { + size_t gsstsize = ec; + size_t gsshsize = sizeof(*token); + + if (trailer == NULL) { + /* Check RRC */ + if (rrc != gsstsize) { + *minor_status = EINVAL; + major_status = GSS_S_FAILURE; + goto failure; + } + + gsshsize += gsstsize; + } else if (trailer->buffer.length != gsstsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } else if (rrc != 0) { + /* Check RRC */ + *minor_status = EINVAL; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (header->buffer.length != gsshsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } + + for (i = 0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[i].buffer.length; + data[i].data.data = iov[i].buffer.value; + } + + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + data[i].data.data = header->buffer.value; + data[i].data.length = sizeof(*token); + i++; + + data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + if (trailer) { + data[i].data.data = trailer->buffer.value; + } else { + data[i].data.data = (uint8_t *)header->buffer.value + + sizeof(*token); + } + data[i].data.length = ec; + i++; + + token = (gss_cfx_wrap_token)header->buffer.value; + token->EC[0] = 0; + token->EC[1] = 0; + token->RRC[0] = 0; + token->RRC[1] = 0; + + ret = krb5_verify_checksum_iov(context, ctx->crypto, usage, data, i, NULL); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + } + + if (qop_state != NULL) { + *qop_state = GSS_C_QOP_DEFAULT; + } + + free(data); + + *minor_status = 0; + return GSS_S_COMPLETE; + + failure: + if (data) + free(data); + + gss_release_iov_buffer(&junk, iov, iov_count); + + return major_status; +} + +OM_uint32 +_gssapi_wrap_iov_length_cfx(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + size_t size; + int i; + gss_iov_buffer_desc *header = NULL; + gss_iov_buffer_desc *padding = NULL; + gss_iov_buffer_desc *trailer = NULL; + size_t gsshsize = 0; + size_t gsstsize = 0; + size_t k5hsize = 0; + size_t k5tsize = 0; + + GSSAPI_KRB5_INIT (&context); + *minor_status = 0; + + for (size = 0, i = 0; i < iov_count; i++) { + switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_EMPTY: + break; + case GSS_IOV_BUFFER_TYPE_DATA: + size += iov[i].buffer.length; + break; + case GSS_IOV_BUFFER_TYPE_HEADER: + if (header != NULL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + header = &iov[i]; + break; + case GSS_IOV_BUFFER_TYPE_TRAILER: + if (trailer != NULL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + trailer = &iov[i]; + break; + case GSS_IOV_BUFFER_TYPE_PADDING: + if (padding != NULL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + padding = &iov[i]; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + break; + default: + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + + major_status = _gk_verify_buffers(minor_status, ctx, header, + padding, trailer, FALSE); + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + if (conf_req_flag) { + size_t k5psize = 0; + size_t k5pbase = 0; + size_t k5bsize = 0; + size_t ec = 0; + + size += sizeof(gss_cfx_wrap_token_desc); + + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_HEADER, + &k5hsize); + if (*minor_status) + return GSS_S_FAILURE; + + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_TRAILER, + &k5tsize); + if (*minor_status) + return GSS_S_FAILURE; + + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_PADDING, + &k5pbase); + if (*minor_status) + return GSS_S_FAILURE; + + if (k5pbase > 1) { + k5psize = k5pbase - (size % k5pbase); + } else { + k5psize = 0; + } + + if (k5psize == 0 && IS_DCE_STYLE(ctx)) { + *minor_status = krb5_crypto_getblocksize(context, ctx->crypto, + &k5bsize); + if (*minor_status) + return GSS_S_FAILURE; + + ec = k5bsize; + } else { + ec = k5psize; + } + + gsshsize = sizeof(gss_cfx_wrap_token_desc) + k5hsize; + gsstsize = sizeof(gss_cfx_wrap_token_desc) + ec + k5tsize; + } else { + *minor_status = krb5_crypto_length(context, ctx->crypto, + KRB5_CRYPTO_TYPE_CHECKSUM, + &k5tsize); + if (*minor_status) + return GSS_S_FAILURE; + + gsshsize = sizeof(gss_cfx_wrap_token_desc); + gsstsize = k5tsize; + } + + if (trailer != NULL) { + trailer->buffer.length = gsstsize; + } else { + gsshsize += gsstsize; + } + + header->buffer.length = gsshsize; + + if (padding) { + /* padding is done via EC and is contained in the header or trailer */ + padding->buffer.length = 0; + } + + if (conf_state) { + *conf_state = conf_req_flag; + } + + return GSS_S_COMPLETE; +} + + + + +OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + const gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + gss_cfx_wrap_token token; + krb5_error_code ret; + unsigned usage; + krb5_data cipher; + size_t wrapped_len, cksumsize; + uint16_t padlength, rrc = 0; + int32_t seq_number; + u_char *p; + + ret = _gsskrb5cfx_wrap_length_cfx(context, + ctx->crypto, conf_req_flag, + IS_DCE_STYLE(ctx), + input_message_buffer->length, + &wrapped_len, &cksumsize, &padlength); + if (ret != 0) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* Always rotate encrypted token (if any) and checksum to header */ + rrc = (conf_req_flag ? sizeof(*token) : 0) + (uint16_t)cksumsize; + + output_message_buffer->length = wrapped_len; + output_message_buffer->value = malloc(output_message_buffer->length); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = output_message_buffer->value; + token = (gss_cfx_wrap_token)p; + token->TOK_ID[0] = 0x05; + token->TOK_ID[1] = 0x04; + token->Flags = 0; + token->Filler = 0xFF; + if ((ctx->more_flags & LOCAL) == 0) + token->Flags |= CFXSentByAcceptor; + if (ctx->more_flags & ACCEPTOR_SUBKEY) + token->Flags |= CFXAcceptorSubkey; + if (conf_req_flag) { + /* + * In Wrap tokens with confidentiality, the EC field is + * used to encode the size (in bytes) of the random filler. + */ + token->Flags |= CFXSealed; + token->EC[0] = (padlength >> 8) & 0xFF; + token->EC[1] = (padlength >> 0) & 0xFF; + } else { + /* + * In Wrap tokens without confidentiality, the EC field is + * used to encode the size (in bytes) of the trailing + * checksum. + * + * This is not used in the checksum calcuation itself, + * because the checksum length could potentially vary + * depending on the data length. + */ + token->EC[0] = 0; + token->EC[1] = 0; + } + + /* + * In Wrap tokens that provide for confidentiality, the RRC + * field in the header contains the hex value 00 00 before + * encryption. + * + * In Wrap tokens that do not provide for confidentiality, + * both the EC and RRC fields in the appended checksum + * contain the hex value 00 00 for the purpose of calculating + * the checksum. + */ + token->RRC[0] = 0; + token->RRC[1] = 0; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber(context, + ctx->auth_context, + &seq_number); + _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); + _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); + krb5_auth_con_setlocalseqnumber(context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* + * If confidentiality is requested, the token header is + * appended to the plaintext before encryption; the resulting + * token is {"header" | encrypt(plaintext | pad | "header")}. + * + * If no confidentiality is requested, the checksum is + * calculated over the plaintext concatenated with the + * token header. + */ + if (ctx->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + } else { + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + } + + if (conf_req_flag) { + /* + * Any necessary padding is added here to ensure that the + * encrypted token header is always at the end of the + * ciphertext. + * + * The specification does not require that the padding + * bytes are initialized. + */ + p += sizeof(*token); + memcpy(p, input_message_buffer->value, input_message_buffer->length); + memset(p + input_message_buffer->length, 0xFF, padlength); + memcpy(p + input_message_buffer->length + padlength, + token, sizeof(*token)); + + ret = krb5_encrypt(context, ctx->crypto, + usage, p, + input_message_buffer->length + padlength + + sizeof(*token), + &cipher); + if (ret != 0) { + *minor_status = ret; + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_FAILURE; + } + assert(sizeof(*token) + cipher.length == wrapped_len); + token->RRC[0] = (rrc >> 8) & 0xFF; + token->RRC[1] = (rrc >> 0) & 0xFF; + + /* + * this is really ugly, but needed against windows + * for DCERPC, as windows rotates by EC+RRC. + */ + if (IS_DCE_STYLE(ctx)) { + ret = rrc_rotate(cipher.data, cipher.length, rrc+padlength, FALSE); + } else { + ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE); + } + if (ret != 0) { + *minor_status = ret; + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_FAILURE; + } + memcpy(p, cipher.data, cipher.length); + krb5_data_free(&cipher); + } else { + char *buf; + Checksum cksum; + + buf = malloc(input_message_buffer->length + sizeof(*token)); + if (buf == NULL) { + *minor_status = ENOMEM; + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_FAILURE; + } + memcpy(buf, input_message_buffer->value, input_message_buffer->length); + memcpy(buf + input_message_buffer->length, token, sizeof(*token)); + + ret = krb5_create_checksum(context, ctx->crypto, + usage, 0, buf, + input_message_buffer->length + + sizeof(*token), + &cksum); + if (ret != 0) { + *minor_status = ret; + _gsskrb5_release_buffer(minor_status, output_message_buffer); + free(buf); + return GSS_S_FAILURE; + } + + free(buf); + + assert(cksum.checksum.length == cksumsize); + token->EC[0] = (cksum.checksum.length >> 8) & 0xFF; + token->EC[1] = (cksum.checksum.length >> 0) & 0xFF; + token->RRC[0] = (rrc >> 8) & 0xFF; + token->RRC[1] = (rrc >> 0) & 0xFF; + + p += sizeof(*token); + memcpy(p, input_message_buffer->value, input_message_buffer->length); + memcpy(p + input_message_buffer->length, + cksum.checksum.data, cksum.checksum.length); + + ret = rrc_rotate(p, + input_message_buffer->length + cksum.checksum.length, rrc, FALSE); + if (ret != 0) { + *minor_status = ret; + _gsskrb5_release_buffer(minor_status, output_message_buffer); + free_Checksum(&cksum); + return GSS_S_FAILURE; + } + free_Checksum(&cksum); + } + + if (conf_state != NULL) { + *conf_state = conf_req_flag; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + gss_cfx_wrap_token token; + u_char token_flags; + krb5_error_code ret; + unsigned usage; + krb5_data data; + uint16_t ec, rrc; + OM_uint32 seq_number_lo, seq_number_hi; + size_t len; + u_char *p; + + *minor_status = 0; + + if (input_message_buffer->length < sizeof(*token)) { + return GSS_S_DEFECTIVE_TOKEN; + } + + p = input_message_buffer->value; + + token = (gss_cfx_wrap_token)p; + + if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) { + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Ignore unknown flags */ + token_flags = token->Flags & + (CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey); + + if (token_flags & CFXSentByAcceptor) { + if ((ctx->more_flags & LOCAL) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ctx->more_flags & ACCEPTOR_SUBKEY) { + if ((token_flags & CFXAcceptorSubkey) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } else { + if (token_flags & CFXAcceptorSubkey) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (token->Filler != 0xFF) { + return GSS_S_DEFECTIVE_TOKEN; + } + + if (conf_state != NULL) { + *conf_state = (token_flags & CFXSealed) ? 1 : 0; + } + + ec = (token->EC[0] << 8) | token->EC[1]; + rrc = (token->RRC[0] << 8) | token->RRC[1]; + + /* + * Check sequence number + */ + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); + if (seq_number_hi) { + /* no support for 64-bit sequence numbers */ + *minor_status = ERANGE; + return GSS_S_UNSEQ_TOKEN; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); + if (ret != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return ret; + } + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* + * Decrypt and/or verify checksum + */ + + if (ctx->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + } else { + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + } + + p += sizeof(*token); + len = input_message_buffer->length; + len -= (p - (u_char *)input_message_buffer->value); + + if (token_flags & CFXSealed) { + /* + * this is really ugly, but needed against windows + * for DCERPC, as windows rotates by EC+RRC. + */ + if (IS_DCE_STYLE(ctx)) { + *minor_status = rrc_rotate(p, len, rrc+ec, TRUE); + } else { + *minor_status = rrc_rotate(p, len, rrc, TRUE); + } + if (*minor_status != 0) { + return GSS_S_FAILURE; + } + + ret = krb5_decrypt(context, ctx->crypto, usage, + p, len, &data); + if (ret != 0) { + *minor_status = ret; + return GSS_S_BAD_MIC; + } + + /* Check that there is room for the pad and token header */ + if (data.length < ec + sizeof(*token)) { + krb5_data_free(&data); + return GSS_S_DEFECTIVE_TOKEN; + } + p = data.data; + p += data.length - sizeof(*token); + + /* RRC is unprotected; don't modify input buffer */ + ((gss_cfx_wrap_token)p)->RRC[0] = token->RRC[0]; + ((gss_cfx_wrap_token)p)->RRC[1] = token->RRC[1]; + + /* Check the integrity of the header */ + if (ct_memcmp(p, token, sizeof(*token)) != 0) { + krb5_data_free(&data); + return GSS_S_BAD_MIC; + } + + output_message_buffer->value = data.data; + output_message_buffer->length = data.length - ec - sizeof(*token); + } else { + Checksum cksum; + + /* Rotate by RRC; bogus to do this in-place XXX */ + *minor_status = rrc_rotate(p, len, rrc, TRUE); + if (*minor_status != 0) { + return GSS_S_FAILURE; + } + + /* Determine checksum type */ + ret = krb5_crypto_get_checksum_type(context, + ctx->crypto, + &cksum.cksumtype); + if (ret != 0) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + cksum.checksum.length = ec; + + /* Check we have at least as much data as the checksum */ + if (len < cksum.checksum.length) { + *minor_status = ERANGE; + return GSS_S_BAD_MIC; + } + + /* Length now is of the plaintext only, no checksum */ + len -= cksum.checksum.length; + cksum.checksum.data = p + len; + + output_message_buffer->length = len; /* for later */ + output_message_buffer->value = malloc(len + sizeof(*token)); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + /* Checksum is over (plaintext-data | "header") */ + memcpy(output_message_buffer->value, p, len); + memcpy((u_char *)output_message_buffer->value + len, + token, sizeof(*token)); + + /* EC is not included in checksum calculation */ + token = (gss_cfx_wrap_token)((u_char *)output_message_buffer->value + + len); + token->EC[0] = 0; + token->EC[1] = 0; + token->RRC[0] = 0; + token->RRC[1] = 0; + + ret = krb5_verify_checksum(context, ctx->crypto, + usage, + output_message_buffer->value, + len + sizeof(*token), + &cksum); + if (ret != 0) { + *minor_status = ret; + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_BAD_MIC; + } + } + + if (qop_state != NULL) { + *qop_state = GSS_C_QOP_DEFAULT; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + gss_cfx_mic_token token; + krb5_error_code ret; + unsigned usage; + Checksum cksum; + u_char *buf; + size_t len; + int32_t seq_number; + + len = message_buffer->length + sizeof(*token); + buf = malloc(len); + if (buf == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy(buf, message_buffer->value, message_buffer->length); + + token = (gss_cfx_mic_token)(buf + message_buffer->length); + token->TOK_ID[0] = 0x04; + token->TOK_ID[1] = 0x04; + token->Flags = 0; + if ((ctx->more_flags & LOCAL) == 0) + token->Flags |= CFXSentByAcceptor; + if (ctx->more_flags & ACCEPTOR_SUBKEY) + token->Flags |= CFXAcceptorSubkey; + memset(token->Filler, 0xFF, 5); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber(context, + ctx->auth_context, + &seq_number); + _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); + _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); + krb5_auth_con_setlocalseqnumber(context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (ctx->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_INITIATOR_SIGN; + } else { + usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; + } + + ret = krb5_create_checksum(context, ctx->crypto, + usage, 0, buf, len, &cksum); + if (ret != 0) { + *minor_status = ret; + free(buf); + return GSS_S_FAILURE; + } + + /* Determine MIC length */ + message_token->length = sizeof(*token) + cksum.checksum.length; + message_token->value = malloc(message_token->length); + if (message_token->value == NULL) { + *minor_status = ENOMEM; + free_Checksum(&cksum); + free(buf); + return GSS_S_FAILURE; + } + + /* Token is { "header" | get_mic("header" | plaintext-data) } */ + memcpy(message_token->value, token, sizeof(*token)); + memcpy((u_char *)message_token->value + sizeof(*token), + cksum.checksum.data, cksum.checksum.length); + + free_Checksum(&cksum); + free(buf); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + gss_cfx_mic_token token; + u_char token_flags; + krb5_error_code ret; + unsigned usage; + OM_uint32 seq_number_lo, seq_number_hi; + u_char *buf, *p; + Checksum cksum; + + *minor_status = 0; + + if (token_buffer->length < sizeof(*token)) { + return GSS_S_DEFECTIVE_TOKEN; + } + + p = token_buffer->value; + + token = (gss_cfx_mic_token)p; + + if (token->TOK_ID[0] != 0x04 || token->TOK_ID[1] != 0x04) { + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Ignore unknown flags */ + token_flags = token->Flags & (CFXSentByAcceptor | CFXAcceptorSubkey); + + if (token_flags & CFXSentByAcceptor) { + if ((ctx->more_flags & LOCAL) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } + if (ctx->more_flags & ACCEPTOR_SUBKEY) { + if ((token_flags & CFXAcceptorSubkey) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } else { + if (token_flags & CFXAcceptorSubkey) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ct_memcmp(token->Filler, "\xff\xff\xff\xff\xff", 5) != 0) { + return GSS_S_DEFECTIVE_TOKEN; + } + + /* + * Check sequence number + */ + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); + if (seq_number_hi) { + *minor_status = ERANGE; + return GSS_S_UNSEQ_TOKEN; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); + if (ret != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* + * Verify checksum + */ + ret = krb5_crypto_get_checksum_type(context, ctx->crypto, + &cksum.cksumtype); + if (ret != 0) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + cksum.checksum.data = p + sizeof(*token); + cksum.checksum.length = token_buffer->length - sizeof(*token); + + if (ctx->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; + } else { + usage = KRB5_KU_USAGE_INITIATOR_SIGN; + } + + buf = malloc(message_buffer->length + sizeof(*token)); + if (buf == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(buf, message_buffer->value, message_buffer->length); + memcpy(buf + message_buffer->length, token, sizeof(*token)); + + ret = krb5_verify_checksum(context, ctx->crypto, + usage, + buf, + sizeof(*token) + message_buffer->length, + &cksum); + if (ret != 0) { + *minor_status = ret; + free(buf); + return GSS_S_BAD_MIC; + } + + free(buf); + + if (qop_state != NULL) { + *qop_state = GSS_C_QOP_DEFAULT; + } + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/cfx.h b/third_party/heimdal/lib/gssapi/krb5/cfx.h new file mode 100644 index 0000000..c30ed07 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/cfx.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef GSSAPI_CFX_H_ +#define GSSAPI_CFX_H_ 1 + +/* + * Implementation of draft-ietf-krb-wg-gssapi-cfx-01.txt + */ + +typedef struct gss_cfx_mic_token_desc_struct { + u_char TOK_ID[2]; /* 04 04 */ + u_char Flags; + u_char Filler[5]; + u_char SND_SEQ[8]; +} gss_cfx_mic_token_desc, *gss_cfx_mic_token; + +typedef struct gss_cfx_wrap_token_desc_struct { + u_char TOK_ID[2]; /* 04 05 */ + u_char Flags; + u_char Filler; + u_char EC[2]; + u_char RRC[2]; + u_char SND_SEQ[8]; +} gss_cfx_wrap_token_desc, *gss_cfx_wrap_token; + +typedef struct gss_cfx_delete_token_desc_struct { + u_char TOK_ID[2]; /* 05 04 */ + u_char Flags; + u_char Filler[5]; + u_char SND_SEQ[8]; +} gss_cfx_delete_token_desc, *gss_cfx_delete_token; + +#endif /* GSSAPI_CFX_H_ */ diff --git a/third_party/heimdal/lib/gssapi/krb5/compare_name.c b/third_party/heimdal/lib/gssapi/krb5/compare_name.c new file mode 100644 index 0000000..4a37e87 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/compare_name.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_compare_name + (OM_uint32 * minor_status, + gss_const_name_t name1, + gss_const_name_t name2, + int * name_equal + ) +{ + krb5_const_principal princ1 = (krb5_const_principal)name1; + krb5_const_principal princ2 = (krb5_const_principal)name2; + krb5_context context; + + GSSAPI_KRB5_INIT(&context); + + *name_equal = krb5_principal_compare (context, + princ1, princ2); + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/compat.c b/third_party/heimdal/lib/gssapi/krb5/compat.c new file mode 100644 index 0000000..3381dff --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/compat.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static krb5_error_code +check_compat(OM_uint32 *minor_status, + krb5_context context, krb5_const_principal name, + const char *option, krb5_boolean *compat, + krb5_boolean match_val) +{ + krb5_error_code ret = 0; + char **p, **q; + krb5_principal match; + + + p = krb5_config_get_strings(context, NULL, "gssapi", + option, NULL); + if(p == NULL) + return 0; + + match = NULL; + for(q = p; *q; q++) { + ret = krb5_parse_name(context, *q, &match); + if (ret) + break; + + if (krb5_principal_match(context, name, match)) { + *compat = match_val; + break; + } + + krb5_free_principal(context, match); + match = NULL; + } + if (match) + krb5_free_principal(context, match); + krb5_config_free_strings(p); + + if (ret) { + if (minor_status) + *minor_status = ret; + return GSS_S_FAILURE; + } + + return 0; +} + +/* + * ctx->ctx_id_mutex is assumed to be locked + */ + +OM_uint32 +_gss_DES3_get_mic_compat(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context) +{ + krb5_boolean use_compat = FALSE; + OM_uint32 ret; + + if ((ctx->more_flags & COMPAT_OLD_DES3_SELECTED) == 0) { + ret = check_compat(minor_status, context, ctx->target, + "broken_des3_mic", &use_compat, TRUE); + if (ret) + return ret; + ret = check_compat(minor_status, context, ctx->target, + "correct_des3_mic", &use_compat, FALSE); + if (ret) + return ret; + + if (use_compat) + ctx->more_flags |= COMPAT_OLD_DES3; + ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; + } + return 0; +} + +#if 0 +OM_uint32 +gss_krb5_compat_des3_mic(OM_uint32 *minor_status, gss_ctx_id_t ctx, int on) +{ + *minor_status = 0; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (on) { + ctx->more_flags |= COMPAT_OLD_DES3; + } else { + ctx->more_flags &= ~COMPAT_OLD_DES3; + } + ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + return 0; +} +#endif diff --git a/third_party/heimdal/lib/gssapi/krb5/context_time.c b/third_party/heimdal/lib/gssapi/krb5/context_time.c new file mode 100644 index 0000000..58249cb --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/context_time.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 +_gsskrb5_lifetime_left(OM_uint32 *minor_status, + krb5_context context, + OM_uint32 endtime, + OM_uint32 *lifetime_rec) +{ + krb5_timestamp now; + krb5_error_code kret; + + if (endtime == 0) { + *lifetime_rec = GSS_C_INDEFINITE; + return GSS_S_COMPLETE; + } + + kret = krb5_timeofday(context, &now); + if (kret) { + *lifetime_rec = 0; + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (endtime < now) + *lifetime_rec = 0; + else + *lifetime_rec = endtime - now; + + return GSS_S_COMPLETE; +} + + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_context_time + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + OM_uint32 * time_rec + ) +{ + krb5_context context; + OM_uint32 endtime; + OM_uint32 major_status; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + + GSSAPI_KRB5_INIT (&context); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + endtime = ctx->endtime; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + major_status = _gsskrb5_lifetime_left(minor_status, context, + endtime, time_rec); + if (major_status != GSS_S_COMPLETE) + return major_status; + + *minor_status = 0; + + if (*time_rec == 0) + return GSS_S_CONTEXT_EXPIRED; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c b/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c new file mode 100644 index 0000000..fc0b9b1 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2000 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +#if 0 +OM_uint32 +gss_krb5_copy_ccache(OM_uint32 *minor_status, + krb5_context context, + gss_cred_id_t cred, + krb5_ccache out) +{ + krb5_error_code kret; + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + if (cred->ccache == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + kret = krb5_cc_copy_cache(context, cred->ccache, out); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + *minor_status = 0; + return GSS_S_COMPLETE; +} +#endif + + +/* + * WARNING: Takes ownership of `id'. Because MEMORY:anonymous is now not + * linked into to the MEMORY ccache namespace, we can't use krb5_cc_resolve() + * with the cache's name anymore. We need a krb5_cc_clone() or some such, with + * attendant new method for ccops. Or we could create a new MEMORY:anonymous + * ccache and copy all the creds from `id' into it. But we know callers of + * this function don't need `id' after calling it, so for now we'll just take + * ownershipd of it. + */ +OM_uint32 +_gsskrb5_krb5_import_cred(OM_uint32 *minor_status, + krb5_ccache *id, + krb5_principal keytab_principal, + krb5_keytab keytab, + gss_cred_id_t *cred) +{ + krb5_context context; + krb5_error_code kret; + gsskrb5_cred handle; + OM_uint32 ret; + int id_given = (*id != NULL); + + *cred = NULL; + + GSSAPI_KRB5_INIT (&context); + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + _gsskrb5_clear_status (); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + handle->usage = 0; + handle->destination_realm = NULL; + + if (*id) { + time_t now; + OM_uint32 left; + + handle->usage |= GSS_C_INITIATE; + + kret = krb5_cc_get_principal(context, *id, + &handle->principal); + if (kret) { + free(handle); + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (keytab_principal) { + krb5_boolean match; + + match = krb5_principal_compare(context, + handle->principal, + keytab_principal); + if (match == FALSE) { + krb5_free_principal(context, handle->principal); + free(handle); + _gsskrb5_clear_status (); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + + krb5_timeofday(context, &now); + ret = __gsskrb5_ccache_lifetime(minor_status, + context, + *id, + handle->principal, + &left); + if (ret != GSS_S_COMPLETE) { + krb5_free_principal(context, handle->principal); + free(handle); + return ret; + } + handle->endtime = now + left; + + handle->ccache = *id; + *id = NULL; + } + + + if (keytab) { + char *str; + + handle->usage |= GSS_C_ACCEPT; + + if (keytab_principal && handle->principal == NULL) { + kret = krb5_copy_principal(context, + keytab_principal, + &handle->principal); + if (kret) + goto out; + } + + kret = krb5_kt_get_full_name(context, keytab, &str); + if (kret) + goto out; + + kret = krb5_kt_resolve(context, str, &handle->keytab); + free(str); + if (kret) + goto out; + } + + + if (id_given || keytab) { + ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); + if (ret == GSS_S_COMPLETE) + ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); + if (ret != GSS_S_COMPLETE) { + kret = *minor_status; + goto out; + } + } + + *minor_status = 0; + *cred = (gss_cred_id_t)handle; + return GSS_S_COMPLETE; + +out: + gss_release_oid_set(minor_status, &handle->mechanisms); + if (handle->ccache) + krb5_cc_close(context, handle->ccache); + if (handle->keytab) + krb5_kt_close(context, handle->keytab); + if (handle->principal) + krb5_free_principal(context, handle->principal); + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + free(handle); + *minor_status = kret; + return GSS_S_FAILURE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/creds.c b/third_party/heimdal/lib/gssapi/krb5/creds.c new file mode 100644 index 0000000..efb0a23 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/creds.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_export_cred(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t cred_token) +{ + OM_uint32 major_status; + gsskrb5_cred handle = (gsskrb5_cred)cred_handle; + krb5_context context; + krb5_error_code ret; + krb5_storage *sp; + krb5_data data; + const char *type; + char *str; + + GSSAPI_KRB5_INIT (&context); + + if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_FAILURE; + } + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + type = krb5_cc_get_type(context, handle->ccache); + if (strcmp(type, "MEMORY") == 0) { + krb5_creds *creds; + krb5_data config_start_realm; + char *start_realm; + + ret = krb5_store_uint32(sp, 0); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_get_config(context, handle->ccache, NULL, "start_realm", + &config_start_realm); + if (ret == 0) { + start_realm = strndup(config_start_realm.data, + config_start_realm.length); + krb5_data_free(&config_start_realm); + } else { + start_realm = strdup(krb5_principal_get_realm(context, + handle->principal)); + } + if (start_realm == NULL) { + *minor_status = krb5_enomem(context); + krb5_storage_free(sp); + return GSS_S_FAILURE; + } + + ret = _krb5_get_krbtgt(context, handle->ccache, start_realm, &creds); + free(start_realm); + start_realm = NULL; + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_store_creds(sp, creds); + krb5_free_creds(context, creds); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + } else { + ret = krb5_store_uint32(sp, 1); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_get_full_name(context, handle->ccache, &str); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_store_string(sp, str); + free(str); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + } + ret = krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_data_free(&data); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + major_status = _gss_mg_store_oid(minor_status, sp, GSS_KRB5_MECHANISM); + if (major_status != GSS_S_COMPLETE) { + krb5_data_free(&data); + krb5_storage_free(sp); + return major_status; + } + + ret = krb5_store_data(sp, data); + krb5_data_free(&data); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + cred_token->value = data.data; + cred_token->length = data.length; + + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_import_cred(OM_uint32 * minor_status, + gss_buffer_t cred_token, + gss_cred_id_t * cred_handle) +{ + krb5_context context; + krb5_error_code ret; + gsskrb5_cred handle; + krb5_ccache id; + krb5_storage *sp; + char *str; + uint32_t type; + int flags = 0; + + *cred_handle = GSS_C_NO_CREDENTIAL; + + GSSAPI_KRB5_INIT (&context); + + sp = krb5_storage_from_mem(cred_token->value, cred_token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = krb5_ret_uint32(sp, &type); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + switch (type) { + case 0: { + krb5_creds creds; + + ret = krb5_ret_creds(sp, &creds); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_initialize(context, id, creds.client); + if (ret) { + krb5_cc_destroy(context, id); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_store_cred(context, id, &creds); + krb5_free_cred_contents(context, &creds); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + + break; + } + case 1: + ret = krb5_ret_string(sp, &str); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_resolve(context, str, &id); + krb5_xfree(str); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + break; + + default: + krb5_storage_free(sp); + *minor_status = 0; + return GSS_S_NO_CRED; + } + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + krb5_cc_close(context, id); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + handle->usage = GSS_C_INITIATE; + handle->destination_realm = NULL; + krb5_cc_get_principal(context, id, &handle->principal); + handle->ccache = id; + handle->cred_flags = flags; + + *cred_handle = (gss_cred_id_t)handle; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/decapsulate.c b/third_party/heimdal/lib/gssapi/krb5/decapsulate.c new file mode 100644 index 0000000..d7b75a6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/decapsulate.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +/* + * return the length of the mechanism in token or -1 + * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN + */ + +ssize_t +_gsskrb5_get_mech (const u_char *ptr, + size_t total_len, + const u_char **mech_ret) +{ + size_t len, len_len, mech_len, foo; + const u_char *p = ptr; + int e; + + if (total_len < 1) + return -1; + if (*p++ != 0x60) + return -1; + e = der_get_length (p, total_len - 1, &len, &len_len); + if (e || 1 + len_len + len != total_len) + return -1; + if (total_len < 1 + len_len + 1) + return -1; + p += len_len; + if (*p++ != 0x06) + return -1; + e = der_get_length (p, total_len - 1 - len_len - 1, + &mech_len, &foo); + if (e) + return -1; + p += foo; + *mech_ret = p; + return mech_len; +} + +OM_uint32 +_gssapi_verify_mech_header(u_char **str, + size_t total_len, + gss_OID mech) +{ + const u_char *p; + ssize_t mech_len; + + mech_len = _gsskrb5_get_mech (*str, total_len, &p); + if (mech_len < 0) + return GSS_S_DEFECTIVE_TOKEN; + + if (mech_len != mech->length) + return GSS_S_BAD_MECH; + if (mech_len > total_len) + return GSS_S_BAD_MECH; + if (p - *str > total_len - mech_len) + return GSS_S_BAD_MECH; + if (ct_memcmp(p, + mech->elements, + mech->length) != 0) + return GSS_S_BAD_MECH; + p += mech_len; + *str = rk_UNCONST(p); + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_verify_header(u_char **str, + size_t total_len, + const void *type, + gss_OID oid) +{ + OM_uint32 ret; + size_t len; + u_char *p = *str; + + ret = _gssapi_verify_mech_header(str, total_len, oid); + if (ret) + return ret; + + len = total_len - (*str - p); + + if (len < 2) + return GSS_S_DEFECTIVE_TOKEN; + + if (ct_memcmp (*str, type, 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + *str += 2; + + return 0; +} + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +_gssapi_decapsulate( + OM_uint32 *minor_status, + gss_buffer_t input_token_buffer, + krb5_data *out_data, + const gss_OID mech +) +{ + u_char *p; + OM_uint32 ret; + + p = input_token_buffer->value; + ret = _gssapi_verify_mech_header(&p, + input_token_buffer->length, + mech); + if (ret) { + *minor_status = 0; + return ret; + } + + out_data->length = input_token_buffer->length - + (p - (u_char *)input_token_buffer->value); + out_data->data = p; + return GSS_S_COMPLETE; +} + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +_gsskrb5_decapsulate(OM_uint32 *minor_status, + gss_buffer_t input_token_buffer, + krb5_data *out_data, + const void *type, + gss_OID oid) +{ + u_char *p; + OM_uint32 ret; + + p = input_token_buffer->value; + ret = _gsskrb5_verify_header(&p, + input_token_buffer->length, + type, + oid); + if (ret) { + *minor_status = 0; + return ret; + } + + out_data->length = input_token_buffer->length - + (p - (u_char *)input_token_buffer->value); + out_data->data = p; + return GSS_S_COMPLETE; +} + +/* + * Verify padding of a gss wrapped message and return its length. + */ + +OM_uint32 +_gssapi_verify_pad(gss_buffer_t wrapped_token, + size_t datalen, + size_t *padlen) +{ + u_char *pad; + size_t padlength; + int i; + + if (wrapped_token->length < 1) + return GSS_S_BAD_MECH; + + pad = (u_char *)wrapped_token->value + wrapped_token->length; + padlength = pad[-1]; + + if (padlength > datalen) + return GSS_S_BAD_MECH; + + for (i = padlength; i > 0 && *--pad == padlength; i--) + ; + if (i != 0) + return GSS_S_BAD_MIC; + + *padlen = padlength; + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/delete_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/delete_sec_context.c new file mode 100644 index 0000000..a480079 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/delete_sec_context.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_delete_sec_context(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token) +{ + krb5_context context; + gsskrb5_ctx ctx; + + GSSAPI_KRB5_INIT (&context); + + *minor_status = 0; + + if (output_token) { + output_token->length = 0; + output_token->value = NULL; + } + + if (*context_handle == GSS_C_NO_CONTEXT) + return GSS_S_COMPLETE; + + ctx = (gsskrb5_ctx) *context_handle; + *context_handle = GSS_C_NO_CONTEXT; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + krb5_auth_con_free (context, ctx->auth_context); + krb5_auth_con_free (context, ctx->deleg_auth_context); + if (ctx->kcred) + krb5_free_creds(context, ctx->kcred); + if(ctx->source) + krb5_free_principal (context, ctx->source); + if(ctx->target) + krb5_free_principal (context, ctx->target); + if (ctx->ticket) + krb5_free_ticket (context, ctx->ticket); + if(ctx->order) + _gssapi_msg_order_destroy(&ctx->order); + if (ctx->service_keyblock) + krb5_free_keyblock (context, ctx->service_keyblock); + krb5_data_free(&ctx->fwd_data); + if (ctx->crypto) + krb5_crypto_destroy(context, ctx->crypto); + if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE)) + krb5_cc_close(context, ctx->ccache); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + memset(ctx, 0, sizeof(*ctx)); + free (ctx); + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/display_name.c b/third_party/heimdal/lib/gssapi/krb5/display_name.c new file mode 100644 index 0000000..67cb61e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/display_name.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_display_name + (OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + krb5_context context; + krb5_const_principal name = (krb5_const_principal)input_name; + krb5_error_code kret; + char *buf; + size_t len; + + GSSAPI_KRB5_INIT (&context); + + kret = krb5_unparse_name_flags (context, name, + KRB5_PRINCIPAL_UNPARSE_DISPLAY, &buf); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + len = strlen (buf); + output_name_buffer->length = len; + output_name_buffer->value = malloc(len + 1); + if (output_name_buffer->value == NULL) { + free (buf); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (output_name_buffer->value, buf, len); + ((char *)output_name_buffer->value)[len] = '\0'; + free (buf); + if (output_name_type) + *output_name_type = GSS_KRB5_NT_PRINCIPAL_NAME; + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/display_status.c b/third_party/heimdal/lib/gssapi/krb5/display_status.c new file mode 100644 index 0000000..cca5f67 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/display_status.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 1998 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static const char * +calling_error(OM_uint32 v) +{ + static const char *msgs[] = { + NULL, /* 0 */ + "A required input parameter could not be read.", /* */ + "A required output parameter could not be written.", /* */ + "A parameter was malformed" + }; + + v >>= GSS_C_CALLING_ERROR_OFFSET; + + if (v == 0) + return ""; + else if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown calling error"; + else + return msgs[v]; +} + +static const char * +routine_error(OM_uint32 v) +{ + static const char *msgs[] = { + NULL, /* 0 */ + "An unsupported mechanism was requested", + "An invalid name was supplied", + "A supplied name was of an unsupported type", + "Incorrect channel bindings were supplied", + "An invalid status code was supplied", + "A token had an invalid MIC", + "No credentials were supplied, or the credentials were unavailable or inaccessible.", + "No context has been established", + "A token was invalid", + "A credential was invalid", + "The referenced credentials have expired", + "The context has expired", + "Miscellaneous failure (see text)", + "The quality-of-protection requested could not be provide", + "The operation is forbidden by local security policy", + "The operation or option is not available", + "The requested credential element already exists", + "The provided name was not a mechanism name.", + }; + + v >>= GSS_C_ROUTINE_ERROR_OFFSET; + + if (v == 0) + return ""; + else if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + +static const char * +supplementary_error(OM_uint32 v) +{ + static const char *msgs[] = { + "normal completion", + "continuation call to routine required", + "duplicate per-message token detected", + "timed-out per-message token detected", + "reordered (early) per-message token detected", + "skipped predecessor token(s) detected" + }; + + v >>= GSS_C_SUPPLEMENTARY_OFFSET; + + if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + +void +_gsskrb5_clear_status (void) +{ + krb5_context context; + + if (_gsskrb5_init (&context) != 0) + return; + krb5_clear_error_message(context); +} + +void +_gsskrb5_set_status (int ret, const char *fmt, ...) +{ + krb5_context context; + va_list args; + char *str; + int e; + + if (_gsskrb5_init (&context) != 0) + return; + + va_start(args, fmt); + e = vasprintf(&str, fmt, args); + va_end(args); + if (e >= 0 && str) { + krb5_set_error_message(context, ret, "%s", str); + free(str); + } +} + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_display_status +(OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + krb5_context context; + char *buf = NULL; + int e = 0; + + GSSAPI_KRB5_INIT (&context); + + status_string->length = 0; + status_string->value = NULL; + + if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && + gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) { + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + if (status_type == GSS_C_GSS_CODE) { + if (GSS_SUPPLEMENTARY_INFO(status_value)) + e = asprintf(&buf, "%s", + supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value))); + else + e = asprintf (&buf, "%s %s", + calling_error(GSS_CALLING_ERROR(status_value)), + routine_error(GSS_ROUTINE_ERROR(status_value))); + } else if (status_type == GSS_C_MECH_CODE) { + const char *buf2 = krb5_get_error_message(context, status_value); + if (buf2) { + buf = strdup(buf2); + krb5_free_error_message(context, buf2); + } else { + e = asprintf(&buf, "unknown mech error-code %u", + (unsigned)status_value); + } + } else { + *minor_status = EINVAL; + return GSS_S_BAD_STATUS; + } + + if (e < 0 || buf == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *message_context = 0; + *minor_status = 0; + + status_string->length = strlen(buf); + status_string->value = buf; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c b/third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c new file mode 100644 index 0000000..f5b34c5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_duplicate_cred ( + OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_id_t *output_cred_handle) +{ + krb5_context context; + gsskrb5_cred cred, dup; + OM_uint32 major, junk; + + dup = NULL; + + if (output_cred_handle == NULL) { + *minor_status = EINVAL; + return GSS_S_CALL_INACCESSIBLE_WRITE; + } + + GSSAPI_KRB5_INIT (&context); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + /* Duplicate the default credential */ + return _gsskrb5_acquire_cred_from(minor_status, GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_BOTH, + GSS_C_NO_CRED_STORE, + output_cred_handle, + NULL, NULL); + } + + /* Duplicate the input credential */ + + dup = calloc(1, sizeof(*dup)); + if (dup == NULL) { + *minor_status = krb5_enomem(context); + return (GSS_S_FAILURE); + } + + *output_cred_handle = (gss_cred_id_t)dup; /* making sure to release on error */ + + cred = (gsskrb5_cred)input_cred_handle; + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + dup->destination_realm = NULL; + if (cred->destination_realm && + (dup->destination_realm = strdup(cred->destination_realm)) == NULL) { + *minor_status = krb5_enomem(context); + free(dup); + return (GSS_S_FAILURE); + } + dup->usage = cred->usage; + dup->endtime = cred->endtime; + dup->principal = NULL; + dup->keytab = NULL; + dup->ccache = NULL; + dup->mechanisms = NULL; + + major = GSS_S_FAILURE; + + HEIMDAL_MUTEX_init(&dup->cred_id_mutex); + *minor_status = krb5_copy_principal(context, cred->principal, + &dup->principal); + if (*minor_status) + goto fail; + + if (cred->keytab) { + char *name = NULL; + + *minor_status = krb5_kt_get_full_name(context, cred->keytab, &name); + if (*minor_status) + goto fail; + *minor_status = krb5_kt_resolve(context, name, &dup->keytab); + krb5_xfree(name); + if (*minor_status) + goto fail; + } + + if (cred->ccache) { + const char *type, *name; + char *type_name = NULL; + + type = krb5_cc_get_type(context, cred->ccache); /* can't fail */ + if (strcmp(type, "MEMORY") == 0) { + *minor_status = krb5_cc_new_unique(context, type, NULL, + &dup->ccache); + if (*minor_status) + goto fail; + + *minor_status = krb5_cc_copy_cache(context, cred->ccache, + dup->ccache); + if (*minor_status) + goto fail; + + } else { + name = krb5_cc_get_name(context, cred->ccache); + if (name == NULL) { + *minor_status = ENOMEM; + goto fail; + } + + if (asprintf(&type_name, "%s:%s", type, name) == -1 || + type_name == NULL) { + *minor_status = ENOMEM; + goto fail; + } + + *minor_status = krb5_cc_resolve(context, type_name, + &dup->ccache); + free(type_name); + if (*minor_status) + goto fail; + } + } + + major = gss_create_empty_oid_set(minor_status, &dup->mechanisms); + if (major != GSS_S_COMPLETE) + goto fail; + + major = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &dup->mechanisms); + if (major != GSS_S_COMPLETE) + goto fail; + + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *output_cred_handle = (gss_cred_id_t)dup; + *minor_status = 0; + return major; + +fail: + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *output_cred_handle = (gss_cred_id_t)dup; + _gsskrb5_release_cred(&junk, output_cred_handle); + return major; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/duplicate_name.c b/third_party/heimdal/lib/gssapi/krb5/duplicate_name.c new file mode 100644 index 0000000..43519d6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/duplicate_name.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_duplicate_name ( + OM_uint32 * minor_status, + gss_const_name_t src_name, + gss_name_t * dest_name + ) +{ + krb5_const_principal src = (krb5_const_principal)src_name; + krb5_context context; + krb5_principal dest; + krb5_error_code kret; + + GSSAPI_KRB5_INIT (&context); + + kret = krb5_copy_principal (context, src, &dest); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } else { + *dest_name = (gss_name_t)dest; + *minor_status = 0; + return GSS_S_COMPLETE; + } +} diff --git a/third_party/heimdal/lib/gssapi/krb5/encapsulate.c b/third_party/heimdal/lib/gssapi/krb5/encapsulate.c new file mode 100644 index 0000000..3b390ce --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/encapsulate.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +void +_gssapi_encap_length (size_t data_len, + size_t *len, + size_t *total_len, + const gss_OID mech) +{ + size_t len_len; + + *len = 1 + 1 + mech->length + data_len; + + len_len = der_length_len(*len); + + *total_len = 1 + len_len + *len; +} + +void +_gsskrb5_encap_length (size_t data_len, + size_t *len, + size_t *total_len, + const gss_OID mech) +{ + _gssapi_encap_length(data_len + 2, len, total_len, mech); +} + +void * +_gssapi_make_mech_header(void *ptr, + size_t len, + const gss_OID mech) +{ + u_char *p = ptr; + int e; + size_t len_len, foo; + + *p++ = 0x60; + len_len = der_length_len(len); + e = der_put_length (p + len_len - 1, len_len, len, &foo); + if(e || foo != len_len) + abort (); + p += len_len; + *p++ = 0x06; + *p++ = mech->length; + memcpy (p, mech->elements, mech->length); + p += mech->length; + return p; +} + +void * +_gsskrb5_make_header (void *ptr, + size_t len, + const void *type, + const gss_OID mech) +{ + u_char *p = ptr; + p = _gssapi_make_mech_header(p, len, mech); + memcpy (p, type, 2); + p += 2; + return p; +} + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings. + */ + +OM_uint32 +_gssapi_encapsulate( + OM_uint32 *minor_status, + const krb5_data *in_data, + gss_buffer_t output_token, + const gss_OID mech +) +{ + size_t len, outer_len; + void *p; + + _gssapi_encap_length (in_data->length, &len, &outer_len, mech); + + output_token->length = outer_len; + output_token->value = malloc (outer_len); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gssapi_make_mech_header (output_token->value, len, mech); + memcpy (p, in_data->data, in_data->length); + return GSS_S_COMPLETE; +} + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API krb5 + * wrappings. + */ + +OM_uint32 +_gsskrb5_encapsulate( + OM_uint32 *minor_status, + const krb5_data *in_data, + gss_buffer_t output_token, + const void *type, + const gss_OID mech +) +{ + size_t len, outer_len; + u_char *p; + + _gsskrb5_encap_length (in_data->length, &len, &outer_len, mech); + + output_token->length = outer_len; + output_token->value = malloc (outer_len); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header (output_token->value, len, type, mech); + memcpy (p, in_data->data, in_data->length); + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/export_name.c b/third_party/heimdal/lib/gssapi/krb5/export_name.c new file mode 100644 index 0000000..1686a65 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/export_name.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997, 1999, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_export_name + (OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_buffer_t exported_name + ) +{ + krb5_context context; + krb5_const_principal princ = (krb5_const_principal)input_name; + krb5_error_code kret; + char *buf, *name; + size_t len; + + GSSAPI_KRB5_INIT (&context); + + kret = krb5_unparse_name (context, princ, &name); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + len = strlen (name); + + exported_name->length = 10 + len + GSS_KRB5_MECHANISM->length; + exported_name->value = malloc(exported_name->length); + if (exported_name->value == NULL) { + free (name); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + buf = exported_name->value; + memcpy(buf, "\x04\x01", 2); + buf += 2; + buf[0] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; + buf[1] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; + buf+= 2; + buf[0] = 0x06; + buf[1] = (GSS_KRB5_MECHANISM->length) & 0xFF; + buf+= 2; + + memcpy(buf, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + buf += GSS_KRB5_MECHANISM->length; + + buf[0] = (len >> 24) & 0xff; + buf[1] = (len >> 16) & 0xff; + buf[2] = (len >> 8) & 0xff; + buf[3] = (len) & 0xff; + buf += 4; + + memcpy (buf, name, len); + + free (name); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c new file mode 100644 index 0000000..c298415 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_export_sec_context( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token + ) +{ + krb5_context context; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle; + krb5_storage *sp; + krb5_auth_context ac; + OM_uint32 ret = GSS_S_COMPLETE; + krb5_data data; + int flags; + OM_uint32 minor; + krb5_error_code kret; + + GSSAPI_KRB5_INIT (&context); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (!(ctx->flags & GSS_C_TRANS_FLAG)) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = 0; + return GSS_S_UNAVAILABLE; + } + + sp = krb5_storage_emem (); + if (sp == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ac = ctx->auth_context; + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_PACKED); + krb5_storage_set_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE); + + /* flagging included fields */ + + flags = 0; + if (ac->local_address) + flags |= SC_LOCAL_ADDRESS; + if (ac->remote_address) + flags |= SC_REMOTE_ADDRESS; + if (ac->keyblock) + flags |= SC_KEYBLOCK; + if (ac->local_subkey) + flags |= SC_LOCAL_SUBKEY; + if (ac->remote_subkey) + flags |= SC_REMOTE_SUBKEY; + if (ac->authenticator) + flags |= SC_AUTHENTICATOR; + if (ctx->source) + flags |= SC_SOURCE_NAME; + if (ctx->target) + flags |= SC_TARGET_NAME; + if (ctx->order) + flags |= SC_ORDER; + + kret = krb5_store_int32 (sp, flags); + if (kret) { + *minor_status = kret; + goto failure; + } + + /* marshall auth context */ + + kret = krb5_store_int32 (sp, ac->flags); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ac->local_address) { + kret = krb5_store_address (sp, *ac->local_address); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->remote_address) { + kret = krb5_store_address (sp, *ac->remote_address); + if (kret) { + *minor_status = kret; + goto failure; + } + } + kret = krb5_store_int16 (sp, ac->local_port); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int16 (sp, ac->remote_port); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ac->keyblock) { + kret = krb5_store_keyblock (sp, *ac->keyblock); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->local_subkey) { + kret = krb5_store_keyblock (sp, *ac->local_subkey); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->remote_subkey) { + kret = krb5_store_keyblock (sp, *ac->remote_subkey); + if (kret) { + *minor_status = kret; + goto failure; + } + } + kret = krb5_store_int32 (sp, ac->local_seqnumber); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ac->remote_seqnumber); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ac->authenticator) { + kret = krb5_store_int64(sp, ac->authenticator->ctime); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32(sp, ac->authenticator->cusec); + if (kret) { + *minor_status = kret; + goto failure; + } + } + + kret = krb5_store_int32 (sp, ac->keytype); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ac->cksumtype); + if (kret) { + *minor_status = kret; + goto failure; + } + + /* names */ + if (ctx->source) { + kret = krb5_store_principal(sp, ctx->source); + if (kret) { + *minor_status = kret; + goto failure; + } + } + + if (ctx->target) { + kret = krb5_store_principal(sp, ctx->target); + if (kret) { + *minor_status = kret; + goto failure; + } + } + + kret = krb5_store_int32 (sp, ctx->flags); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ctx->more_flags); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ctx->state); + if (kret) { + *minor_status = kret; + goto failure; + } + /* + * XXX We should put a 64-bit int here, but we don't have a + * krb5_store_int64() yet. + */ + kret = krb5_store_int32 (sp, ctx->endtime); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ctx->order) { + kret = _gssapi_msg_order_export(sp, ctx->order); + if (kret) { + *minor_status = kret; + goto failure; + } + } + + kret = krb5_storage_to_data (sp, &data); + krb5_storage_free (sp); + if (kret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = kret; + return GSS_S_FAILURE; + } + interprocess_token->length = data.length; + interprocess_token->value = data.data; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + ret = _gsskrb5_delete_sec_context (minor_status, context_handle, + GSS_C_NO_BUFFER); + if (ret != GSS_S_COMPLETE) + _gss_secure_release_buffer (&minor, interprocess_token); + *minor_status = 0; + return ret; + failure: + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + krb5_storage_free (sp); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/external.c b/third_party/heimdal/lib/gssapi/krb5/external.c new file mode 100644 index 0000000..e58df18 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/external.c @@ -0,0 +1,413 @@ +/* + * Copyright (c) 1997 - 2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" +#include <gssapi_mech.h> + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_user_name_oid_desc = + {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x01")}; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_machine_uid_name_oid_desc = + {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x02")}; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_string_uid_name_oid_desc = + {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x03")}; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)). The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc. This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_hostbased_service_x_oid_desc = + {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x02")}; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x04"}, corresponding to an + * object-identifier value of {iso(1) member-body(2) + * Unites States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized + * to point to that gss_OID_desc. + */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_hostbased_service_oid_desc = + {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x04")}; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_anonymous_oid_desc = + {6, rk_UNCONST("\x2b\x06\01\x05\x06\x03")}; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_export_name_oid_desc = + {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x04") }; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_name(1)}. The recommended symbolic name for this type + * is "GSS_KRB5_NT_PRINCIPAL_NAME". + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_nt_principal_name_oid_desc = + {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01") }; + +/* + * GSS_C_NT_COMPOSITE_EXPORT [RFC6680], OID {iso(1) identified-organization(3) + * dod(6) internet(1) security(5) nametypes(6) gss-composite-export(6)}. + */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_composite_export_oid_desc = + {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x06")}; + +/* + * draft-ietf-cat-iakerb-09, IAKERB: + * The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance + * with the mechanism proposed by SPNEGO [7] for negotiating protocol + * variations, is: {iso(1) org(3) dod(6) internet(1) security(5) + * mechanisms(5) iakerb(10) iakerbProxyProtocol(1)}. The proposed + * mechanism ID for IAKERB minimum messages GSS-API Kerberos, in + * accordance with the mechanism proposed by SPNEGO for negotiating + * protocol variations, is: {iso(1) org(3) dod(6) internet(1) + * security(5) mechanisms(5) iakerb(10) + * iakerbMinimumMessagesProtocol(2)}. + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_iakerb_proxy_mechanism_oid_desc = + {7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x01")}; + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_iakerb_min_msg_mechanism_oid_desc = + {7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x02") }; + +/* + * Context for krb5 calls. + */ + +static gss_mo_desc krb5_mo[] = { + { + GSS_C_MA_SASL_MECH_NAME, + GSS_MO_MA, + "SASL mech name", + rk_UNCONST("GS2-KRB5"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_NAME, + GSS_MO_MA, + "Mechanism name", + rk_UNCONST("KRB5"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_DESCRIPTION, + GSS_MO_MA, + "Mechanism description", + rk_UNCONST("Heimdal Kerberos 5 mech"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_CONCRETE, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_ITOK_FRAMED, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_AUTH_INIT, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_AUTH_TARG, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_DELEG_CRED, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_INTEG_PROT, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_CONF_PROT, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_MIC, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_WRAP, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_PROT_READY, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_REPLAY_DET, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_OOS_DET, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_CBINDINGS, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_PFS, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_CTX_TRANS, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + } +}; + +/* + * + */ + +static gssapi_mech_interface_desc krb5_mech = { + GMI_VERSION, + "krb5", + {9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }, + 0, + NULL, /* gm_acquire_cred */ + _gsskrb5_release_cred, + _gsskrb5_init_sec_context, + _gsskrb5_accept_sec_context, + _gsskrb5_process_context_token, + _gsskrb5_delete_sec_context, + _gsskrb5_context_time, + _gsskrb5_get_mic, + _gsskrb5_verify_mic, + _gsskrb5_wrap, + _gsskrb5_unwrap, + _gsskrb5_display_status, + _gsskrb5_indicate_mechs, + _gsskrb5_compare_name, + _gsskrb5_display_name, + _gsskrb5_import_name, + _gsskrb5_export_name, + _gsskrb5_release_name, + _gsskrb5_inquire_cred, + _gsskrb5_inquire_context, + _gsskrb5_wrap_size_limit, + NULL, /* gm_add_cred */ + _gsskrb5_inquire_cred_by_mech, + _gsskrb5_export_sec_context, + _gsskrb5_import_sec_context, + _gsskrb5_inquire_names_for_mech, + _gsskrb5_inquire_mechs_for_name, + _gsskrb5_canonicalize_name, + _gsskrb5_duplicate_name, + _gsskrb5_inquire_sec_context_by_oid, + _gsskrb5_inquire_cred_by_oid, + _gsskrb5_set_sec_context_option, + _gsskrb5_set_cred_option, + _gsskrb5_pseudo_random, + _gk_wrap_iov, + _gk_unwrap_iov, + _gk_wrap_iov_length, + NULL, /* gm_store_cred */ + _gsskrb5_export_cred, + _gsskrb5_import_cred, + _gsskrb5_acquire_cred_from, + NULL, /* gm_acquire_cred_impersonate_name */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + krb5_mo, + sizeof(krb5_mo) / sizeof(krb5_mo[0]), + _gsskrb5_localname, + _gsskrb5_authorize_localname, + _gsskrb5_display_name_ext, + _gsskrb5_inquire_name, + _gsskrb5_get_name_attribute, + _gsskrb5_set_name_attribute, + _gsskrb5_delete_name_attribute, + _gsskrb5_export_name_composite, + _gsskrb5_duplicate_cred, + _gsskrb5_add_cred_from, + _gsskrb5_store_cred_into, + NULL, /* gm_query_mechanism_info */ + NULL, /* gm_query_meta_data */ + NULL, /* gm_exchange_meta_data */ + _gsskrb5_store_cred_into2, + NULL /* gm_compat */ +}; + +gssapi_mech_interface +__gss_krb5_initialize(void) +{ + return &krb5_mech; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/get_mic.c b/third_party/heimdal/lib/gssapi/krb5/get_mic.c new file mode 100644 index 0000000..d9cf9d7 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/get_mic.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +#ifdef HEIM_WEAK_CRYPTO + +static OM_uint32 +mic_des + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key + ) +{ + u_char *p; + EVP_MD_CTX *md5; + u_char hash[16]; + DES_key_schedule schedule; + EVP_CIPHER_CTX des_ctx; + DES_cblock deskey; + DES_cblock zero; + int32_t seq_number; + size_t len, total_len; + + _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); + + message_token->length = total_len; + message_token->value = malloc (total_len); + if (message_token->value == NULL) { + message_token->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(message_token->value, + len, + "\x01\x01", /* TOK_ID */ + GSS_KRB5_MECHANISM); + + memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ + p += 2; + + memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ + p += 4; + + /* Fill in later (SND-SEQ) */ + memset (p, 0, 16); + p += 16; + + /* checksum */ + md5 = EVP_MD_CTX_create(); + EVP_DigestInit_ex(md5, EVP_md5(), NULL); + EVP_DigestUpdate(md5, p - 24, 8); + EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length); + EVP_DigestFinal_ex(md5, hash, NULL); + EVP_MD_CTX_destroy(md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + DES_set_key_unchecked (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + memcpy (p - 8, hash, 8); /* SGN_CKSUM */ + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + /* sequence number */ + krb5_auth_con_getlocalseqnumber (context, + ctx->auth_context, + &seq_number); + + p -= 16; /* SND_SEQ */ + p[0] = (seq_number >> 0) & 0xFF; + p[1] = (seq_number >> 8) & 0xFF; + p[2] = (seq_number >> 16) & 0xFF; + p[3] = (seq_number >> 24) & 0xFF; + memset (p + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + EVP_CIPHER_CTX_init(&des_ctx); + EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); + EVP_Cipher(&des_ctx, p, p, 8); + EVP_CIPHER_CTX_cleanup(&des_ctx); + + krb5_auth_con_setlocalseqnumber (context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + memset_s(deskey, sizeof(deskey), 0, sizeof(deskey)); + memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); + + *minor_status = 0; + return GSS_S_COMPLETE; +} +#endif + +static OM_uint32 +mic_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key + ) +{ + u_char *p; + Checksum cksum; + u_char seq[8]; + + int32_t seq_number; + size_t len, total_len; + + krb5_crypto crypto; + krb5_error_code kret; + krb5_data encdata; + char *tmp; + char ivec[8]; + + _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); + + message_token->length = total_len; + message_token->value = malloc (total_len); + if (message_token->value == NULL) { + message_token->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(message_token->value, + len, + "\x01\x01", /* TOK-ID */ + GSS_KRB5_MECHANISM); + + memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ + p += 2; + + memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ + p += 4; + + /* this should be done in parts */ + + tmp = malloc (message_buffer->length + 8); + if (tmp == NULL) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, p - 8, 8); + memcpy (tmp + 8, message_buffer->value, message_buffer->length); + + kret = krb5_crypto_init(context, key, 0, &crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + free (tmp); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_create_checksum (context, + crypto, + KRB5_KU_USAGE_SIGN, + 0, + tmp, + message_buffer->length + 8, + &cksum); + free (tmp); + krb5_crypto_destroy (context, crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + *minor_status = kret; + return GSS_S_FAILURE; + } + + memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + /* sequence number */ + krb5_auth_con_getlocalseqnumber (context, + ctx->auth_context, + &seq_number); + + seq[0] = (seq_number >> 0) & 0xFF; + seq[1] = (seq_number >> 8) & 0xFF; + seq[2] = (seq_number >> 16) & 0xFF; + seq[3] = (seq_number >> 24) & 0xFF; + memset (seq + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + kret = krb5_crypto_init(context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (ctx->more_flags & COMPAT_OLD_DES3) + memset(ivec, 0, 8); + else + memcpy(ivec, p + 8, 8); + + kret = krb5_encrypt_ivec (context, + crypto, + KRB5_KU_USAGE_SEQ, + seq, 8, &encdata, ivec); + krb5_crypto_destroy (context, crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + *minor_status = kret; + return GSS_S_FAILURE; + } + + assert (encdata.length == 8); + + memcpy (p, encdata.data, encdata.length); + krb5_data_free (&encdata); + + krb5_auth_con_setlocalseqnumber (context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + free_Checksum (&cksum); + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + krb5_context context; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + krb5_keyblock *key; + OM_uint32 ret; + + GSSAPI_KRB5_INIT (&context); + + if (ctx->more_flags & IS_CFX) + return _gssapi_mic_cfx (minor_status, ctx, context, qop_req, + message_buffer, message_token); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + switch (key->keytype) { + case KRB5_ENCTYPE_DES_CBC_CRC : + case KRB5_ENCTYPE_DES_CBC_MD4 : + case KRB5_ENCTYPE_DES_CBC_MD5 : +#ifdef HEIM_WEAK_CRYPTO + ret = mic_des (minor_status, ctx, context, qop_req, + message_buffer, message_token, key); +#else + ret = GSS_S_FAILURE; +#endif + break; + case KRB5_ENCTYPE_DES3_CBC_MD5 : + case KRB5_ENCTYPE_DES3_CBC_SHA1 : + ret = mic_des3 (minor_status, ctx, context, qop_req, + message_buffer, message_token, key); + break; + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: + ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req, + message_buffer, message_token, key); + break; + default : + abort(); + break; + } + krb5_free_keyblock (context, key); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/gkrb5_err.et b/third_party/heimdal/lib/gssapi/krb5/gkrb5_err.et new file mode 100644 index 0000000..109876e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/gkrb5_err.et @@ -0,0 +1,33 @@ +# +# extended gss krb5 error messages +# + +id "$Id$" + +error_table gk5 + +prefix GSS_KRB5_S + +error_code G_BAD_SERVICE_NAME, "No @ in SERVICE-NAME name string" +error_code G_BAD_STRING_UID, "STRING-UID-NAME contains nondigits" +error_code G_NOUSER, "UID does not resolve to username" +error_code G_VALIDATE_FAILED, "Validation error" +error_code G_BUFFER_ALLOC, "Couldn't allocate gss_buffer_t data" +error_code G_BAD_MSG_CTX, "Message context invalid" +error_code G_WRONG_SIZE, "Buffer is the wrong size" +error_code G_BAD_USAGE, "Credential usage type is unknown" +error_code G_UNKNOWN_QOP, "Unknown quality of protection specified" +error_code G_UNKNOWN_CRED_STORE_ELEMENT, "Credential store contained unknown elements" +error_code G_BAD_PASSWORD_CRED_STORE, "Credential store cannot contain both a password and a credentials cache or client keytab" + +index 128 + +error_code KG_CCACHE_NOMATCH, "Principal in credential cache does not match desired name" +error_code KG_KEYTAB_NOMATCH, "No principal in keytab matches desired name" +error_code KG_TGT_MISSING, "Credential cache has no TGT" +error_code KG_NO_SUBKEY, "Authenticator has no subkey" +error_code KG_CONTEXT_ESTABLISHED, "Context is already fully established" +error_code KG_BAD_SIGN_TYPE, "Unknown signature type in token" +error_code KG_BAD_LENGTH, "Invalid field length in token" +error_code KG_CTX_INCOMPLETE, "Attempt to use incomplete security context" +error_code KG_INPUT_TOO_LONG, "Input too long" diff --git a/third_party/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/third_party/heimdal/lib/gssapi/krb5/gsskrb5_locl.h new file mode 100644 index 0000000..fbbb168 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/gsskrb5_locl.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef GSSKRB5_LOCL_H +#define GSSKRB5_LOCL_H + +#include <config.h> + +#include <krb5_locl.h> +#include <gkrb5_err.h> +#include <gssapi.h> +#include <gssapi_mech.h> +#include <gssapi_krb5.h> +#include <assert.h> +#include <mech/utils.h> + +#include "cfx.h" + +/* + * + */ + +struct gss_msg_order; + +typedef struct gsskrb5_ctx { + struct krb5_auth_context_data *auth_context; + struct krb5_auth_context_data *deleg_auth_context; + krb5_principal source, target; + OM_uint32 flags; + enum { LOCAL = 1, OPEN = 2, + COMPAT_OLD_DES3 = 4, + COMPAT_OLD_DES3_SELECTED = 8, + ACCEPTOR_SUBKEY = 16, + RETRIED = 32, + CLOSE_CCACHE = 64, + IS_CFX = 128 + } more_flags; + enum gss_ctx_id_t_state { + /* initiator states */ + INITIATOR_START, + INITIATOR_RESTART, + INITIATOR_WAIT_FOR_MUTUAL, + INITIATOR_READY, + /* acceptor states */ + ACCEPTOR_START, + ACCEPTOR_WAIT_FOR_DCESTYLE, + ACCEPTOR_READY + } state; + krb5_creds *kcred; + krb5_ccache ccache; + struct krb5_ticket *ticket; + time_t endtime; + HEIMDAL_MUTEX ctx_id_mutex; + struct gss_msg_order *order; + krb5_keyblock *service_keyblock; + krb5_data fwd_data; + krb5_crypto crypto; +} *gsskrb5_ctx; + +static inline krb5_boolean +IS_DCE_STYLE(gsskrb5_ctx ctx) +{ + return (ctx->flags & GSS_C_DCE_STYLE) != 0; +} + +typedef struct { + krb5_principal principal; + char *destination_realm; /* Realm of acceptor service, if delegated */ + int cred_flags; +#define GSS_CF_DESTROY_CRED_ON_RELEASE 1 +#define GSS_CF_NO_CI_FLAGS 2 + struct krb5_keytab_data *keytab; + time_t endtime; + gss_cred_usage_t usage; + gss_OID_set mechanisms; + struct krb5_ccache_data *ccache; + HEIMDAL_MUTEX cred_id_mutex; + krb5_enctype *enctypes; +} *gsskrb5_cred; + +typedef struct Principal *gsskrb5_name; + +/* + * + */ + +extern krb5_keytab _gsskrb5_keytab; +extern HEIMDAL_MUTEX gssapi_keytab_mutex; + +/* + * Prototypes + */ + +#include "krb5/gsskrb5-private.h" + +#define GSSAPI_KRB5_INIT(ctx) do { \ + krb5_error_code kret_gss_init; \ + if((kret_gss_init = _gsskrb5_init (ctx)) != 0) { \ + *minor_status = kret_gss_init; \ + return GSS_S_FAILURE; \ + } \ +} while (0) + +/* sec_context flags */ + +#define SC_LOCAL_ADDRESS 0x0001 +#define SC_REMOTE_ADDRESS 0x0002 +#define SC_KEYBLOCK 0x0004 +#define SC_LOCAL_SUBKEY 0x0008 +#define SC_REMOTE_SUBKEY 0x0010 +#define SC_SOURCE_NAME 0x0020 +#define SC_TARGET_NAME 0x0040 +#define SC_ORDER 0x0080 +#define SC_AUTHENTICATOR 0x0100 + +struct gsskrb5_ccache_name_args { + const char *name; + const char *out_name; +}; + +#endif diff --git a/third_party/heimdal/lib/gssapi/krb5/import_name.c b/third_party/heimdal/lib/gssapi/krb5/import_name.c new file mode 100644 index 0000000..f4ee231 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/import_name.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static OM_uint32 +parse_krb5_name (OM_uint32 *minor_status, + krb5_context context, + const char *name, + gss_name_t *output_name) +{ + krb5_principal princ; + krb5_error_code kerr; + + kerr = krb5_parse_name (context, name, &princ); + + if (kerr == 0) { + *output_name = (gss_name_t)princ; + return GSS_S_COMPLETE; + } + *minor_status = kerr; + + if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) + return GSS_S_BAD_NAME; + + return GSS_S_FAILURE; +} + +static OM_uint32 +import_krb5_name (OM_uint32 *minor_status, + krb5_context context, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + OM_uint32 ret; + char *tmp; + + tmp = malloc (input_name_buffer->length + 1); + if (tmp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, + input_name_buffer->value, + input_name_buffer->length); + tmp[input_name_buffer->length] = '\0'; + + ret = parse_krb5_name(minor_status, context, tmp, output_name); + free(tmp); + + return ret; +} + +OM_uint32 +_gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context, + gss_const_name_t targetname, krb5_principal *out) +{ + krb5_const_principal p = (krb5_const_principal)targetname; + krb5_error_code ret; + char *hostname = NULL, *service; + int type; + const char *comp; + + *minor_status = 0; + + /* If its not a hostname */ + type = krb5_principal_get_type(context, p); + comp = krb5_principal_get_comp_string(context, p, 0); + if (type == KRB5_NT_SRV_HST || type == KRB5_NT_SRV_HST_NEEDS_CANON || + (type == KRB5_NT_UNKNOWN && comp != NULL && strcmp(comp, "host") == 0)) { + if (p->name.name_string.len == 0) + return GSS_S_BAD_NAME; + else if (p->name.name_string.len > 1) + hostname = p->name.name_string.val[1]; + + service = p->name.name_string.val[0]; + + ret = krb5_sname_to_principal(context, + hostname, + service, + KRB5_NT_SRV_HST, + out); + if (ret == 0) { + const char *in_realm = krb5_principal_get_realm(context, + p); + const char *out_realm = krb5_principal_get_realm(context, + *out); + + /* + * Avoid loss of information, check for the "referral + * realm" and set back what was specified. + */ + if (out_realm != NULL && out_realm[0] == '\0') { + ret = krb5_principal_set_realm(context, *out, in_realm); + } + } + } else { + ret = krb5_copy_principal(context, p, out); + } + + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + return 0; +} + + +static OM_uint32 +import_hostbased_name(OM_uint32 *minor_status, + krb5_context context, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + krb5_principal princ = NULL; + krb5_error_code kerr; + char *tmp, *p, *host = NULL; + + tmp = malloc (input_name_buffer->length + 1); + if (tmp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, + input_name_buffer->value, + input_name_buffer->length); + tmp[input_name_buffer->length] = '\0'; + + p = strchr (tmp, '@'); + if (p != NULL) { + *p = '\0'; + host = p + 1; + } + + kerr = krb5_make_principal(context, &princ, "", tmp, host, NULL); + free (tmp); + *minor_status = kerr; + if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) + return GSS_S_BAD_NAME; + else if (kerr) + return GSS_S_FAILURE; + + krb5_principal_set_type(context, princ, KRB5_NT_SRV_HST); + *output_name = (gss_name_t)princ; + + return 0; +} + +static OM_uint32 +import_export_name (OM_uint32 *minor_status, + krb5_context context, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + CompositePrincipal *composite; + unsigned char *p; + uint32_t length; + size_t sz; + OM_uint32 ret; + int is_composite; + char *name; + + if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length) + return GSS_S_BAD_NAME; + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + p = input_name_buffer->value; + + if (p[0] != 0x04 || + (p[1] != 0x01 && p[1] != 0x02) || + p[2] != 0x00 || + p[3] != GSS_KRB5_MECHANISM->length + 2 || + p[4] != 0x06 || + p[5] != GSS_KRB5_MECHANISM->length || + memcmp(&p[6], GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_NAME; + + is_composite = p[1] == 0x02; + + p += 6 + GSS_KRB5_MECHANISM->length; + + length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + p += 4; + + if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length) + return GSS_S_BAD_NAME; + + if (is_composite) { + if ((composite = calloc(1, sizeof(*composite))) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = decode_CompositePrincipal(p, length, composite, &sz); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + if (sz != length) { + free_CompositePrincipal(composite); + free(composite); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + *output_name = (void *)composite; + return GSS_S_COMPLETE; + } + + name = malloc(length + 1); + if (name == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(name, p, length); + name[length] = '\0'; + + ret = parse_krb5_name(minor_status, context, name, output_name); + free(name); + return ret; +} + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + krb5_context context; + + *minor_status = 0; + *output_name = GSS_C_NO_NAME; + + GSSAPI_KRB5_INIT (&context); + + if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE) || + gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE_X)) + return import_hostbased_name (minor_status, + context, + input_name_buffer, + output_name); + else if (input_name_type == GSS_C_NO_OID + || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME) + || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) + /* default printable syntax */ + return import_krb5_name (minor_status, + context, + input_name_buffer, + output_name); + else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME) || + gss_oid_equal(input_name_type, GSS_C_NT_COMPOSITE_EXPORT)) { + return import_export_name(minor_status, + context, + input_name_buffer, + output_name); + } else { + *minor_status = 0; + return GSS_S_BAD_NAMETYPE; + } +} diff --git a/third_party/heimdal/lib/gssapi/krb5/import_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/import_sec_context.c new file mode 100644 index 0000000..2255a71 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/import_sec_context.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t * context_handle + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_context context; + krb5_error_code kret; + krb5_storage *sp; + krb5_auth_context ac; + krb5_address local, remote; + krb5_address *localp, *remotep; + krb5_keyblock keyblock; + int32_t flags, tmp; + int64_t tmp64; + gsskrb5_ctx ctx; + + GSSAPI_KRB5_INIT (&context); + + *context_handle = GSS_C_NO_CONTEXT; + + localp = remotep = NULL; + + sp = krb5_storage_from_mem (interprocess_token->value, + interprocess_token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_PACKED); + krb5_storage_set_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE); + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + krb5_storage_free (sp); + return GSS_S_FAILURE; + } + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + kret = krb5_auth_con_init (context, + &ctx->auth_context); + if (kret) { + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + /* flags */ + + *minor_status = 0; + + if (krb5_ret_int32 (sp, &flags) != 0) + goto failure; + + /* retrieve the auth context */ + + ac = ctx->auth_context; + if (krb5_ret_int32 (sp, &tmp) != 0) + goto failure; + ac->flags = tmp; + if (flags & SC_LOCAL_ADDRESS) { + if (krb5_ret_address (sp, localp = &local) != 0) + goto failure; + } + + if (flags & SC_REMOTE_ADDRESS) { + if (krb5_ret_address (sp, remotep = &remote) != 0) + goto failure; + } + + krb5_auth_con_setaddrs (context, ac, localp, remotep); + if (localp) + krb5_free_address (context, localp); + if (remotep) + krb5_free_address (context, remotep); + localp = remotep = NULL; + + if (krb5_ret_int16 (sp, &ac->local_port) != 0) + goto failure; + + if (krb5_ret_int16 (sp, &ac->remote_port) != 0) + goto failure; + if (flags & SC_KEYBLOCK) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setkey (context, ac, &keyblock); + krb5_free_keyblock_contents (context, &keyblock); + } + if (flags & SC_LOCAL_SUBKEY) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setlocalsubkey (context, ac, &keyblock); + krb5_free_keyblock_contents (context, &keyblock); + } + if (flags & SC_REMOTE_SUBKEY) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setremotesubkey (context, ac, &keyblock); + krb5_free_keyblock_contents (context, &keyblock); + } + if (krb5_ret_uint32 (sp, &ac->local_seqnumber)) + goto failure; + if (krb5_ret_uint32 (sp, &ac->remote_seqnumber)) + goto failure; + + if (flags & SC_AUTHENTICATOR) { + if (krb5_ret_int64(sp, &tmp64)) + goto failure; + ac->authenticator->ctime = tmp64; + if (krb5_ret_int32(sp, &tmp)) + goto failure; + ac->authenticator->cusec = tmp; + } + + if (krb5_ret_int32 (sp, &tmp) != 0) + goto failure; + ac->keytype = tmp; + if (krb5_ret_int32 (sp, &tmp) != 0) + goto failure; + ac->cksumtype = tmp; + + /* names */ + if (flags & SC_SOURCE_NAME) { + if (krb5_ret_principal(sp, &ctx->source)) + goto failure; + } + + if (flags & SC_TARGET_NAME) { + if (krb5_ret_principal(sp, &ctx->target)) + goto failure; + } + + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->flags = tmp; + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->more_flags = tmp; + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->state = tmp; + /* + * XXX endtime should be a 64-bit int, but we don't have + * krb5_ret_int64() yet. + */ + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->endtime = tmp; + + if (flags & SC_ORDER) { + ret = _gssapi_msg_order_import(minor_status, sp, &ctx->order); + if (ret) + goto failure; + } + + krb5_storage_free (sp); + + _gsskrb5i_is_cfx(context, ctx, (ctx->more_flags & LOCAL) == 0); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; + +failure: + krb5_auth_con_free (context, + ctx->auth_context); + if (ctx->source != NULL) + krb5_free_principal(context, ctx->source); + if (ctx->target != NULL) + krb5_free_principal(context, ctx->target); + if (localp) + krb5_free_address (context, localp); + if (remotep) + krb5_free_address (context, remotep); + if(ctx->order) + _gssapi_msg_order_destroy(&ctx->order); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + krb5_storage_free (sp); + free (ctx); + *context_handle = GSS_C_NO_CONTEXT; + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/indicate_mechs.c b/third_party/heimdal/lib/gssapi/krb5/indicate_mechs.c new file mode 100644 index 0000000..6201378 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/indicate_mechs.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_indicate_mechs + (OM_uint32 * minor_status, + gss_OID_set * mech_set + ) +{ + OM_uint32 ret, junk; + + ret = gss_create_empty_oid_set(minor_status, mech_set); + if (ret) + return ret; + + ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, mech_set); + if (ret) { + gss_release_oid_set(&junk, mech_set); + return ret; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/init.c b/third_party/heimdal/lib/gssapi/krb5/init.c new file mode 100644 index 0000000..325b2c4 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/init.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1997 - 2001, 2003, 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static HEIMDAL_MUTEX context_mutex = HEIMDAL_MUTEX_INITIALIZER; +static int created_key; +static HEIMDAL_thread_key context_key; + +static void +destroy_context(void *ptr) +{ + krb5_context context = ptr; + + if (context == NULL) + return; + krb5_free_context(context); +} + +krb5_error_code +_gsskrb5_init (krb5_context *context) +{ + krb5_error_code ret = 0; + + HEIMDAL_MUTEX_lock(&context_mutex); + + if (!created_key) { + HEIMDAL_key_create(&context_key, destroy_context, ret); + if (ret) { + HEIMDAL_MUTEX_unlock(&context_mutex); + return ret; + } + created_key = 1; + } + HEIMDAL_MUTEX_unlock(&context_mutex); + + *context = HEIMDAL_getspecific(context_key); + if (*context == NULL) { + + ret = krb5_init_context(context); + if (ret == 0) { + krb5_add_et_list(*context, initialize_gk5_error_table_r); + HEIMDAL_setspecific(context_key, *context, ret); + if (ret) { + krb5_free_context(*context); + *context = NULL; + } + } + } + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c new file mode 100644 index 0000000..62b26ed --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -0,0 +1,1021 @@ +/* + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static OM_uint32 +gsskrb5_set_authorization_data(OM_uint32 *, + krb5_context, + krb5_auth_context, + gss_const_name_t); + +/* + * copy the addresses from `input_chan_bindings' (if any) to + * the auth context `ac' + */ + +static OM_uint32 +set_addresses (krb5_context context, + krb5_auth_context ac, + const gss_channel_bindings_t input_chan_bindings) +{ + /* Port numbers are expected to be in application_data.value, + * initator's port first */ + + krb5_address initiator_addr, acceptor_addr; + krb5_error_code kret; + + if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS + || input_chan_bindings->application_data.length != + 2 * sizeof(ac->local_port)) + return 0; + + memset(&initiator_addr, 0, sizeof(initiator_addr)); + memset(&acceptor_addr, 0, sizeof(acceptor_addr)); + + ac->local_port = + *(int16_t *) input_chan_bindings->application_data.value; + + ac->remote_port = + *((int16_t *) input_chan_bindings->application_data.value + 1); + + kret = _gsskrb5i_address_to_krb5addr(context, + input_chan_bindings->acceptor_addrtype, + &input_chan_bindings->acceptor_address, + ac->remote_port, + &acceptor_addr); + if (kret) + return kret; + + kret = _gsskrb5i_address_to_krb5addr(context, + input_chan_bindings->initiator_addrtype, + &input_chan_bindings->initiator_address, + ac->local_port, + &initiator_addr); + if (kret) { + krb5_free_address (context, &acceptor_addr); + return kret; + } + + kret = krb5_auth_con_setaddrs(context, + ac, + &initiator_addr, /* local address */ + &acceptor_addr); /* remote address */ + + krb5_free_address (context, &initiator_addr); + krb5_free_address (context, &acceptor_addr); + +#if 0 + free(input_chan_bindings->application_data.value); + input_chan_bindings->application_data.value = NULL; + input_chan_bindings->application_data.length = 0; +#endif + + return kret; +} + +OM_uint32 +_gsskrb5_create_ctx( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + krb5_context context, + const gss_channel_bindings_t input_chan_bindings, + enum gss_ctx_id_t_state state) +{ + krb5_error_code kret; + gsskrb5_ctx ctx; + + *context_handle = NULL; + + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ctx->auth_context = NULL; + ctx->deleg_auth_context = NULL; + ctx->source = NULL; + ctx->target = NULL; + ctx->kcred = NULL; + ctx->ccache = NULL; + ctx->state = state; + ctx->flags = 0; + ctx->more_flags = 0; + ctx->service_keyblock = NULL; + ctx->ticket = NULL; + krb5_data_zero(&ctx->fwd_data); + ctx->endtime = 0; + ctx->order = NULL; + ctx->crypto = NULL; + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + kret = krb5_auth_con_init (context, &ctx->auth_context); + if (kret) { + *minor_status = kret; + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + free(ctx); + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_init (context, &ctx->deleg_auth_context); + if (kret) { + *minor_status = kret; + krb5_auth_con_free(context, ctx->auth_context); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + free(ctx); + return GSS_S_FAILURE; + } + + kret = set_addresses(context, ctx->auth_context, input_chan_bindings); + if (kret) { + *minor_status = kret; + + krb5_auth_con_free(context, ctx->auth_context); + krb5_auth_con_free(context, ctx->deleg_auth_context); + + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + free(ctx); + return GSS_S_BAD_BINDINGS; + } + + kret = set_addresses(context, ctx->deleg_auth_context, input_chan_bindings); + if (kret) { + *minor_status = kret; + + krb5_auth_con_free(context, ctx->auth_context); + krb5_auth_con_free(context, ctx->deleg_auth_context); + + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + free(ctx); + return GSS_S_BAD_BINDINGS; + } + + /* + * We need a sequence number + */ + + krb5_auth_con_addflags(context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE | + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED, + NULL); + + /* + * We need a sequence number + */ + + krb5_auth_con_addflags(context, + ctx->deleg_auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE | + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED, + NULL); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + + +static OM_uint32 +gsskrb5_get_creds( + OM_uint32 * minor_status, + krb5_context context, + krb5_ccache ccache, + gsskrb5_ctx ctx, + gss_const_name_t target_name, + OM_uint32 time_req, + OM_uint32 * time_rec) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_creds this_cred; + OM_uint32 lifetime_rec; + + if (ctx->target) { + krb5_free_principal(context, ctx->target); + ctx->target = NULL; + } + if (ctx->kcred) { + krb5_free_creds(context, ctx->kcred); + ctx->kcred = NULL; + } + + ret = _gsskrb5_canon_name(minor_status, context, target_name, + &ctx->target); + if (ret) + return ret; + + memset(&this_cred, 0, sizeof(this_cred)); + this_cred.client = ctx->source; + this_cred.server = ctx->target; + + if (time_req && time_req != GSS_C_INDEFINITE) { + krb5_timestamp ts; + + krb5_timeofday (context, &ts); + this_cred.times.endtime = ts + time_req; + } else { + this_cred.times.endtime = 0; + } + + this_cred.session.keytype = KEYTYPE_NULL; + + kret = krb5_get_credentials(context, + 0, + ccache, + &this_cred, + &ctx->kcred); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + krb5_free_principal(context, ctx->target); + kret = krb5_copy_principal(context, ctx->kcred->server, &ctx->target); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + ctx->endtime = ctx->kcred->times.endtime; + + ret = _gsskrb5_lifetime_left(minor_status, context, + ctx->endtime, &lifetime_rec); + if (ret) return ret; + + if (lifetime_rec == 0) { + *minor_status = 0; + return GSS_S_CONTEXT_EXPIRED; + } + + if (time_rec) *time_rec = lifetime_rec; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +gsskrb5_initiator_ready( + OM_uint32 * minor_status, + gsskrb5_ctx ctx, + krb5_context context) +{ + OM_uint32 ret; + int32_t seq_number; + int is_cfx = 0; + OM_uint32 flags = ctx->flags; + + krb5_free_creds(context, ctx->kcred); + ctx->kcred = NULL; + + if (ctx->more_flags & CLOSE_CCACHE) + krb5_cc_close(context, ctx->ccache); + ctx->ccache = NULL; + + krb5_auth_con_getremoteseqnumber (context, ctx->auth_context, &seq_number); + + _gsskrb5i_is_cfx(context, ctx, 0); + is_cfx = (ctx->more_flags & IS_CFX); + + ret = _gssapi_msg_order_create(minor_status, + &ctx->order, + _gssapi_msg_order_f(flags), + seq_number, 0, is_cfx); + if (ret) return ret; + + ctx->state = INITIATOR_READY; + ctx->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +/* + * handle delegated creds in init-sec-context + */ + +static void +do_delegation (krb5_context context, + krb5_auth_context ac, + krb5_ccache ccache, + krb5_creds *cred, + krb5_data *fwd_data, + uint32_t flagmask, + uint32_t *flags) +{ + krb5_error_code kret; + krb5_principal client; + const char *host; + + krb5_data_zero (fwd_data); + + kret = krb5_cc_get_principal(context, ccache, &client); + if (kret) + goto out; + + /* We can't generally enforce server.name_type == KRB5_NT_SRV_HST */ + if (cred->server->name.name_string.len < 2) + goto out; + host = krb5_principal_get_comp_string(context, cred->server, 1); + +#define FWDABLE 1 + kret = krb5_fwd_tgt_creds(context, ac, host, client, cred->server, ccache, + FWDABLE, fwd_data); + + out: + if (kret) + *flags &= ~flagmask; + else + *flags |= flagmask; + + if (client) + krb5_free_principal(context, client); +} + +/* + * first stage of init-sec-context + */ + +static OM_uint32 +init_auth +(OM_uint32 * minor_status, + gsskrb5_cred cred, + gsskrb5_ctx ctx, + krb5_context context, + gss_const_name_t name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_error_code kret; + krb5_data fwd_data; + OM_uint32 lifetime_rec; + + krb5_data_zero(&fwd_data); + + *minor_status = 0; + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + if (cred == NULL) { + kret = krb5_cc_default (context, &ctx->ccache); + if (kret) { + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + ctx->more_flags |= CLOSE_CCACHE; + } else + ctx->ccache = cred->ccache; + + kret = krb5_cc_get_principal (context, ctx->ccache, &ctx->source); + if (kret) { + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + /* + * This is hideous glue for (NFS) clients that wants to limit the + * available enctypes to what it can support (encryption in + * kernel). + */ + if (cred && cred->enctypes) + krb5_set_default_in_tkt_etypes(context, cred->enctypes); + + ret = gsskrb5_get_creds(minor_status, context, ctx->ccache, + ctx, name, time_req, time_rec); + if (ret) + goto failure; + + ret = gsskrb5_set_authorization_data(minor_status, context, + ctx->auth_context, name); + if (ret) + goto failure; + + ctx->endtime = ctx->kcred->times.endtime; + + ret = _gss_DES3_get_mic_compat(minor_status, ctx, context); + if (ret) + goto failure; + + ret = _gsskrb5_lifetime_left(minor_status, + context, + ctx->endtime, + &lifetime_rec); + if (ret) + goto failure; + + if (lifetime_rec == 0) { + *minor_status = 0; + ret = GSS_S_CONTEXT_EXPIRED; + goto failure; + } + + krb5_auth_con_setkey(context, + ctx->auth_context, + &ctx->kcred->session); + + kret = krb5_auth_con_generatelocalsubkey(context, + ctx->auth_context, + &ctx->kcred->session); + if(kret) { + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + return GSS_S_COMPLETE; + +failure: + if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE)) + krb5_cc_close(context, ctx->ccache); + ctx->ccache = NULL; + + return ret; + +} + +static OM_uint32 +init_auth_restart +(OM_uint32 * minor_status, + gsskrb5_cred cred, + gsskrb5_ctx ctx, + krb5_context context, + OM_uint32 req_flags, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_error_code kret; + krb5_flags ap_options; + krb5_data outbuf; + uint32_t flags; + krb5_data authenticator; + Checksum cksum; + krb5_enctype enctype; + krb5_data fwd_data, timedata; + int32_t offset = 0, oldoffset = 0; + uint32_t flagmask; + + krb5_data_zero(&outbuf); + krb5_data_zero(&fwd_data); + + *minor_status = 0; + + /* + * Check if our configuration requires us to follow the KDC's + * guidance. If so, we transmogrify the GSS_C_DELEG_FLAG into + * the GSS_C_DELEG_POLICY_FLAG. + */ + if ((context->flags & KRB5_CTX_F_ENFORCE_OK_AS_DELEGATE) + && (req_flags & GSS_C_DELEG_FLAG)) { + req_flags &= ~GSS_C_DELEG_FLAG; + req_flags |= GSS_C_DELEG_POLICY_FLAG; + } + + /* + * If the credential doesn't have ok-as-delegate, check if there + * is a realm setting and use that. + */ + if (!ctx->kcred->flags.b.ok_as_delegate) { + krb5_data data; + + ret = krb5_cc_get_config(context, ctx->ccache, NULL, + "realm-config", &data); + if (ret == 0) { + /* XXX 1 is use ok-as-delegate */ + if (data.length < 1 || ((((unsigned char *)data.data)[0]) & 1) == 0) + req_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); + krb5_data_free(&data); + } + } + + flagmask = 0; + + /* if we used GSS_C_DELEG_POLICY_FLAG, trust KDC */ + if ((req_flags & GSS_C_DELEG_POLICY_FLAG) + && ctx->kcred->flags.b.ok_as_delegate) + flagmask |= GSS_C_DELEG_FLAG | GSS_C_DELEG_POLICY_FLAG; + /* if there still is a GSS_C_DELEG_FLAG, use that */ + if (req_flags & GSS_C_DELEG_FLAG) + flagmask |= GSS_C_DELEG_FLAG; + + + flags = 0; + ap_options = 0; + if (flagmask & GSS_C_DELEG_FLAG) { + do_delegation (context, + ctx->deleg_auth_context, + ctx->ccache, ctx->kcred, + &fwd_data, flagmask, &flags); + } + + if (req_flags & GSS_C_MUTUAL_FLAG) { + flags |= GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + + if (req_flags & GSS_C_REPLAY_FLAG) + flags |= GSS_C_REPLAY_FLAG; + if (req_flags & GSS_C_SEQUENCE_FLAG) + flags |= GSS_C_SEQUENCE_FLAG; +#if 0 + if (req_flags & GSS_C_ANON_FLAG) + ; /* XXX */ +#endif + if (req_flags & GSS_C_DCE_STYLE) { + /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */ + flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + if (req_flags & GSS_C_IDENTIFY_FLAG) + flags |= GSS_C_IDENTIFY_FLAG; + if (req_flags & GSS_C_EXTENDED_ERROR_FLAG) + flags |= GSS_C_EXTENDED_ERROR_FLAG; + + if (req_flags & GSS_C_CONF_FLAG) { + flags |= GSS_C_CONF_FLAG; + } + if (req_flags & GSS_C_INTEG_FLAG) { + flags |= GSS_C_INTEG_FLAG; + } + if (cred == NULL || !(cred->cred_flags & GSS_CF_NO_CI_FLAGS)) { + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + } + flags |= GSS_C_TRANS_FLAG; + + if (ret_flags) + *ret_flags = flags; + ctx->flags = flags; + ctx->more_flags |= LOCAL; + + ret = _gsskrb5_create_8003_checksum (minor_status, + input_chan_bindings, + flags, + &fwd_data, + &cksum); + krb5_data_free (&fwd_data); + if (ret) + goto failure; + + enctype = ctx->auth_context->keyblock->keytype; + + ret = krb5_cc_get_config(context, ctx->ccache, ctx->target, + "time-offset", &timedata); + if (ret == 0) { + if (timedata.length == 4) { + const u_char *p = timedata.data; + offset = ((uint32_t)p[0] << 24) + | ((uint32_t)p[1] << 16) + | ((uint32_t)p[2] << 8) + | ((uint32_t)p[3] << 0); + } + krb5_data_free(&timedata); + } + + if (offset) { + krb5_get_kdc_sec_offset (context, &oldoffset, NULL); + krb5_set_kdc_sec_offset (context, offset, -1); + } + + kret = _krb5_build_authenticator(context, + ctx->auth_context, + enctype, + ctx->kcred, + &cksum, + &authenticator, + KRB5_KU_AP_REQ_AUTH); + + if (kret) { + if (offset) + krb5_set_kdc_sec_offset (context, oldoffset, -1); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_build_ap_req (context, + enctype, + ctx->kcred, + ap_options, + authenticator, + &outbuf); + if (offset) + krb5_set_kdc_sec_offset (context, oldoffset, -1); + if (kret) { + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + if (flags & GSS_C_DCE_STYLE) { + output_token->value = outbuf.data; + output_token->length = outbuf.length; + } else { + ret = _gsskrb5_encapsulate (minor_status, &outbuf, output_token, + (u_char *)(intptr_t)"\x01\x00", + GSS_KRB5_MECHANISM); + krb5_data_free (&outbuf); + if (ret) + goto failure; + } + + free_Checksum(&cksum); + + if (flags & GSS_C_MUTUAL_FLAG) { + ctx->state = INITIATOR_WAIT_FOR_MUTUAL; + return GSS_S_CONTINUE_NEEDED; + } + + return gsskrb5_initiator_ready(minor_status, ctx, context); +failure: + if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE)) + krb5_cc_close(context, ctx->ccache); + ctx->ccache = NULL; + + return ret; +} + +static krb5_error_code +handle_error_packet(krb5_context context, + gsskrb5_ctx ctx, + krb5_data indata) +{ + krb5_error_code kret; + KRB_ERROR error; + + kret = krb5_rd_error(context, &indata, &error); + if (kret == 0) { + kret = krb5_error_from_rd_error(context, &error, NULL); + + /* save the time skrew for this host */ + if (kret == KRB5KRB_AP_ERR_SKEW) { + krb5_data timedata; + unsigned char p[4]; + int32_t t = error.stime - time(NULL); + + p[0] = (t >> 24) & 0xFF; + p[1] = (t >> 16) & 0xFF; + p[2] = (t >> 8) & 0xFF; + p[3] = (t >> 0) & 0xFF; + + timedata.data = p; + timedata.length = sizeof(p); + + krb5_cc_set_config(context, ctx->ccache, ctx->target, + "time-offset", &timedata); + + if ((ctx->more_flags & RETRIED) == 0) + ctx->state = INITIATOR_RESTART; + ctx->more_flags |= RETRIED; + } + free_KRB_ERROR (&error); + } + return kret; +} + + +static OM_uint32 +repl_mutual +(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + krb5_context context, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data indata; + krb5_ap_rep_enc_part *repl; + + output_token->length = 0; + output_token->value = NULL; + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + if (IS_DCE_STYLE(ctx)) { + /* There is no OID wrapping. */ + indata.length = input_token->length; + indata.data = input_token->value; + kret = krb5_rd_rep(context, + ctx->auth_context, + &indata, + &repl); + if (kret) { + ret = _gsskrb5_decapsulate(minor_status, + input_token, + &indata, + "\x03\x00", + GSS_KRB5_MECHANISM); + if (ret == GSS_S_COMPLETE) { + *minor_status = handle_error_packet(context, ctx, indata); + } else { + *minor_status = kret; + } + return GSS_S_FAILURE; + } + } else { + ret = _gsskrb5_decapsulate (minor_status, + input_token, + &indata, + "\x02\x00", + GSS_KRB5_MECHANISM); + if (ret == GSS_S_DEFECTIVE_TOKEN) { + /* check if there is an error token sent instead */ + ret = _gsskrb5_decapsulate (minor_status, + input_token, + &indata, + "\x03\x00", + GSS_KRB5_MECHANISM); + if (ret == GSS_S_COMPLETE) { + *minor_status = handle_error_packet(context, ctx, indata); + return GSS_S_FAILURE; + } + } + kret = krb5_rd_rep (context, + ctx->auth_context, + &indata, + &repl); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + krb5_free_ap_rep_enc_part (context, + repl); + + *minor_status = 0; + if (time_rec) + _gsskrb5_lifetime_left(minor_status, + context, + ctx->endtime, + time_rec); + if (ret_flags) + *ret_flags = ctx->flags; + + if (req_flags & GSS_C_DCE_STYLE) { + int32_t local_seq, remote_seq; + krb5_data outbuf; + + /* + * So DCE_STYLE is strange. The client echos the seq number + * that the server used in the server's mk_rep in its own + * mk_rep(). After when done, it resets to it's own seq number + * for the gss_wrap calls. + */ + + krb5_auth_con_getremoteseqnumber(context, ctx->auth_context, &remote_seq); + krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &local_seq); + krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, remote_seq); + + kret = krb5_mk_rep(context, ctx->auth_context, &outbuf); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + /* reset local seq number */ + krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, local_seq); + + output_token->length = outbuf.length; + output_token->value = outbuf.data; + } + + return gsskrb5_initiator_ready(minor_status, ctx, context); +} + +/* + * gss_init_sec_context + */ + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context +(OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + gss_ctx_id_t * context_handle, + gss_const_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + krb5_context context; + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; + gsskrb5_ctx ctx; + OM_uint32 ret; + + GSSAPI_KRB5_INIT (&context); + + output_token->length = 0; + output_token->value = NULL; + + if (context_handle == NULL) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + + if (target_name == GSS_C_NO_NAME) { + if (actual_mech_type) + *actual_mech_type = GSS_C_NO_OID; + *minor_status = 0; + return GSS_S_BAD_NAME; + } + + if (mech_type != GSS_C_NO_OID && + !gss_oid_equal(mech_type, GSS_KRB5_MECHANISM)) + return GSS_S_BAD_MECH; + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + OM_uint32 ret1; + + if (*context_handle != GSS_C_NO_CONTEXT) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + ret1 = _gsskrb5_create_ctx(minor_status, + context_handle, + context, + input_chan_bindings, + INITIATOR_START); + if (ret1) + return ret1; + } + + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + ctx = (gsskrb5_ctx) *context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + again: + switch (ctx->state) { + case INITIATOR_START: + ret = init_auth(minor_status, + cred, + ctx, + context, + target_name, + mech_type, + req_flags, + time_req, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + if (ret != GSS_S_COMPLETE) + break; + fallthrough; + case INITIATOR_RESTART: + ret = init_auth_restart(minor_status, + cred, + ctx, + context, + req_flags, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + break; + case INITIATOR_WAIT_FOR_MUTUAL: + ret = repl_mutual(minor_status, + ctx, + context, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + if (ctx->state == INITIATOR_RESTART) + goto again; + break; + case INITIATOR_READY: + /* + * If we get there, the caller have called + * gss_init_sec_context() one time too many. + */ + _gsskrb5_set_status(EINVAL, "init_sec_context " + "called one time too many"); + *minor_status = EINVAL; + ret = GSS_S_BAD_STATUS; + break; + default: + _gsskrb5_set_status(EINVAL, "init_sec_context " + "invalid state %d for client", + (int)ctx->state); + *minor_status = EINVAL; + ret = GSS_S_BAD_STATUS; + break; + } + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* destroy context in case of error */ + if (GSS_ERROR(ret)) { + OM_uint32 min2; + _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); + } + + return ret; + +} + +static OM_uint32 +gsskrb5_set_authorization_data(OM_uint32 *minor_status, + krb5_context context, + krb5_auth_context auth_context, + gss_const_name_t gn) +{ + const CompositePrincipal *name = (const void *)gn; + AuthorizationData *ad; + krb5_error_code kret = 0; + size_t i; + + if (name->nameattrs == NULL || name->nameattrs->want_ad == NULL) + return GSS_S_COMPLETE; + + ad = name->nameattrs->want_ad; + for (i = 0; kret == 0 && i < ad->len; i++) { + kret = krb5_auth_con_add_AuthorizationData(context, auth_context, + ad->val[0].ad_type, + &ad->val[0].ad_data); + } + + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_context.c b/third_party/heimdal/lib/gssapi/krb5/inquire_context.c new file mode 100644 index 0000000..e225c33 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/inquire_context.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_context ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + krb5_context context; + OM_uint32 ret; + gsskrb5_ctx ctx = (gsskrb5_ctx)context_handle; + gss_name_t name; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (targ_name) + *targ_name = GSS_C_NO_NAME; + + GSSAPI_KRB5_INIT (&context); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (src_name) { + name = (gss_name_t)ctx->source; + ret = _gsskrb5_duplicate_name (minor_status, name, src_name); + if (ret) + goto failed; + } + + if (targ_name) { + name = (gss_name_t)ctx->target; + ret = _gsskrb5_duplicate_name (minor_status, name, targ_name); + if (ret) + goto failed; + } + + if (lifetime_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + context, + ctx->endtime, + lifetime_rec); + if (ret) + goto failed; + } + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (ctx_flags) + *ctx_flags = ctx->flags; + + if (locally_initiated) + *locally_initiated = ctx->more_flags & LOCAL; + + if (open_context) + *open_context = ctx->more_flags & OPEN; + + *minor_status = 0; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_COMPLETE; + +failed: + if (src_name) + _gsskrb5_release_name(NULL, src_name); + if (targ_name) + _gsskrb5_release_name(NULL, targ_name); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_cred.c b/third_party/heimdal/lib/gssapi/krb5/inquire_cred.c new file mode 100644 index 0000000..b7b67f7 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/inquire_cred.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred +(OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + gss_name_t * output_name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ) +{ + krb5_context context; + gss_cred_id_t aqcred_init = GSS_C_NO_CREDENTIAL; + gss_cred_id_t aqcred_accept = GSS_C_NO_CREDENTIAL; + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; + gss_OID_set amechs = GSS_C_NO_OID_SET; + gss_OID_set imechs = GSS_C_NO_OID_SET; + OM_uint32 junk; + OM_uint32 aminor; + OM_uint32 ret; + OM_uint32 aret; + OM_uint32 alife = GSS_C_INDEFINITE; + OM_uint32 ilife = GSS_C_INDEFINITE; + + /* + * XXX This function is more complex than it has to be. It should call + * _gsskrb5_inquire_cred_by_mech() twice and merge the results in the + * cred_handle == GSS_C_NO_CREDENTIAL case, but since + * _gsskrb5_inquire_cred_by_mech() is implemented in terms of this + * function, first we must fix _gsskrb5_inquire_cred_by_mech(). + */ + + *minor_status = 0; + + if (output_name) + *output_name = GSS_C_NO_NAME; + if (cred_usage) + *cred_usage = GSS_C_BOTH; /* There's no NONE */ + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; + + GSSAPI_KRB5_INIT (&context); + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + /* + * From here to the end of this if we should refactor into a separate + * function. + */ + /* Get the info for the default ACCEPT credential */ + aret = _gsskrb5_acquire_cred_from(&aminor, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_ACCEPT, + GSS_C_NO_CRED_STORE, + &aqcred_accept, + NULL, + NULL); + if (aret == GSS_S_COMPLETE) { + aret = _gsskrb5_inquire_cred(&aminor, + aqcred_accept, + output_name, + &alife, + NULL, + &amechs); + (void) _gsskrb5_release_cred(&junk, &aqcred_accept); + if (aret == GSS_S_COMPLETE) { + output_name = NULL; /* Can't merge names; output only one */ + if (cred_usage) + *cred_usage = GSS_C_ACCEPT; + if (lifetime) + *lifetime = alife; + if (mechanisms) { + *mechanisms = amechs; + amechs = GSS_C_NO_OID_SET; + } + (void) gss_release_oid_set(&junk, &amechs); + } else if (aret != GSS_S_NO_CRED) { + *minor_status = aminor; + return aret; + } else { + alife = GSS_C_INDEFINITE; + } + } + + /* Get the info for the default INITIATE credential */ + ret = _gsskrb5_acquire_cred_from(minor_status, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_INITIATE, + GSS_C_NO_CRED_STORE, + &aqcred_init, + NULL, + NULL); + if (ret == GSS_S_COMPLETE) { + ret = _gsskrb5_inquire_cred(minor_status, + aqcred_init, + output_name, + &ilife, + NULL, + &imechs); + (void) _gsskrb5_release_cred(&junk, &aqcred_init); + if (ret == GSS_S_COMPLETE) { + /* + * Merge results for INITIATE with ACCEPT if we had ACCEPT and + * for those outputs that are desired. + */ + if (cred_usage) { + *cred_usage = (*cred_usage == GSS_C_ACCEPT) ? + GSS_C_BOTH : GSS_C_INITIATE; + } + if (lifetime) + *lifetime = min(alife, ilife); + if (mechanisms) { + /* + * This is just one mechanism (IAKERB and such would live + * elsewhere). imechs will be equal to amechs, though not + * ==. + */ + if (aret != GSS_S_COMPLETE) { + *mechanisms = imechs; + imechs = GSS_C_NO_OID_SET; + } + } + (void) gss_release_oid_set(&junk, &amechs); + } else if (ret != GSS_S_NO_CRED) { + *minor_status = aminor; + return aret; + } + } + + if (aret != GSS_S_COMPLETE && ret != GSS_S_COMPLETE) { + *minor_status = aminor; + return aret; + } + *minor_status = 0; /* Even though 0 is not specified to be special */ + return GSS_S_COMPLETE; + } + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + if (output_name != NULL) { + if (cred->principal != NULL) { + gss_name_t name = (gss_name_t)cred->principal; + ret = _gsskrb5_duplicate_name(minor_status, name, output_name); + if (ret) + goto out; + } else if (cred->usage == GSS_C_ACCEPT) { + /* + * Keytab case, princ may not be set (yet, ever, whatever). + * + * We used to unconditionally output the krb5_sname_to_principal() + * of the host service for the hostname, but we didn't know if we + * had keytab entries for it, so it was incorrect. We can't be + * breaking anything in tree by outputting GSS_C_NO_NAME, but we + * might be breaking other callers. + */ + *output_name = GSS_C_NO_NAME; + } else { + /* This shouldn't happen */ + *minor_status = KRB5_NOCREDS_SUPPLIED; /* XXX */ + ret = GSS_S_NO_CRED; + goto out; + } + } + if (lifetime != NULL) { + ret = _gsskrb5_lifetime_left(minor_status, + context, + cred->endtime, + lifetime); + if (ret) + goto out; + } + if (cred_usage != NULL) + *cred_usage = cred->usage; + if (mechanisms != NULL) { + ret = gss_create_empty_oid_set(minor_status, mechanisms); + if (ret) + goto out; + ret = gss_add_oid_set_member(minor_status, + &cred->mechanisms->elements[0], + mechanisms); + if (ret) + goto out; + } + ret = GSS_S_COMPLETE; + +out: + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c b/third_party/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c new file mode 100644 index 0000000..6ce4994 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2003, 2006, 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred_by_mech ( + OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ) +{ + gss_cred_usage_t usage; + OM_uint32 maj_stat; + OM_uint32 lifetime; + + /* + * XXX This is busted. _gsskrb5_inquire_cred() should be implemented in + * terms of _gsskrb5_inquire_cred_by_mech(), NOT the other way around. + */ + maj_stat = + _gsskrb5_inquire_cred (minor_status, cred_handle, + name, &lifetime, &usage, NULL); + if (maj_stat) + return maj_stat; + + if (initiator_lifetime) { + if (usage == GSS_C_INITIATE || usage == GSS_C_BOTH) + *initiator_lifetime = lifetime; + else + *initiator_lifetime = 0; + } + + if (acceptor_lifetime) { + if (usage == GSS_C_ACCEPT || usage == GSS_C_BOTH) + *acceptor_lifetime = lifetime; + else + *acceptor_lifetime = 0; + } + + if (cred_usage) + *cred_usage = usage; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c b/third_party/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c new file mode 100644 index 0000000..7dae3d2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred_by_oid + (OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_context context; + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; + krb5_error_code ret; + gss_buffer_desc buffer; + char *str; + + GSSAPI_KRB5_INIT (&context); + + if (gss_oid_equal(desired_object, GSS_KRB5_COPY_CCACHE_X) == 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + if (cred->ccache == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = krb5_cc_get_full_name(context, cred->ccache, &str); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + buffer.value = str; + buffer.length = strlen(str); + + ret = gss_add_buffer_set_member(minor_status, &buffer, data_set); + if (ret != GSS_S_COMPLETE) + _gsskrb5_clear_status (); + + free(str); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c b/third_party/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c new file mode 100644 index 0000000..c6c6746 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_mechs_for_name ( + OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_OID_set * mech_types + ) +{ + OM_uint32 ret; + + ret = gss_create_empty_oid_set(minor_status, mech_types); + if (ret) + return ret; + + ret = gss_add_oid_set_member(minor_status, + GSS_KRB5_MECHANISM, + mech_types); + if (ret) + gss_release_oid_set(NULL, mech_types); + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c b/third_party/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c new file mode 100644 index 0000000..65bd49c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static gss_OID name_list[] = { + GSS_C_NT_HOSTBASED_SERVICE, + GSS_C_NT_USER_NAME, + GSS_KRB5_NT_PRINCIPAL_NAME, + GSS_C_NT_EXPORT_NAME, + NULL +}; + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + OM_uint32 ret; + int i; + + *minor_status = 0; + + if (gss_oid_equal(mechanism, GSS_KRB5_MECHANISM) == 0 && + gss_oid_equal(mechanism, GSS_C_NULL_OID) == 0) { + *name_types = GSS_C_NO_OID_SET; + return GSS_S_BAD_MECH; + } + + ret = gss_create_empty_oid_set(minor_status, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + for (i = 0; name_list[i] != NULL; i++) { + ret = gss_add_oid_set_member(minor_status, + name_list[i], + name_types); + if (ret != GSS_S_COMPLETE) + break; + } + + if (ret != GSS_S_COMPLETE) + gss_release_oid_set(NULL, name_types); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c b/third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c new file mode 100644 index 0000000..f572774 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static int +oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix) +{ + int ret; + heim_oid oid; + heim_oid prefix; + + *suffix = 0; + + ret = der_get_oid(oid_enc->elements, oid_enc->length, + &oid, NULL); + if (ret) { + return 0; + } + + ret = der_get_oid(prefix_enc->elements, prefix_enc->length, + &prefix, NULL); + if (ret) { + der_free_oid(&oid); + return 0; + } + + ret = 0; + + if (oid.length - 1 == prefix.length) { + *suffix = oid.components[oid.length - 1]; + oid.length--; + ret = (der_heim_oid_cmp(&oid, &prefix) == 0); + oid.length++; + } + + der_free_oid(&oid); + der_free_oid(&prefix); + + return ret; +} + +static OM_uint32 inquire_sec_context_tkt_flags + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + OM_uint32 tkt_flags; + unsigned char buf[4]; + gss_buffer_desc value; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + if (context_handle->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + _gsskrb5_set_status(EINVAL, "No ticket from which to obtain flags"); + *minor_status = EINVAL; + return GSS_S_BAD_MECH; + } + + tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + _gsskrb5_encode_om_uint32(tkt_flags, buf); + value.length = sizeof(buf); + value.value = buf; + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); +} + +enum keytype { ACCEPTOR_KEY, INITIATOR_KEY, TOKEN_KEY }; + +static OM_uint32 inquire_sec_context_get_subkey + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + enum keytype keytype, + gss_buffer_set_t *data_set) +{ + krb5_keyblock *key = NULL; + krb5_storage *sp = NULL; + krb5_data data; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret; + + krb5_data_zero(&data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + ret = ENOMEM; + goto out; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + switch(keytype) { + case ACCEPTOR_KEY: + ret = _gsskrb5i_get_acceptor_subkey(context_handle, context, &key); + break; + case INITIATOR_KEY: + ret = _gsskrb5i_get_initiator_subkey(context_handle, context, &key); + break; + case TOKEN_KEY: + ret = _gsskrb5i_get_token_key(context_handle, context, &key); + break; + default: + _gsskrb5_set_status(EINVAL, "%d is not a valid subkey type", keytype); + ret = EINVAL; + break; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) + goto out; + if (key == NULL) { + _gsskrb5_set_status(EINVAL, "have no subkey of type %d", keytype); + ret = EINVAL; + goto out; + } + + ret = krb5_store_keyblock(sp, *key); + if (ret) + goto out; + + ret = krb5_storage_to_data(sp, &data); + if (ret) + goto out; + + { + gss_buffer_desc value; + + value.length = data.length; + value.value = data.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + } + +out: + krb5_free_keyblock(context, key); + krb5_data_free(&data); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} + +static OM_uint32 inquire_sec_context_get_sspi_session_key + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + gss_buffer_set_t *data_set) +{ + krb5_keyblock *key; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret; + gss_buffer_desc value; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(context_handle, context, &key); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + if (ret) + goto out; + if (key == NULL) { + ret = EINVAL; + goto out; + } + + value.length = key->keyvalue.length; + value.value = key->keyvalue.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + krb5_free_keyblock(context, key); + + /* MIT also returns the enctype encoded as an OID in data_set[1] */ + +out: + if (ret) { + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} + +static OM_uint32 inquire_sec_context_authz_data + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + unsigned ad_type, + gss_buffer_set_t *data_set) +{ + krb5_data data; + gss_buffer_desc ad_data; + OM_uint32 ret; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + if (context_handle->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + *minor_status = EINVAL; + _gsskrb5_set_status(EINVAL, "No ticket to obtain authz data from"); + return GSS_S_NO_CONTEXT; + } + + ret = krb5_ticket_get_authorization_data_type(context, + context_handle->ticket, + ad_type, + &data); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ad_data.value = data.data; + ad_data.length = data.length; + + ret = gss_add_buffer_set_member(minor_status, + &ad_data, + data_set); + + krb5_data_free(&data); + + return ret; +} + +static OM_uint32 inquire_sec_context_has_buggy_spnego + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + uint8_t old_enctype; + gss_buffer_desc buffer; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + /* + * For Windows SPNEGO implementations, the initiator or acceptor + * are presumed to be "buggy" (Windows 2003 or earlier) if an + * "older" (i.e. pre-AES per RFC 4121) encryption type was used. + */ + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + old_enctype = ((context_handle->more_flags & IS_CFX) == 0); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + buffer.value = &old_enctype; + buffer.length = sizeof(old_enctype); + + return gss_add_buffer_set_member(minor_status, &buffer, data_set); +} + +/* + * + */ + +static OM_uint32 +export_lucid_sec_context_v1(OM_uint32 *minor_status, + gsskrb5_ctx context_handle, + krb5_context context, + gss_buffer_set_t *data_set) +{ + krb5_storage *sp = NULL; + OM_uint32 major_status = GSS_S_COMPLETE; + krb5_error_code ret; + krb5_keyblock *key = NULL; + int32_t number; + int is_cfx; + krb5_data data; + + *minor_status = 0; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + is_cfx = (context_handle->more_flags & IS_CFX); + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + ret = ENOMEM; + goto out; + } + + ret = krb5_store_int32(sp, 1); + if (ret) goto out; + ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0); + if (ret) goto out; + /* XXX need krb5_store_int64() */ + ret = krb5_store_int32(sp, context_handle->endtime); + if (ret) goto out; + krb5_auth_con_getlocalseqnumber (context, + context_handle->auth_context, + &number); + ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ + if (ret) goto out; + ret = krb5_store_uint32(sp, (uint32_t)number); + if (ret) goto out; + krb5_auth_con_getremoteseqnumber (context, + context_handle->auth_context, + &number); + ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ + if (ret) goto out; + ret = krb5_store_uint32(sp, (uint32_t)number); + if (ret) goto out; + ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0); + if (ret) goto out; + + ret = _gsskrb5i_get_token_key(context_handle, context, &key); + if (ret) goto out; + + if (is_cfx == 0) { + int sign_alg, seal_alg; + + switch (key->keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + sign_alg = 0; + seal_alg = 0; + break; + case ETYPE_DES3_CBC_MD5: + case ETYPE_DES3_CBC_SHA1: + sign_alg = 4; + seal_alg = 2; + break; + case ETYPE_ARCFOUR_HMAC_MD5: + case ETYPE_ARCFOUR_HMAC_MD5_56: + sign_alg = 17; + seal_alg = 16; + break; + default: + sign_alg = -1; + seal_alg = -1; + break; + } + ret = krb5_store_int32(sp, sign_alg); + if (ret) goto out; + ret = krb5_store_int32(sp, seal_alg); + if (ret) goto out; + /* ctx_key */ + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + } else { + int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0; + + /* have_acceptor_subkey */ + ret = krb5_store_int32(sp, subkey_p); + if (ret) goto out; + /* ctx_key */ + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + /* acceptor_subkey */ + if (subkey_p) { + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + } + } + ret = krb5_storage_to_data(sp, &data); + if (ret) goto out; + + { + gss_buffer_desc ad_data; + + ad_data.value = data.data; + ad_data.length = data.length; + + ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set); + krb5_data_free(&data); + if (ret) + goto out; + } + +out: + if (key) + krb5_free_keyblock (context, key); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return major_status; +} + +static OM_uint32 +get_authtime(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + gss_buffer_set_t *data_set) + +{ + gss_buffer_desc value; + unsigned char buf[4]; + OM_uint32 authtime; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (ctx->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + _gsskrb5_set_status(EINVAL, "No ticket to obtain auth time from"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + authtime = ctx->ticket->ticket.authtime; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + _gsskrb5_encode_om_uint32(authtime, buf); + value.length = sizeof(buf); + value.value = buf; + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); +} + + +static OM_uint32 +get_service_keyblock + (OM_uint32 *minor_status, + gsskrb5_ctx ctx, + gss_buffer_set_t *data_set) +{ + krb5_storage *sp = NULL; + krb5_data data; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret = EINVAL; + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (ctx->service_keyblock == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + krb5_storage_free(sp); + _gsskrb5_set_status(EINVAL, "No service keyblock on gssapi context"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + krb5_data_zero(&data); + + ret = krb5_store_keyblock(sp, *ctx->service_keyblock); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (ret) + goto out; + + ret = krb5_storage_to_data(sp, &data); + if (ret) + goto out; + + { + gss_buffer_desc value; + + value.length = data.length; + value.value = data.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + } + +out: + krb5_data_free(&data); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} +/* + * + */ + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_sec_context_by_oid + (OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_context context; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + unsigned suffix; + + if (ctx == NULL) { + *minor_status = EINVAL; + return GSS_S_NO_CONTEXT; + } + + GSSAPI_KRB5_INIT (&context); + + if (gss_oid_equal(desired_object, GSS_KRB5_GET_TKT_FLAGS_X)) { + return inquire_sec_context_tkt_flags(minor_status, + ctx, + data_set); + } else if (gss_oid_equal(desired_object, GSS_C_INQ_PEER_HAS_BUGGY_SPNEGO)) { + return inquire_sec_context_has_buggy_spnego(minor_status, + ctx, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + context, + TOKEN_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + context, + INITIATOR_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + context, + ACCEPTOR_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_C_INQ_SSPI_SESSION_KEY)) { + return inquire_sec_context_get_sspi_session_key(minor_status, + ctx, + context, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_AUTHTIME_X)) { + return get_authtime(minor_status, ctx, data_set); + } else if (oid_prefix_equal(desired_object, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X, + &suffix)) { + return inquire_sec_context_authz_data(minor_status, + ctx, + context, + suffix, + data_set); + } else if (oid_prefix_equal(desired_object, + GSS_KRB5_EXPORT_LUCID_CONTEXT_X, + &suffix)) { + if (suffix == 1) + return export_lucid_sec_context_v1(minor_status, + ctx, + context, + data_set); + *minor_status = 0; + return GSS_S_FAILURE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SERVICE_KEYBLOCK_X)) { + return get_service_keyblock(minor_status, ctx, data_set); + } else { + *minor_status = 0; + return GSS_S_FAILURE; + } +} + diff --git a/third_party/heimdal/lib/gssapi/krb5/name_attrs.c b/third_party/heimdal/lib/gssapi/krb5/name_attrs.c new file mode 100644 index 0000000..11fc2ef --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/name_attrs.c @@ -0,0 +1,1171 @@ +/* + * Copyright (c) 2021 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +/* + * (Not-yet-)Standard name attributes for Kerberos MNs, + * GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "...". + * + * I.e., "urn:ietf:kerberos:nameattr-...". (XXX Register this URN namespace + * with IANA.) + * + * Note that we do use URN fragments. + * + * Specific attributes below the base URN: + * + * - name access attributes: + * - "realm" -> realm of name + * - "name-ncomp" -> count of name components + * - "name-ncomp#<digit>" -> name component N (0 <= N <= 9) + * + * Ticket and Authenticator access attributes: + * + * - "transit-path" -> encoding of the transited path + * - "authenticator-authz-data" -> encoding of all of the authz-data from + * the AP-REQ's Authenticator + * - "ticket-authz-data" -> encoding of all of the authz-data from + * the AP-REQ's Ticket + * - "ticket-authz-data#pac" -> the PAC + * - "authz-data#<N>" -> encoding of all of a specific auth-data + * element type N (e.g., 2, meaning + * AD-INTENDED-FOR-SERVER) + * + * Misc. attributes: + * + * - "peer-realm" -> name of peer's realm (if this is an MN + * resulting for establishing a security + * context) + * - "canonical-name" -> exported name token and RFC1964 display + * syntax of the name's canonical name + * + * Compatibility with MIT: + * + * - "urn:mspac:" -> the PAC and its individual info buffers + * + * TODO: + * + * - Add some sort of display syntax for transit path + * - Add support for URN q-components or attribute prefixes to specify + * alternative raw and/or display value encodings (JSON?) + * - Add support for attributes for accessing other parts of the Ticket / KDC + * reply enc-parts, like auth times + * - Add support for getting PAC logon fields, including SIDs (one at a time) + * - Add support for CAMMAC? + */ + +static int +attr_eq(gss_const_buffer_t attr, const char *aname, size_t aname_len, \ + int prefix_check) +{ + if (attr->length < aname_len) + return 0; + + if (strncmp((char *)attr->value, aname, aname_len) != 0) + return 0; + + return prefix_check || attr->length == aname_len; +} + +#define ATTR_EQ(a, an) (attr_eq(a, an, sizeof(an) - 1, FALSE)) +#define ATTR_EQ_PREFIX(a, an) (attr_eq(a, an, sizeof(an) - 1, TRUE)) + +/* Split attribute into prefix, suffix, and fragment. See RFC6680. */ +static void +split_attr(gss_const_buffer_t orig, + gss_buffer_t prefix, + gss_buffer_t attr, + gss_buffer_t frag, + int *is_urn) +{ + char *last = NULL; + char *p = orig->value; + + *attr = *orig; + prefix->value = orig->value; + prefix->length = 0; + frag->length = 0; + frag->value = NULL; + + /* FIXME We don't have a memrchr() in lib/roken */ + for (p = memchr(p, ' ', orig->length); + p; + p = memchr(p + 1, ' ', orig->length)) { + last = p; + prefix->length = last - (const char *)orig->value; + attr->value = last + 1; + attr->length = orig->length - (prefix->length + 1); + } + if (prefix->length == 0) + prefix->value = NULL; + + if ((*is_urn = (strncmp(attr->value, "urn:", sizeof("urn:") - 1) == 0)) && + (p = memchr((char *)attr->value + 1, '#', attr->length - 1))) { + frag->value = ++p; + frag->length = attr->length - (p - (const char *)attr->value); + attr->length = --p - (const char *)attr->value; + } +} + +typedef OM_uint32 get_name_attr_f(OM_uint32 *, + const CompositePrincipal *, + gss_const_buffer_t, + gss_const_buffer_t, + gss_const_buffer_t, + int *, + int *, + gss_buffer_t, + gss_buffer_t, + int *); + +typedef OM_uint32 set_name_attr_f(OM_uint32 *, + CompositePrincipal *, + gss_const_buffer_t, + gss_const_buffer_t, + gss_const_buffer_t, + int, + gss_buffer_t); + +typedef OM_uint32 del_name_attr_f(OM_uint32 *, + CompositePrincipal *, + gss_const_buffer_t, + gss_const_buffer_t, + gss_const_buffer_t); +typedef get_name_attr_f *get_name_attr_fp; +typedef set_name_attr_f *set_name_attr_fp; +typedef del_name_attr_f *del_name_attr_fp; + +static get_name_attr_f get_realm; +static get_name_attr_f get_ncomps; +static get_name_attr_f get_peer_realm; +static get_name_attr_f get_pac; +static get_name_attr_f get_pac_buffer; +static get_name_attr_f get_authz_data; +static get_name_attr_f get_ticket_authz_data; +static get_name_attr_f get_authenticator_authz_data; +static set_name_attr_f set_authenticator_authz_data; +static get_name_attr_f get_transited; +static get_name_attr_f get_canonical_name; + +#define NB(n) \ + GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n, n, \ + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n) - 1, \ + sizeof(n) - 1 +#define NM(n) \ + "urn:mspac:" n, n, sizeof("urn:mspac:" n) - 1, sizeof(n) - 1 + +static struct krb5_name_attrs { + const char *fullname; + const char *name; + size_t fullnamelen; + size_t namelen; + get_name_attr_fp getter; + set_name_attr_fp setter; + del_name_attr_fp deleter; + unsigned int indicate:1; + unsigned int is_krb5_name_attr_urn:1; +} name_attrs[] = { + /* XXX We should sort these so we can binary search them */ + { NB("realm"), get_realm, NULL, NULL, 1, 1 }, + { NB("name-ncomp"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#0"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#1"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#2"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#3"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#4"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#5"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#6"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#7"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#8"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("name-ncomp#9"), get_ncomps, NULL, NULL, 1, 1 }, + { NB("peer-realm"), get_peer_realm, NULL, NULL, 1, 1 }, + { NB("ticket-authz-data#pac"), get_pac, NULL, NULL, 1, 1 }, + { NM(""), get_pac, NULL, NULL, 1, 0 }, + { NM("logon-info"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("credentials-info"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("server-checksum"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("privsvr-checksum"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("client-info"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("delegation-info"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("upn-dns-info"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("ticket-checksum"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("attributes-info"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NM("requestor-sid"), get_pac_buffer, NULL, NULL, 1, 0 }, + { NB("ticket-authz-data#kdc-issued"), + get_ticket_authz_data, NULL, NULL, 1, 1 }, + { NB("ticket-authz-data"), + get_ticket_authz_data, NULL, NULL, 1, 1 }, + { NB("authenticator-authz-data"), + get_authenticator_authz_data, + set_authenticator_authz_data, NULL, 1, 1 }, + { NB("authz-data"), get_authz_data, NULL, NULL, 1, 1 }, + { NB("transit-path"), get_transited, NULL, NULL, 1, 1 }, + { NB("canonical-name"), get_canonical_name, NULL, NULL, 1, 1 }, +}; + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_get_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t original_attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + gss_buffer_desc prefix, attr, suffix, frag; + size_t i; + int is_krb5_name_attr_urn = 0; + int is_urn = 0; + + *minor_status = 0; + if (authenticated) + *authenticated = 0; + if (complete) + *complete = 0; + if (more) + *more = 0; + if (value) { + value->length = 0; + value->value = NULL; + } + if (display_value) { + display_value->length = 0; + display_value->value = NULL; + } + + suffix.value = NULL; + suffix.length = 0; + + split_attr(original_attr, &prefix, &attr, &frag, &is_urn); + + if (prefix.length || !is_urn) + return GSS_S_UNAVAILABLE; + + is_krb5_name_attr_urn = + ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN); + if (is_krb5_name_attr_urn) { + suffix.value = + (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1; + suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1); + } + + for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { + if (!name_attrs[i].getter) + continue; + if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) { + if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0)) + continue; + } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) { + if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0)) + continue; + } else + continue; + + return name_attrs[i].getter(minor_status, + (const CompositePrincipal *)name, + &prefix, &attr, &frag, authenticated, + complete, value, display_value, more); + } + return GSS_S_UNAVAILABLE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_set_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t original_attr, + gss_buffer_t value) +{ + gss_buffer_desc prefix, attr, suffix, frag; + size_t i; + int is_krb5_name_attr_urn = 0; + int is_urn = 0; + + *minor_status = 0; + + suffix.value = NULL; + suffix.length = 0; + + split_attr(original_attr, &prefix, &attr, &frag, &is_urn); + + if (prefix.length || !is_urn) + return GSS_S_UNAVAILABLE; + + is_krb5_name_attr_urn = + ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN); + if (is_krb5_name_attr_urn) { + suffix.value = + (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1; + suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1); + } + + for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { + if (!name_attrs[i].setter) + continue; + if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) { + if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0)) + continue; + } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) { + if (!attr_eq(&attr, name_attrs[i].name, name_attrs[i].namelen, 0)) + continue; + } else + continue; + + return name_attrs[i].setter(minor_status, (CompositePrincipal *)name, + &prefix, &attr, &frag, complete, value); + } + return GSS_S_UNAVAILABLE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t original_attr) +{ + gss_buffer_desc prefix, attr, suffix, frag; + size_t i; + int is_krb5_name_attr_urn = 0; + int is_urn = 0; + + *minor_status = 0; + + suffix.value = NULL; + suffix.length = 0; + + split_attr(original_attr, &prefix, &attr, &frag, &is_urn); + + if (prefix.length || !is_urn) + return GSS_S_UNAVAILABLE; + + is_krb5_name_attr_urn = + ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN); + if (is_krb5_name_attr_urn) { + suffix.value = + (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1; + suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1); + } + + for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { + if (!name_attrs[i].deleter) + continue; + if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) { + if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0)) + continue; + } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) { + if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0)) + continue; + } else + continue; + + return name_attrs[i].deleter(minor_status, (CompositePrincipal *)name, + &prefix, &attr, &frag); + } + return GSS_S_UNAVAILABLE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_inquire_name(OM_uint32 *minor_status, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs) +{ + gss_buffer_desc prefix, attr, frag, a; + OM_uint32 major = GSS_S_UNAVAILABLE; + size_t i; + int authenticated, is_urn; + + *minor_status = 0; + if (name_is_MN) + *name_is_MN = 1; + if (MN_mech) + *MN_mech = GSS_KRB5_MECHANISM; + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ; + if (attrs == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) { + if (!name_attrs[i].indicate) + continue; + a.value = (void *)(uintptr_t)name_attrs[i].fullname; + a.length = name_attrs[i].fullnamelen; + split_attr(&a, &prefix, &attr, &frag, &is_urn); + major = name_attrs[i].getter(minor_status, + (const CompositePrincipal *)name, + &prefix, &attr, &frag, &authenticated, + NULL, NULL, NULL, NULL); + if (major == GSS_S_UNAVAILABLE) + continue; + if (major != GSS_S_COMPLETE) + break; + major = gss_add_buffer_set_member(minor_status, &a, attrs); + } + if (major == GSS_S_UNAVAILABLE) + major = GSS_S_COMPLETE; + return major; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_display_name_ext(OM_uint32 *minor_status, + gss_name_t name, + gss_OID display_as_name_type, + gss_buffer_t display_name) +{ + krb5_const_principal p = (void *)name; + char *s = NULL; + + *minor_status = 0; + if (display_name == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + display_name->length = 0; + display_name->value = NULL; + + if (gss_oid_equal(display_as_name_type, GSS_C_NT_USER_NAME)) { + if (p->name.name_string.len != 1) + return GSS_S_UNAVAILABLE; + return _gsskrb5_localname(minor_status, name, GSS_KRB5_MECHANISM, + display_name); + } + if (!gss_oid_equal(display_as_name_type, GSS_C_NT_HOSTBASED_SERVICE) || + p->name.name_string.len != 2 || + strchr(p->name.name_string.val[0], '@') || + strchr(p->name.name_string.val[1], '.') == NULL) + return GSS_S_UNAVAILABLE; + if (asprintf(&s, "%s@%s", p->name.name_string.val[0], + p->name.name_string.val[1]) == -1 || s == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + display_name->length = strlen(s); + display_name->value = s; + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_export_name_composite(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exported_name) +{ + krb5_error_code kret; + gss_buffer_desc inner = GSS_C_EMPTY_BUFFER; + unsigned char *buf; + size_t sz; + + if (name == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + if (exported_name == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length, + (void *)name, &sz, kret); + if (kret != 0) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length; + exported_name->value = malloc(exported_name->length); + if (exported_name->value == NULL) { + free(inner.value); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + buf = exported_name->value; + buf[0] = 0x04; + buf[1] = 0x02; + buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; + buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; + buf[4] = 0x06; + buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF; + + memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + buf += 6 + GSS_KRB5_MECHANISM->length; + + buf[0] = (inner.length >> 24) & 0xff; + buf[1] = (inner.length >> 16) & 0xff; + buf[2] = (inner.length >> 8) & 0xff; + buf[3] = (inner.length) & 0xff; + buf += 4; + + memcpy(buf, inner.value, inner.length); + free(inner.value); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +#define CHECK_ENOMEM(v, dv) \ + do { \ + if (((v) && !(v)->value) || ((dv) && !(dv)->value)) { \ + if ((v) && (v)->value) { \ + free((v)->value); \ + (v)->length = 0; \ + (v)->value = NULL; \ + } \ + *minor_status = ENOMEM; \ + return GSS_S_FAILURE; \ + } \ + } while (0) + +static OM_uint32 +get_realm(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + PrincipalNameAttrs *nameattrs = name->nameattrs; + + if (prefix->length || frag->length || !name->realm) + return GSS_S_UNAVAILABLE; + if (authenticated && nameattrs && nameattrs->authenticated) + *authenticated = 1; + if (complete) + *complete = 1; + if (value && (value->value = strdup(name->realm))) + value->length = strlen(name->realm); + if (display_value && (display_value->value = strdup(name->realm))) + display_value->length = strlen(name->realm); + CHECK_ENOMEM(value, display_value); + return GSS_S_COMPLETE; +} + +static OM_uint32 +get_ncomps(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + PrincipalNameAttrs *nameattrs = name->nameattrs; + int n = -1; + + if (authenticated && nameattrs && nameattrs->authenticated) + *authenticated = 1; + if (complete) + *complete = 1; + + if (frag->length == 1 && + ((const char *)frag->value)[0] >= '0' && + ((const char *)frag->value)[0] <= '9') { + n = ((const char *)frag->value)[0] - '0'; + } else if (frag->length == sizeof("all") - 1 && + strncmp(frag->value, "all", sizeof("all") - 1) == 0) { + if (!more || *more < -1 || *more == 0 || *more > CHAR_MAX || + *more > (int)name->name.name_string.len) { + *minor_status = EINVAL; + return GSS_S_UNAVAILABLE; + } + if (*more == -1) { + *more = name->name.name_string.len - 1; + n = 0; + } else { + n = name->name.name_string.len - *more; + (*more)--; + } + } + + if (frag->length == 0) { + char *s = NULL; + + /* Outut count of components */ + if (value && (value->value = malloc(sizeof(size_t)))) { + *((size_t *)value->value) = name->name.name_string.len; + value->length = sizeof(size_t); + } + if (display_value && + asprintf(&s, "%u", (unsigned int)name->name.name_string.len) > 0) { + display_value->value = s; + display_value->length = strlen(display_value->value); + } + } else { + /* + * Output a component. The value and the display value are the same in + * this case. + */ + if (n < 0 || n >= name->name.name_string.len) { + *minor_status = EINVAL; + return GSS_S_UNAVAILABLE; + } + if (value && (value->value = strdup(name->name.name_string.val[n]))) + value->length = strlen(name->name.name_string.val[n]); + if (display_value && + (display_value->value = strdup(name->name.name_string.val[n]))) + display_value->length = strlen(name->name.name_string.val[n]); + } + + CHECK_ENOMEM(value, display_value); + return GSS_S_COMPLETE; +} + +static OM_uint32 +get_peer_realm(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + PrincipalNameAttrs *nameattrs = name->nameattrs; + + if (prefix->length || frag->length || !nameattrs || !nameattrs->peer_realm) + return GSS_S_UNAVAILABLE; + if (authenticated) + *authenticated = 1; + if (complete) + *complete = 1; + if (value && (value->value = strdup(nameattrs->peer_realm[0]))) + value->length = strlen(value->value); + if (display_value && + (display_value->value = strdup(nameattrs->peer_realm[0]))) + display_value->length = strlen(display_value->value); + + CHECK_ENOMEM(value, display_value); + return GSS_S_COMPLETE; +} + +static OM_uint32 +get_pac(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_error_code kret; + krb5_context context; + krb5_data data; + PrincipalNameAttrs *nameattrs = name->nameattrs; + PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; + EncTicketPart *ticket = NULL; + + krb5_data_zero(&data); + + if (src == NULL || + src->element != choice_PrincipalNameAttrSrc_enc_ticket_part) + return GSS_S_UNAVAILABLE; + + ticket = &src->u.enc_ticket_part; + + if (prefix->length || !authenticated || !ticket) + return GSS_S_UNAVAILABLE; + + GSSAPI_KRB5_INIT(&context); + + *authenticated = nameattrs->pac_verified; + if (complete) + *complete = 1; + + kret = _krb5_get_ad(context, ticket->authorization_data, + NULL, KRB5_AUTHDATA_WIN2K_PAC, + value ? &data : NULL); + + if (value) { + value->length = data.length; + value->value = data.data; + } + + *minor_status = kret; + if (kret == ENOENT) + return GSS_S_UNAVAILABLE; + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +get_pac_buffer(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_error_code kret; + krb5_context context; + krb5_data data; + PrincipalNameAttrs *nameattrs = name->nameattrs; + krb5_data suffix; + + krb5_data_zero(&data); + + if (prefix->length || !authenticated || + !nameattrs || !nameattrs->pac) + return GSS_S_UNAVAILABLE; + + GSSAPI_KRB5_INIT(&context); + + if (ATTR_EQ_PREFIX(attr, "urn:mspac:")) { + suffix.length = attr->length - (sizeof("urn:mspac:") - 1); + suffix.data = (char *)attr->value + sizeof("urn:mspac:") - 1; + } else if (ATTR_EQ_PREFIX(frag, "pac-")) { + suffix.length = frag->length - sizeof("pac-") - 1; + suffix.data = (char *)frag->value + sizeof("pac-") - 1; + } else + return GSS_S_UNAVAILABLE; /* should not be reached */ + + *authenticated = nameattrs->pac_verified; + if (complete) + *complete = 1; + + kret = _krb5_pac_get_buffer_by_name(context, nameattrs->pac, &suffix, + value ? &data : NULL); + + if (value) { + value->length = data.length; + value->value = data.data; + } + + *minor_status = kret; + if (kret == ENOENT) + return GSS_S_UNAVAILABLE; + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +get_authz_data(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_error_code kret = 0; + PrincipalNameAttrs *nameattrs = name->nameattrs; + PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; + EncTicketPart *ticket = NULL; + krb5_context context; + krb5_data data; + char s[22]; + char *end; + int64_t n; + + if (src) switch (src->element) { + case choice_PrincipalNameAttrSrc_enc_ticket_part: + ticket = &src->u.enc_ticket_part; + break; + case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: + default: + return GSS_S_UNAVAILABLE; + } + + if (!nameattrs || !frag->length || frag->length > sizeof(s) - 1) + return GSS_S_UNAVAILABLE; + + /* Output a specific AD element from the ticket or authenticator */ + krb5_data_zero(&data); + memcpy(s, frag->value, frag->length); + s[frag->length] = '\0'; + errno = 0; + n = strtoll(s, &end, 10); + if (end[0] == '\0' && (errno || n > INT_MAX || n < INT_MIN)) { + *minor_status = ERANGE; + return GSS_S_UNAVAILABLE; + } + if (end[0] != '\0') { + *minor_status = EINVAL; + return GSS_S_UNAVAILABLE; + } + + if (authenticated) + *authenticated = 0; + if (complete) + *complete = 1; + + GSSAPI_KRB5_INIT(&context); + + kret = ENOENT; + if (ticket && ticket->authorization_data) { + kret = _krb5_get_ad(context, ticket->authorization_data, + NULL, n, value ? &data : NULL); + + /* If it's from the ticket, it _may_ be authenticated: */ + if (kret == 0 && authenticated) { + if (n == KRB5_AUTHDATA_KDC_ISSUED) + *authenticated = nameattrs->kdc_issued_verified; + else if (n == KRB5_AUTHDATA_WIN2K_PAC) + *authenticated = nameattrs->pac_verified; + } + } + if (kret == ENOENT && nameattrs->authenticator_ad && + n != KRB5_AUTHDATA_KDC_ISSUED && + n != KRB5_AUTHDATA_WIN2K_PAC) { + kret = _krb5_get_ad(context, nameattrs->authenticator_ad, + NULL, n, value ? &data : NULL); + } + + if (value) { + value->length = data.length; + value->value = data.data; + } + *minor_status = kret; + if (kret == ENOENT) + return GSS_S_UNAVAILABLE; + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +get_ticket_authz_data(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_error_code kret = 0; + PrincipalNameAttrs *nameattrs = name->nameattrs; + PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; + EncTicketPart *ticket = NULL; + size_t sz; + + if (src) switch (src->element) { + case choice_PrincipalNameAttrSrc_enc_ticket_part: + ticket = &src->u.enc_ticket_part; + break; + case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: + default: + return GSS_S_UNAVAILABLE; + } + + if (!ticket) + return GSS_S_UNAVAILABLE; + + if (complete) + *complete = 1; + + if (frag->length == sizeof("kdc-issued") - 1 && + strncmp(frag->value, "kdc-issued", sizeof("kdc-issued") - 1) == 0) { + krb5_context context; + krb5_data data; + + GSSAPI_KRB5_INIT(&context); + if (authenticated) + *authenticated = nameattrs->kdc_issued_verified; + + kret = _krb5_get_ad(context, ticket->authorization_data, + NULL, KRB5_AUTHDATA_KDC_ISSUED, + value ? &data : NULL); + if (value) { + value->length = data.length; + value->value = data.data; + } + if (kret == ENOENT) + return GSS_S_UNAVAILABLE; + *minor_status = kret; + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; + } else if (frag->length) { + return GSS_S_UNAVAILABLE; + } + + /* Just because it's in the Ticket doesn't make it authenticated */ + if (authenticated) + *authenticated = 0; + + if (value) { + ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length, + ticket->authorization_data, &sz, kret); + *minor_status = kret; + } + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +get_authenticator_authz_data(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_error_code kret = 0; + PrincipalNameAttrs *nameattrs = name->nameattrs; + size_t sz; + + if (!nameattrs || !nameattrs->authenticator_ad) + return GSS_S_UNAVAILABLE; + if (authenticated) + *authenticated = 0; + if (complete) + *complete = 1; + + if (value) { + ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length, + nameattrs->authenticator_ad, &sz, kret); + *minor_status = kret; + } + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +set_authenticator_authz_data(OM_uint32 *minor_status, + CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int complete, + gss_buffer_t value) +{ + AuthorizationDataElement e; + krb5_error_code kret; + size_t sz; + + if (!value) + return GSS_S_CALL_INACCESSIBLE_READ; + if (frag->length && + !ATTR_EQ(frag, "if-relevant")) + return GSS_S_UNAVAILABLE; + + if ((name->nameattrs == NULL && + (name->nameattrs = calloc(1, sizeof(*name->nameattrs))) == NULL) || + (name->nameattrs->want_ad == NULL && + (name->nameattrs->want_ad = + calloc(1, sizeof(*name->nameattrs->want_ad))) == NULL)) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memset(&e, 0, sizeof(e)); + kret = decode_AuthorizationDataElement(value->value, value->length, &e, + &sz); + if (kret == 0) { + if (frag->length) { + AuthorizationData ir; + + ir.len = 0; + ir.val = NULL; + kret = add_AuthorizationData(&ir, &e); + free_AuthorizationDataElement(&e); + if (kret == 0) { + e.ad_type = KRB5_AUTHDATA_IF_RELEVANT; + ASN1_MALLOC_ENCODE(AuthorizationData, e.ad_data.data, + e.ad_data.length, &ir, &sz, kret); + kret = add_AuthorizationData(name->nameattrs->want_ad, &e); + } + free_AuthorizationData(&ir); + } else { + kret = add_AuthorizationData(name->nameattrs->want_ad, &e); + free_AuthorizationDataElement(&e); + } + } + + *minor_status = kret; + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +get_transited(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_error_code kret = 0; + PrincipalNameAttrs *nameattrs = name->nameattrs; + PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; + EncTicketPart *ticket = NULL; + size_t sz; + + if (src) switch (src->element) { + case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: + break; + case choice_PrincipalNameAttrSrc_enc_ticket_part: + ticket = &src->u.enc_ticket_part; + break; + default: + return GSS_S_UNAVAILABLE; + } + + if (!nameattrs && !ticket) + return GSS_S_UNAVAILABLE; + if (nameattrs && !nameattrs->transited && !ticket) + return GSS_S_UNAVAILABLE; + + if (authenticated) + *authenticated = 1; + if (complete) + *complete = 1; + + if (value && ticket) + ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length, + &ticket->transited, &sz, kret); + else if (value && nameattrs->transited) + ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length, + nameattrs->transited, &sz, kret); + *minor_status = kret; + return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +get_canonical_name(OM_uint32 *minor_status, + const CompositePrincipal *name, + gss_const_buffer_t prefix, + gss_const_buffer_t attr, + gss_const_buffer_t frag, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_error_code kret = 0; + PrincipalNameAttrs *nameattrs = name->nameattrs; + PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL; + krb5_principal p = NULL; + krb5_context context; + EncTicketPart *ticket = NULL; + EncKDCRepPart *kdcrep = NULL; + + if (src) switch (src->element) { + case choice_PrincipalNameAttrSrc_enc_kdc_rep_part: + kdcrep = &src->u.enc_kdc_rep_part; + break; + case choice_PrincipalNameAttrSrc_enc_ticket_part: + ticket = &src->u.enc_ticket_part; + break; + default: + return GSS_S_UNAVAILABLE; + } + + GSSAPI_KRB5_INIT(&context); + + if (authenticated) + *authenticated = 1; + if (complete) + *complete = 1; + + if (kdcrep) { + kret = _krb5_principalname2krb5_principal(context, &p, + kdcrep->sname, + kdcrep->srealm); + } else if (nameattrs && nameattrs->pac && + (_krb5_pac_get_canon_principal(context, nameattrs->pac, &p)) == 0) { + if (authenticated) + *authenticated = nameattrs->pac_verified; + } else if (ticket) { + krb5_data data; + krb5_pac pac = NULL; + + krb5_data_zero(&data); + + /* Use canonical name from PAC if available */ + kret = _krb5_get_ad(context, ticket->authorization_data, + NULL, KRB5_AUTHDATA_WIN2K_PAC, &data); + if (kret == 0) + kret = krb5_pac_parse(context, data.data, data.length, &pac); + if (kret == 0) + kret = _krb5_pac_get_canon_principal(context, pac, &p); + if (kret == 0 && authenticated) + *authenticated = nameattrs->pac_verified; + else if (kret == ENOENT) + kret = _krb5_principalname2krb5_principal(context, &p, + ticket->cname, + ticket->crealm); + + krb5_data_free(&data); + krb5_pac_free(context, pac); + } else + return GSS_S_UNAVAILABLE; + if (kret == 0 && value) { + OM_uint32 major; + /* + * Value is exported name token (exported composite name token + * should also work). + */ + major = _gsskrb5_export_name(minor_status, (gss_name_t)p, value); + if (major != GSS_S_COMPLETE) { + krb5_free_principal(context, p); + return major; + } + } + if (kret == 0 && display_value) { + /* Display value is principal name display form */ + kret = krb5_unparse_name(context, p, + (char **)&display_value->value); + if (kret == 0) + display_value->length = strlen(display_value->value); + } + + krb5_free_principal(context, p); + if (kret) { + if (value) { + free(value->value); + value->length = 0; + value->value = NULL; + } + *minor_status = kret; + return GSS_S_UNAVAILABLE; + } + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/pname_to_uid.c b/third_party/heimdal/lib/gssapi/krb5/pname_to_uid.c new file mode 100644 index 0000000..dca7464 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/pname_to_uid.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_localname(OM_uint32 *minor_status, + gss_const_name_t pname, + const gss_OID mech_type, + gss_buffer_t localname) +{ + krb5_error_code ret; + krb5_context context; + krb5_const_principal princ = (krb5_const_principal)pname; + char lnamebuf[256]; + + GSSAPI_KRB5_INIT(&context); + + *minor_status = 0; + + ret = krb5_aname_to_localname(context, princ, + sizeof(lnamebuf), lnamebuf); + if (ret != 0) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + localname->length = strlen(lnamebuf); + + localname->value = malloc(localname->length + 1); + if (localname->value == NULL) { + localname->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy(localname->value, lnamebuf, localname->length + 1); + *minor_status = 0; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/prf.c b/third_party/heimdal/lib/gssapi/krb5/prf.c new file mode 100644 index 0000000..671ab2c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/prf.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + gsskrb5_ctx ctx = (gsskrb5_ctx)context_handle; + krb5_context context; + krb5_error_code ret; + krb5_crypto crypto; + krb5_data input, output; + uint32_t num; + OM_uint32 junk; + unsigned char *p; + krb5_keyblock *key = NULL; + size_t dol; + + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + if (desired_output_len <= 0 || prf_in->length + 4 < prf_in->length) { + *minor_status = 0; + return GSS_S_FAILURE; + } + dol = desired_output_len; + + GSSAPI_KRB5_INIT (&context); + + switch(prf_key) { + case GSS_C_PRF_KEY_FULL: + _gsskrb5i_get_acceptor_subkey(ctx, context, &key); + break; + case GSS_C_PRF_KEY_PARTIAL: + _gsskrb5i_get_initiator_subkey(ctx, context, &key); + break; + default: + _gsskrb5_set_status(EINVAL, "unknown kerberos prf_key"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (key == NULL) { + _gsskrb5_set_status(EINVAL, "no prf_key found"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = krb5_crypto_init(context, key, 0, &crypto); + krb5_free_keyblock (context, key); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + prf_out->value = malloc(dol); + if (prf_out->value == NULL) { + _gsskrb5_set_status(GSS_KRB5_S_KG_INPUT_TOO_LONG, "Out of memory"); + *minor_status = GSS_KRB5_S_KG_INPUT_TOO_LONG; + krb5_crypto_destroy(context, crypto); + return GSS_S_FAILURE; + } + prf_out->length = dol; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + input.length = prf_in->length + 4; + input.data = malloc(prf_in->length + 4); + if (input.data == NULL) { + _gsskrb5_set_status(GSS_KRB5_S_KG_INPUT_TOO_LONG, "Out of memory"); + *minor_status = GSS_KRB5_S_KG_INPUT_TOO_LONG; + gss_release_buffer(&junk, prf_out); + krb5_crypto_destroy(context, crypto); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_FAILURE; + } + memcpy(((uint8_t *)input.data) + 4, prf_in->value, prf_in->length); + + num = 0; + p = prf_out->value; + while(dol > 0) { + size_t tsize; + + _gsskrb5_encode_be_om_uint32(num, input.data); + + ret = krb5_crypto_prf(context, crypto, &input, &output); + if (ret) { + *minor_status = ret; + free(input.data); + gss_release_buffer(&junk, prf_out); + krb5_crypto_destroy(context, crypto); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_FAILURE; + } + + tsize = min(dol, output.length); + memcpy(p, output.data, tsize); + p += tsize; + dol -= tsize; + krb5_data_free(&output); + num++; + } + free(input.data); + + krb5_crypto_destroy(context, crypto); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/process_context_token.c b/third_party/heimdal/lib/gssapi/krb5/process_context_token.c new file mode 100644 index 0000000..601b0e8 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/process_context_token.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_process_context_token ( + OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + krb5_context context; + OM_uint32 ret = GSS_S_FAILURE; + gss_buffer_desc empty_buffer; + + empty_buffer.length = 0; + empty_buffer.value = NULL; + + GSSAPI_KRB5_INIT (&context); + + ret = _gsskrb5_verify_mic_internal(minor_status, + (gsskrb5_ctx)context_handle, + context, + token_buffer, &empty_buffer, + GSS_C_QOP_DEFAULT, + "\x01\x02"); + + if (ret == GSS_S_COMPLETE) + ret = _gsskrb5_delete_sec_context(minor_status, + rk_UNCONST(&context_handle), + GSS_C_NO_BUFFER); + if (ret == GSS_S_COMPLETE) + *minor_status = 0; + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/release_buffer.c b/third_party/heimdal/lib/gssapi/krb5/release_buffer.c new file mode 100644 index 0000000..b704e00 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/release_buffer.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997 - 2000, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 _gsskrb5_release_buffer + (OM_uint32 * minor_status, + gss_buffer_t buffer + ) +{ + *minor_status = 0; + free (buffer->value); + buffer->value = NULL; + buffer->length = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/release_cred.c b/third_party/heimdal/lib/gssapi/krb5/release_cred.c new file mode 100644 index 0000000..e1bb870 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/release_cred.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_release_cred + (OM_uint32 * minor_status, + gss_cred_id_t * cred_handle + ) +{ + krb5_context context; + gsskrb5_cred cred; + OM_uint32 junk; + + *minor_status = 0; + + if (*cred_handle == NULL) + return GSS_S_COMPLETE; + + cred = (gsskrb5_cred)*cred_handle; + *cred_handle = GSS_C_NO_CREDENTIAL; + + GSSAPI_KRB5_INIT (&context); + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + free(cred->destination_realm); + if (cred->principal != NULL) + krb5_free_principal(context, cred->principal); + if (cred->keytab != NULL) + krb5_kt_close(context, cred->keytab); + if (cred->ccache != NULL) { + if (cred->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) + krb5_cc_destroy(context, cred->ccache); + else + krb5_cc_close(context, cred->ccache); + } + gss_release_oid_set(&junk, &cred->mechanisms); + if (cred->enctypes) + free(cred->enctypes); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + HEIMDAL_MUTEX_destroy(&cred->cred_id_mutex); + memset(cred, 0, sizeof(*cred)); + free(cred); + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/krb5/release_name.c b/third_party/heimdal/lib/gssapi/krb5/release_name.c new file mode 100644 index 0000000..57fc8a4 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/release_name.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ) +{ + krb5_context context; + krb5_principal name = (krb5_principal)*input_name; + + *minor_status = 0; + + GSSAPI_KRB5_INIT (&context); + + *input_name = GSS_C_NO_NAME; + + krb5_free_principal(context, name); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/sequence.c b/third_party/heimdal/lib/gssapi/krb5/sequence.c new file mode 100644 index 0000000..2e0e7b2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/sequence.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +#define DEFAULT_JITTER_WINDOW 20 + +struct gss_msg_order { + OM_uint32 flags; + OM_uint32 start; + OM_uint32 length; + OM_uint32 jitter_window; + OM_uint32 first_seq; + OM_uint32 elem[1]; +}; + + +/* + * + */ + +static OM_uint32 +msg_order_alloc(OM_uint32 *minor_status, + struct gss_msg_order **o, + OM_uint32 jitter_window) +{ + size_t len; + + len = jitter_window * sizeof((*o)->elem[0]); + len += sizeof(**o); + len -= sizeof((*o)->elem[0]); + + *o = calloc(1, len); + if (*o == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +/* + * + */ + +OM_uint32 +_gssapi_msg_order_create(OM_uint32 *minor_status, + struct gss_msg_order **o, + OM_uint32 flags, + OM_uint32 seq_num, + OM_uint32 jitter_window, + int use_64) +{ + OM_uint32 ret; + + if (jitter_window == 0) + jitter_window = DEFAULT_JITTER_WINDOW; + + ret = msg_order_alloc(minor_status, o, jitter_window); + if(ret != GSS_S_COMPLETE) + return ret; + + (*o)->flags = flags; + (*o)->length = 0; + (*o)->first_seq = seq_num; + (*o)->jitter_window = jitter_window; + (*o)->elem[0] = seq_num - 1; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_msg_order_destroy(struct gss_msg_order **m) +{ + free(*m); + *m = NULL; + return GSS_S_COMPLETE; +} + +static void +elem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val) +{ + o->elem[slot % o->jitter_window] = val; +} + +static void +elem_insert(struct gss_msg_order *o, + unsigned int after_slot, + OM_uint32 seq_num) +{ + assert(o->jitter_window > after_slot); + + if (o->length > after_slot) + memmove(&o->elem[after_slot + 1], &o->elem[after_slot], + (o->length - after_slot - 1) * sizeof(o->elem[0])); + + elem_set(o, after_slot, seq_num); + + if (o->length < o->jitter_window) + o->length++; +} + +/* rule 1: expected sequence number */ +/* rule 2: > expected sequence number */ +/* rule 3: seqnum < seqnum(first) */ +/* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */ + +OM_uint32 +_gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num) +{ + OM_uint32 r; + size_t i; + + if (o == NULL) + return GSS_S_COMPLETE; + + if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0) + return GSS_S_COMPLETE; + + /* check if the packet is the next in order */ + if (o->elem[0] == seq_num - 1) { + elem_insert(o, 0, seq_num); + return GSS_S_COMPLETE; + } + + r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG; + + /* sequence number larger then largest sequence number + * or smaller then the first sequence number */ + if (seq_num > o->elem[0] + || seq_num < o->first_seq + || o->length == 0) + { + elem_insert(o, 0, seq_num); + if (r) { + return GSS_S_COMPLETE; + } else { + return GSS_S_GAP_TOKEN; + } + } + + assert(o->length > 0); + + /* sequence number smaller the first sequence number */ + if (seq_num < o->elem[o->length - 1]) { + if (r) + return(GSS_S_OLD_TOKEN); + else + return(GSS_S_UNSEQ_TOKEN); + } + + if (seq_num == o->elem[o->length - 1]) { + return GSS_S_DUPLICATE_TOKEN; + } + + for (i = 0; i < o->length - 1; i++) { + if (o->elem[i] == seq_num) + return GSS_S_DUPLICATE_TOKEN; + if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) { + elem_insert(o, i, seq_num); + if (r) + return GSS_S_COMPLETE; + else + return GSS_S_UNSEQ_TOKEN; + } + } + + return GSS_S_FAILURE; +} + +OM_uint32 +_gssapi_msg_order_f(OM_uint32 flags) +{ + return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG); +} + +/* + * Translate `o` into inter-process format and export in to `sp'. + */ + +krb5_error_code +_gssapi_msg_order_export(krb5_storage *sp, struct gss_msg_order *o) +{ + krb5_error_code kret; + OM_uint32 i; + + kret = krb5_store_int32(sp, o->flags); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->start); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->length); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->jitter_window); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->first_seq); + if (kret) + return kret; + + for (i = 0; i < o->jitter_window; i++) { + kret = krb5_store_int32(sp, o->elem[i]); + if (kret) + return kret; + } + + return 0; +} + +OM_uint32 +_gssapi_msg_order_import(OM_uint32 *minor_status, + krb5_storage *sp, + struct gss_msg_order **o) +{ + OM_uint32 ret; + krb5_error_code kret; + int32_t i, flags, start, length, jitter_window, first_seq; + + kret = krb5_ret_int32(sp, &flags); + if (kret) + goto failed; + kret = krb5_ret_int32(sp, &start); + if (kret) + goto failed; + kret = krb5_ret_int32(sp, &length); + if (kret) + goto failed; + kret = krb5_ret_int32(sp, &jitter_window); + if (kret) + goto failed; + kret = krb5_ret_int32(sp, &first_seq); + if (kret) + goto failed; + + ret = msg_order_alloc(minor_status, o, jitter_window); + if (ret != GSS_S_COMPLETE) + return ret; + + (*o)->flags = flags; + (*o)->start = start; + (*o)->length = length; + (*o)->jitter_window = jitter_window; + (*o)->first_seq = first_seq; + + for( i = 0; i < jitter_window; i++ ) { + kret = krb5_ret_int32(sp, (int32_t*)&((*o)->elem[i])); + if (kret) + goto failed; + } + + *minor_status = 0; + return GSS_S_COMPLETE; + +failed: + _gssapi_msg_order_destroy(o); + *minor_status = kret; + return GSS_S_FAILURE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/set_cred_option.c b/third_party/heimdal/lib/gssapi/krb5/set_cred_option.c new file mode 100644 index 0000000..ef177a0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static OM_uint32 +import_cred(OM_uint32 *minor_status, + krb5_context context, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + OM_uint32 major_stat; + krb5_error_code ret; + krb5_principal keytab_principal = NULL; + krb5_keytab keytab = NULL; + krb5_storage *sp = NULL; + krb5_ccache id = NULL; + char *str; + + if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + sp = krb5_storage_from_mem(value->value, value->length); + if (sp == NULL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + /* credential cache name */ + ret = krb5_ret_string(sp, &str); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + if (str[0]) { + ret = krb5_cc_resolve(context, str, &id); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + } + free(str); + str = NULL; + + /* keytab principal name */ + ret = krb5_ret_string(sp, &str); + if (ret == 0 && str[0]) + ret = krb5_parse_name(context, str, &keytab_principal); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + free(str); + str = NULL; + + /* keytab principal */ + ret = krb5_ret_string(sp, &str); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + if (str[0]) { + ret = krb5_kt_resolve(context, str, &keytab); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + } + free(str); + str = NULL; + + major_stat = _gsskrb5_krb5_import_cred(minor_status, &id, keytab_principal, + keytab, cred_handle); +out: + if (id) + krb5_cc_close(context, id); + if (keytab_principal) + krb5_free_principal(context, keytab_principal); + if (keytab) + krb5_kt_close(context, keytab); + if (str) + free(str); + if (sp) + krb5_storage_free(sp); + + return major_stat; +} + + +static OM_uint32 +allowed_enctypes(OM_uint32 *minor_status, + krb5_context context, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + OM_uint32 major_stat; + krb5_error_code ret; + size_t len, i; + krb5_enctype *enctypes = NULL; + krb5_storage *sp = NULL; + gsskrb5_cred cred; + + if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + cred = (gsskrb5_cred)*cred_handle; + + if ((value->length % 4) != 0) { + *minor_status = 0; + major_stat = GSS_S_FAILURE; + goto out; + } + + /* serialized as int32_t[], but stored as krb5_enctype[] */ + len = value->length / 4; + enctypes = malloc((len + 1) * sizeof(krb5_enctype)); + if (enctypes == NULL) { + *minor_status = ENOMEM; + major_stat = GSS_S_FAILURE; + goto out; + } + + sp = krb5_storage_from_mem(value->value, value->length); + if (sp == NULL) { + *minor_status = ENOMEM; + major_stat = GSS_S_FAILURE; + goto out; + } + + for (i = 0; i < len; i++) { + int32_t e; + + ret = krb5_ret_int32(sp, &e); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + enctypes[i] = e; + } + enctypes[i] = KRB5_ENCTYPE_NULL; + + if (cred->enctypes) + free(cred->enctypes); + cred->enctypes = enctypes; + + krb5_storage_free(sp); + + return GSS_S_COMPLETE; + +out: + if (sp) + krb5_storage_free(sp); + if (enctypes) + free(enctypes); + + return major_stat; +} + +static OM_uint32 +no_ci_flags(OM_uint32 *minor_status, + krb5_context context, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + gsskrb5_cred cred; + + if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + cred = (gsskrb5_cred)*cred_handle; + cred->cred_flags |= GSS_CF_NO_CI_FLAGS; + + *minor_status = 0; + return GSS_S_COMPLETE; + +} + + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_set_cred_option + (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + krb5_context context; + + GSSAPI_KRB5_INIT (&context); + + if (value == GSS_C_NO_BUFFER) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X)) + return import_cred(minor_status, context, cred_handle, value); + + if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X)) + return allowed_enctypes(minor_status, context, cred_handle, value); + + if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) { + return no_ci_flags(minor_status, context, cred_handle, value); + } + + + *minor_status = EINVAL; + return GSS_S_FAILURE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/set_sec_context_option.c b/third_party/heimdal/lib/gssapi/krb5/set_sec_context_option.c new file mode 100644 index 0000000..3a6f86b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/set_sec_context_option.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * glue routine for _gsskrb5_inquire_sec_context_by_oid + */ + +#include "gsskrb5_locl.h" + +static OM_uint32 +get_bool(OM_uint32 *minor_status, + const gss_buffer_t value, + int *flag) +{ + if (value->value == NULL || value->length != 1) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + *flag = *((const char *)value->value) != 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +get_string(OM_uint32 *minor_status, + const gss_buffer_t value, + char **str) +{ + if (value == NULL || value->length == 0) { + *str = NULL; + } else { + *str = malloc(value->length + 1); + if (*str == NULL) { + *minor_status = 0; + return GSS_S_UNAVAILABLE; + } + memcpy(*str, value->value, value->length); + (*str)[value->length] = '\0'; + } + return GSS_S_COMPLETE; +} + +static OM_uint32 +get_int32(OM_uint32 *minor_status, + const gss_buffer_t value, + OM_uint32 *ret) +{ + *minor_status = 0; + if (value == NULL || value->length == 0) + *ret = 0; + else if (value->length == sizeof(*ret)) + memcpy(ret, value->value, sizeof(*ret)); + else + return GSS_S_UNAVAILABLE; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +set_int32(OM_uint32 *minor_status, + const gss_buffer_t value, + OM_uint32 set) +{ + *minor_status = 0; + if (value->length == sizeof(set)) + memcpy(value->value, &set, sizeof(set)); + else + return GSS_S_UNAVAILABLE; + + return GSS_S_COMPLETE; +} + +/* + * GSS_KRB5_IMPORT_RFC4121_CONTEXT_X is an internal, private interface + * to allow SAnon to create a skeletal context for using RFC4121 message + * protection services. + * + * rfc4121_args ::= initiator_flag || flags || enctype || session key + */ +static OM_uint32 +make_rfc4121_context(OM_uint32 *minor, + krb5_context context, + gss_ctx_id_t *context_handle, + gss_const_buffer_t rfc4121_args) +{ + OM_uint32 major = GSS_S_FAILURE, tmp; + krb5_error_code ret; + krb5_storage *sp = NULL; + gsskrb5_ctx ctx = NULL; + uint8_t initiator_flag; + int32_t enctype; + size_t keysize; + krb5_keyblock *key; + + *minor = 0; + + sp = krb5_storage_from_readonly_mem(rfc4121_args->value, rfc4121_args->length); + if (sp == NULL) { + ret = ENOMEM; + goto out; + } + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST); + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + ret = ENOMEM; + goto out; + } + + ret = krb5_ret_uint8(sp, &initiator_flag); + if (ret != 0) + goto out; + + ret = krb5_ret_uint32(sp, &ctx->flags); + if (ret != 0) + goto out; + + ctx->more_flags = IS_CFX | ACCEPTOR_SUBKEY | OPEN; + if (initiator_flag) + ctx->more_flags |= LOCAL; + + ctx->state = initiator_flag ? INITIATOR_READY : ACCEPTOR_READY; + + ret = krb5_ret_int32(sp, &enctype); + if (ret != 0) + goto out; + + ret = krb5_enctype_keysize(context, enctype, &keysize); + if (ret != 0) + goto out; + + ctx->auth_context = calloc(1, sizeof(*ctx->auth_context)); + if (ctx->auth_context == NULL) { + ret = ENOMEM; + goto out; + } + + key = calloc(1, sizeof(*key)); + if (key == NULL) { + ret = ENOMEM; + goto out; + } + if (initiator_flag) + ctx->auth_context->remote_subkey = key; + else + ctx->auth_context->local_subkey = key; + + key->keytype = enctype; + key->keyvalue.data = malloc(keysize); + if (key->keyvalue.data == NULL) { + ret = ENOMEM; + goto out; + } + + if (krb5_storage_read(sp, key->keyvalue.data, keysize) != keysize) { + ret = EINVAL; + goto out; + } + key->keyvalue.length = keysize; + + ret = krb5_crypto_init(context, key, 0, &ctx->crypto); + if (ret != 0) + goto out; + + major = _gssapi_msg_order_create(minor, &ctx->order, + _gssapi_msg_order_f(ctx->flags), + 0, 0, 1); + if (major != GSS_S_COMPLETE) + goto out; + +out: + krb5_storage_free(sp); + + if (major != GSS_S_COMPLETE) { + if (*minor == 0) + *minor = ret; + _gsskrb5_delete_sec_context(&tmp, (gss_ctx_id_t *)&ctx, GSS_C_NO_BUFFER); + } else { + *context_handle = (gss_ctx_id_t)ctx; + } + + return major; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_set_sec_context_option + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + krb5_context context; + OM_uint32 maj_stat; + + GSSAPI_KRB5_INIT (&context); + + if (value == GSS_C_NO_BUFFER) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_COMPAT_DES3_MIC_X)) { + gsskrb5_ctx ctx; + int flag; + + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_NO_CONTEXT; + } + + maj_stat = get_bool(minor_status, value, &flag); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + ctx = (gsskrb5_ctx)*context_handle; + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (flag) + ctx->more_flags |= COMPAT_OLD_DES3; + else + ctx->more_flags &= ~COMPAT_OLD_DES3; + ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_COMPLETE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DNS_CANONICALIZE_X)) { + int flag; + + maj_stat = get_bool(minor_status, value, &flag); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + krb5_set_dns_canonicalize_hostname(context, flag); + return GSS_S_COMPLETE; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X)) { + char *str; + + maj_stat = get_string(minor_status, value, &str); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + maj_stat = _gsskrb5_register_acceptor_identity(minor_status, str); + free(str); + + return maj_stat; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DEFAULT_REALM_X)) { + char *str; + + maj_stat = get_string(minor_status, value, &str); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + if (str == NULL) { + *minor_status = 0; + return GSS_S_CALL_INACCESSIBLE_READ; + } + + krb5_set_default_realm(context, str); + free(str); + + *minor_status = 0; + return GSS_S_COMPLETE; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_SEND_TO_KDC_X)) { + + *minor_status = EINVAL; + return GSS_S_FAILURE; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_TIME_OFFSET_X)) { + OM_uint32 offset; + time_t t; + + maj_stat = get_int32(minor_status, value, &offset); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + t = time(NULL) + offset; + + krb5_set_real_time(context, t, 0); + + *minor_status = 0; + return GSS_S_COMPLETE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_TIME_OFFSET_X)) { + krb5_timestamp sec; + int32_t usec; + time_t t; + + t = time(NULL); + + krb5_us_timeofday (context, &sec, &usec); + + maj_stat = set_int32(minor_status, value, sec - t); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + *minor_status = 0; + return GSS_S_COMPLETE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_PLUGIN_REGISTER_X)) { + struct gsskrb5_krb5_plugin c; + + if (value->length != sizeof(c)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + memcpy(&c, value->value, sizeof(c)); + krb5_plugin_register(context, c.type, c.name, c.symbol); + + *minor_status = 0; + return GSS_S_COMPLETE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_CCACHE_NAME_X)) { + struct gsskrb5_ccache_name_args *args = value->value; + + if (value->length != sizeof(*args)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + return _gsskrb5_krb5_ccache_name(minor_status, args->name, &args->out_name); + } else if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_RFC4121_CONTEXT_X)) { + return make_rfc4121_context(minor_status, context, context_handle, value); + } + + *minor_status = EINVAL; + return GSS_S_FAILURE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/store_cred.c b/third_party/heimdal/lib/gssapi/krb5/store_cred.c new file mode 100644 index 0000000..6d727b4 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/store_cred.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +static int +same_princ(krb5_context context, krb5_ccache id1, krb5_ccache id2) +{ + krb5_error_code ret; + krb5_principal p1 = NULL; + krb5_principal p2 = NULL; + int same = 0; + + ret = krb5_cc_get_principal(context, id1, &p1); + if (ret == 0) + ret = krb5_cc_get_principal(context, id2, &p2); + /* If either principal is absent, it's the same for our purposes */ + same = ret ? 1 : krb5_principal_compare(context, p1, p2); + krb5_free_principal(context, p1); + krb5_free_principal(context, p2); + return same; +} + +static OM_uint32 +add_env(OM_uint32 *minor, + gss_buffer_set_t *env, + const char *var, + const char *val) +{ + OM_uint32 major; + gss_buffer_desc b; + char *varval = NULL; + + if (asprintf(&varval, "%s=%s", var, val) == -1 || varval == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + b.value = varval; + b.length = strlen(varval) + 1; + major = gss_add_buffer_set_member(minor, &b, env); + free(varval); + return major; +} + +static OM_uint32 +set_proc(OM_uint32 *minor, gss_buffer_set_t env) +{ + /* + * XXX On systems with setpag(), call setpag(). On WIN32... create a + * session, set the access token, ...? + */ +#ifndef WIN32 + size_t i; + + for (i = 0; i < env->count; i++) + putenv(env->elements[i].value); +#endif + return GSS_S_COMPLETE; +} + +/* + * A principal is the best principal for a user IFF + * + * - it has one component + * - the one component is the same as the user's name + * - the real is the user_realm from configuration + */ +static int +principal_is_best_for_user(krb5_context context, + const char *app, + krb5_const_principal p, + const char *user) +{ + char *default_realm = NULL; + char *user_realm = NULL; + int ret; + + (void) krb5_get_default_realm(context, &default_realm); + krb5_appdefault_string(context, app, NULL, "user_realm", default_realm, + &user_realm); + ret = user_realm && + krb5_principal_get_num_comp(context, p) == 1 && + strcmp(user_realm, krb5_principal_get_realm(context, p)) == 0 && + (!user || + strcmp(user, krb5_principal_get_comp_string(context, p, 0)) == 0); + free(default_realm); + free(user_realm); + return ret; +} + +static krb5_error_code +check_destination_tgt_policy(krb5_context context, + const char *appname, + gsskrb5_cred input_cred) +{ + krb5_error_code ret; + krb5_boolean want_dst_tgt = 0; + krb5_data v; + + if (input_cred->destination_realm == NULL) + /* + * Not a delegated credential, so we can't check the destination TGT + * policy for the realm of the service -- we don't know the realm of + * the service. + */ + return 0; + + krb5_appdefault_boolean(context, appname, input_cred->destination_realm, + "require_delegate_destination_tgt", FALSE, + &want_dst_tgt); + if (!want_dst_tgt) + return 0; + + krb5_data_zero(&v); + ret = krb5_cc_get_config(context, input_cred->ccache, NULL, + "start_realm", &v); + if (ret == 0 && + v.length != strlen(input_cred->destination_realm)) + ret = KRB5_CC_NOTFOUND; + if (ret == 0 && + strncmp(input_cred->destination_realm, v.data, v.length) != 0) + ret = KRB5_CC_NOTFOUND; + if (ret) + krb5_set_error_message(context, ret, + "Delegated TGT is not a destination TGT for " + "realm \"%s\" but for \"%.*s\"", + input_cred->destination_realm, + (int)(v.length ? v.length : sizeof("<UNKNOWN>") - 1), + v.data ? (const char *)v.data : "<UNKNOWN>"); + krb5_data_free(&v); + return ret; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_store_cred_into2(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 store_cred_flags, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored, + gss_buffer_set_t *envp) +{ + krb5_context context; + krb5_error_code ret; + gsskrb5_cred input_cred; + krb5_ccache id = NULL; + time_t exp_current; + time_t exp_new; + gss_buffer_set_t env = GSS_C_NO_BUFFER_SET; + const char *cs_unique_ccache = NULL; + const char *cs_ccache_name = NULL; + const char *cs_user_name = NULL; + const char *cs_app_name = NULL; + char *ccache_name = NULL; + OM_uint32 major_status = GSS_S_FAILURE; + OM_uint32 junk; + OM_uint32 overwrite_cred = store_cred_flags & GSS_C_STORE_CRED_OVERWRITE; + int default_for = 0; + + *minor_status = 0; + + /* Sanity check inputs */ + if (cred_usage != GSS_C_INITIATE) { + /* It'd be nice if we could also do accept, writing a keytab */ + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_FAILURE; + } + if (desired_mech != GSS_C_NO_OID && + gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) + return GSS_S_BAD_MECH; + if (input_cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_CALL_INACCESSIBLE_READ; + input_cred = (gsskrb5_cred)input_cred_handle; + + /* Sanity check the input_cred */ + if (input_cred->usage != cred_usage && input_cred->usage != GSS_C_BOTH) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_NO_CRED; + } + if (input_cred->principal == NULL) { + *minor_status = GSS_KRB5_S_KG_TGT_MISSING; + return GSS_S_NO_CRED; + } + + /* Extract the ccache name from the store if given */ + if (cred_store != GSS_C_NO_CRED_STORE) { + major_status = __gsskrb5_cred_store_find(minor_status, cred_store, + "unique_ccache_type", + &cs_unique_ccache); + if (GSS_ERROR(major_status)) + return major_status; + major_status = __gsskrb5_cred_store_find(minor_status, cred_store, + "ccache", &cs_ccache_name); + if (GSS_ERROR(major_status)) + return major_status; + major_status = __gsskrb5_cred_store_find(minor_status, cred_store, + "username", &cs_user_name); + if (GSS_ERROR(major_status)) + return major_status; + major_status = __gsskrb5_cred_store_find(minor_status, cred_store, + "appname", &cs_app_name); + if (GSS_ERROR(major_status)) + return major_status; + } + + GSSAPI_KRB5_INIT (&context); + HEIMDAL_MUTEX_lock(&input_cred->cred_id_mutex); + + if (cs_ccache_name && strchr(cs_ccache_name, '%')) { + ret = _krb5_expand_default_cc_name(context, cs_ccache_name, + &ccache_name); + if (ret) { + HEIMDAL_MUTEX_unlock(&input_cred->cred_id_mutex); + *minor_status = ret; + return GSS_S_FAILURE; + } + cs_ccache_name = ccache_name; + } + + /* More sanity checking of the input_cred (good to fail early) */ + ret = krb5_cc_get_lifetime(context, input_cred->ccache, &exp_new); + if (ret) { + HEIMDAL_MUTEX_unlock(&input_cred->cred_id_mutex); + *minor_status = ret; + free(ccache_name); + return GSS_S_NO_CRED; + } + + ret = check_destination_tgt_policy(context, cs_app_name, input_cred); + if (ret) { + HEIMDAL_MUTEX_unlock(&input_cred->cred_id_mutex); + *minor_status = ret; + free(ccache_name); + return GSS_S_NO_CRED; + } + + /* + * Find an appropriate ccache, which will be one of: + * + * - the one given in the cred_store, if given + * - a new unique one for some ccache type in the cred_store, if given + * - a subsidiary cache named for the principal in the default collection, + * if the principal is the "best principal for the user" + * - the default ccache + */ + if (cs_ccache_name) { + ret = krb5_cc_resolve(context, cs_ccache_name, &id); + } else if (cs_unique_ccache) { + overwrite_cred = 1; + ret = krb5_cc_new_unique(context, cs_unique_ccache, NULL, &id); + } else if (principal_is_best_for_user(context, cs_app_name, + input_cred->principal, + cs_user_name)) { + ret = krb5_cc_default(context, &id); + if (ret == 0 && !same_princ(context, id, input_cred->ccache)) { + krb5_cc_close(context, id); + ret = krb5_cc_default_for(context, input_cred->principal, &id); + default_for = 1; + } + } else { + ret = krb5_cc_default_for(context, input_cred->principal, &id); + default_for = 1; + } + + if (ret || id == NULL) { + HEIMDAL_MUTEX_unlock(&input_cred->cred_id_mutex); + *minor_status = ret; + free(ccache_name); + return ret == 0 ? GSS_S_NO_CRED : GSS_S_FAILURE; + } + + /* + * If we're using a subsidiary ccache for this principal and it has some + * other principal's tickets in it -> overwrite. + */ + if (!overwrite_cred && default_for && + !same_princ(context, id, input_cred->ccache)) + overwrite_cred = 1; + if (!overwrite_cred && same_princ(context, id, input_cred->ccache)) { + /* + * If current creds are for the same princ as we already had creds for, + * and the new creds live longer than the old, overwrite. + */ + ret = krb5_cc_get_lifetime(context, id, &exp_current); + if (ret != 0 || exp_new > exp_current) + overwrite_cred = 1; + } + + if (overwrite_cred) { + ret = krb5_cc_initialize(context, id, input_cred->principal); + if (ret == 0) + ret = krb5_cc_copy_match_f(context, input_cred->ccache, id, NULL, NULL, + NULL); + } + + if ((store_cred_flags & GSS_C_STORE_CRED_SET_PROCESS) && envp == NULL) + envp = &env; + if (envp != NULL) { + char *fullname = NULL; + + if ((ret = krb5_cc_get_full_name(context, id, &fullname)) == 0) { + major_status = add_env(minor_status, envp, "KRB5CCNAME", fullname); + free(fullname); + if (major_status) + ret = *minor_status; + } + } + (void) krb5_cc_close(context, id); + + HEIMDAL_MUTEX_unlock(&input_cred->cred_id_mutex); + if (ret == 0 && (store_cred_flags & GSS_C_STORE_CRED_SET_PROCESS) && + (major_status = set_proc(minor_status, *envp)) != GSS_S_COMPLETE) + ret = *minor_status; + (void) gss_release_buffer_set(&junk, &env); + free(ccache_name); + *minor_status = ret; + return ret ? major_status : GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_store_cred_into(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + OM_uint32 store_cred_flags = + (overwrite_cred ? GSS_C_STORE_CRED_OVERWRITE : 0) | + (default_cred ? GSS_C_STORE_CRED_DEFAULT : 0); + + return _gsskrb5_store_cred_into2(minor_status, input_cred_handle, + cred_usage, desired_mech, + store_cred_flags, cred_store, + elements_stored, cred_usage_stored, NULL); +} diff --git a/third_party/heimdal/lib/gssapi/krb5/test_acquire_cred.c b/third_party/heimdal/lib/gssapi/krb5/test_acquire_cred.c new file mode 100644 index 0000000..812fce6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/test_acquire_cred.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2003-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" +#include <err.h> + +static void +print_time(OM_uint32 time_rec) +{ + if (time_rec == GSS_C_INDEFINITE) { + printf("cred never expire\n"); + } else { + time_t t = time_rec + time(NULL); + printf("expiration time: %s", ctime(&t)); + } +} + +static void +test_add(gss_cred_id_t cred_handle) +{ + OM_uint32 major_status, minor_status; + gss_cred_id_t copy_cred; + OM_uint32 time_rec; + + major_status = gss_add_cred (&minor_status, + cred_handle, + GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, + GSS_C_INITIATE, + 0, + 0, + ©_cred, + NULL, + &time_rec, + NULL); + + if (GSS_ERROR(major_status)) + errx(1, "add_cred failed"); + + print_time(time_rec); + + major_status = gss_release_cred(&minor_status, + ©_cred); + if (GSS_ERROR(major_status)) + errx(1, "release_cred failed"); +} + +static void +test_add_mutate(gss_cred_id_t cred_handle) +{ + OM_uint32 major_status, minor_status; + OM_uint32 time_rec; + + major_status = gss_add_cred (&minor_status, + cred_handle, + GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, + GSS_C_INITIATE, + 0, + 0, + NULL, + NULL, + &time_rec, + NULL); + + if (GSS_ERROR(major_status)) + errx(1, "add_cred failed"); + + print_time(time_rec); +} + +static void +copy_cred(void) +{ + OM_uint32 major_status, minor_status; + gss_cred_id_t cred_handle; + OM_uint32 time_rec; + + major_status = gss_acquire_cred(&minor_status, + GSS_C_NO_NAME, + 0, + NULL, + GSS_C_INITIATE, + &cred_handle, + NULL, + &time_rec); + if (GSS_ERROR(major_status)) + errx(1, "acquire_cred failed"); + + print_time(time_rec); + + test_add(cred_handle); + test_add(cred_handle); + test_add(cred_handle); + test_add_mutate(cred_handle); + + major_status = gss_release_cred(&minor_status, + &cred_handle); + if (GSS_ERROR(major_status)) + errx(1, "release_cred failed"); +} + +static void +acquire_cred_service(const char *service) +{ + OM_uint32 major_status, minor_status; + gss_cred_id_t cred_handle; + OM_uint32 time_rec; + gss_buffer_desc name_buffer; + gss_name_t name; + + name_buffer.value = rk_UNCONST(service); + name_buffer.length = strlen(service); + + major_status = gss_import_name(&minor_status, + &name_buffer, + GSS_C_NT_HOSTBASED_SERVICE, + &name); + if (GSS_ERROR(major_status)) + errx(1, "import_name failed"); + + + major_status = gss_acquire_cred(&minor_status, + name, + 0, + NULL, + GSS_C_ACCEPT, + &cred_handle, + NULL, + &time_rec); + if (GSS_ERROR(major_status)) + errx(1, "acquire_cred failed"); + + print_time(time_rec); + + major_status = gss_release_cred(&minor_status, + &cred_handle); + if (GSS_ERROR(major_status)) + errx(1, "release_cred failed"); + + + major_status = gss_release_name(&minor_status, + &name); + if (GSS_ERROR(major_status)) + errx(1, "release_name failed"); + +} + +int +main(int argc, char **argv) +{ + copy_cred(); + + acquire_cred_service("host@xen2-heimdal-linux.lab.it.su.se"); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/test_cfx.c b/third_party/heimdal/lib/gssapi/krb5/test_cfx.c new file mode 100644 index 0000000..15f853c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/test_cfx.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +struct range { + size_t lower; + size_t upper; +}; + +struct range tests[] = { + { 0, 1040 }, + { 2040, 2080 }, + { 4080, 5000 }, + { 8180, 8292 }, + { 9980, 10010 } +}; + +static void +test_range(const struct range *r, int integ, + krb5_context context, krb5_crypto crypto) +{ + krb5_error_code ret; + size_t size, rsize; + struct gsskrb5_ctx ctx; + + for (size = r->lower; size < r->upper; size++) { + size_t cksumsize; + uint16_t padsize; + OM_uint32 minor; + OM_uint32 max_wrap_size; + + ctx.crypto = crypto; + + ret = _gssapi_wrap_size_cfx(&minor, + &ctx, + context, + integ, + 0, + size, + &max_wrap_size); + if (ret) + krb5_errx(context, 1, "_gsskrb5cfx_max_wrap_length_cfx: %d", ret); + if (max_wrap_size == 0) + continue; + + ret = _gsskrb5cfx_wrap_length_cfx(context, + crypto, + integ, + 0, + max_wrap_size, + &rsize, &cksumsize, &padsize); + if (ret) + krb5_errx(context, 1, "_gsskrb5cfx_wrap_length_cfx: %d", ret); + + if (size < rsize) + krb5_errx(context, 1, + "size (%d) < rsize (%d) for max_wrap_size %d", + (int)size, (int)rsize, (int)max_wrap_size); + } +} + +static void +test_special(krb5_context context, krb5_crypto crypto, + int integ, size_t testsize) +{ + krb5_error_code ret; + size_t rsize; + OM_uint32 max_wrap_size; + size_t cksumsize; + uint16_t padsize; + struct gsskrb5_ctx ctx; + OM_uint32 minor; + + ctx.crypto = crypto; + + ret = _gssapi_wrap_size_cfx(&minor, + &ctx, + context, + integ, + 0, + testsize, + &max_wrap_size); + if (ret) + krb5_errx(context, 1, "_gsskrb5cfx_max_wrap_length_cfx: %d", ret); + if (ret) + krb5_errx(context, 1, "_gsskrb5cfx_max_wrap_length_cfx: %d", ret); + + ret = _gsskrb5cfx_wrap_length_cfx(context, + crypto, + integ, + 0, + max_wrap_size, + &rsize, &cksumsize, &padsize); + if (ret) + krb5_errx(context, 1, "_gsskrb5cfx_wrap_length_cfx: %d", ret); + + if (testsize < rsize) + krb5_errx(context, 1, + "testsize (%d) < rsize (%d) for max_wrap_size %d", + (int)testsize, (int)rsize, (int)max_wrap_size); +} + + + + +int +main(int argc, char **argv) +{ + krb5_keyblock keyblock; + krb5_error_code ret; + krb5_context context; + krb5_crypto crypto; + int i; + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_context_init: %d", ret); + + ret = krb5_generate_random_keyblock(context, + KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, + &keyblock); + if (ret) + krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); + + ret = krb5_crypto_init(context, &keyblock, 0, &crypto); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_init"); + + test_special(context, crypto, 1, 60); + test_special(context, crypto, 0, 60); + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + test_range(&tests[i], 1, context, crypto); + test_range(&tests[i], 0, context, crypto); + } + + krb5_free_keyblock_contents(context, &keyblock); + krb5_crypto_destroy(context, crypto); + krb5_free_context(context); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/test_cred.c b/third_party/heimdal/lib/gssapi/krb5/test_cred.c new file mode 100644 index 0000000..e0395f0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/test_cred.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2003-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" +#include <err.h> +#include <getarg.h> + +static void +gss_print_errors (int min_stat) +{ + OM_uint32 new_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + OM_uint32 ret; + + do { + ret = gss_display_status (&new_stat, + min_stat, + GSS_C_MECH_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + fprintf (stderr, "%.*s\n", (int)status_string.length, + (char *)status_string.value); + gss_release_buffer (&new_stat, &status_string); + } while (!GSS_ERROR(ret) && msg_ctx != 0); +} + +static void +gss_err(int exitval, int status, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vwarnx (fmt, args); + gss_print_errors (status); + va_end(args); + exit (exitval); +} + +static void +acquire_release_loop(gss_name_t name, int counter, gss_cred_usage_t usage) +{ + OM_uint32 maj_stat, min_stat; + gss_cred_id_t cred; + int i; + + for (i = 0; i < counter; i++) { + maj_stat = gss_acquire_cred(&min_stat, name, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + usage, + &cred, + NULL, + NULL); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "aquire %d %d != GSS_S_COMPLETE", + i, (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release %d %d != GSS_S_COMPLETE", + i, (int)maj_stat); + } +} + + +static void +acquire_add_release_add(gss_name_t name, gss_cred_usage_t usage) +{ + OM_uint32 maj_stat, min_stat; + gss_cred_id_t cred, cred2, cred3; + + maj_stat = gss_acquire_cred(&min_stat, name, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + usage, + &cred, + NULL, + NULL); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "aquire %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_add_cred(&min_stat, + cred, + GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, + usage, + GSS_C_INDEFINITE, + GSS_C_INDEFINITE, + &cred2, + NULL, + NULL, + NULL); + + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "add_cred %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_add_cred(&min_stat, + cred2, + GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, + GSS_C_BOTH, + GSS_C_INDEFINITE, + GSS_C_INDEFINITE, + &cred3, + NULL, + NULL, + NULL); + + maj_stat = gss_release_cred(&min_stat, &cred2); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred3); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat); +} + +static void +add_add_release_add(gss_name_t name, gss_cred_usage_t usage) +{ + OM_uint32 maj_stat, min_stat; + gss_cred_id_t cred, cred2; + + maj_stat = gss_add_cred(&min_stat, + GSS_C_NO_CREDENTIAL, + name, + GSS_KRB5_MECHANISM, + usage, + GSS_C_INDEFINITE, + GSS_C_INDEFINITE, + &cred, + NULL, + NULL, + NULL); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "add_cred %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_add_cred(&min_stat, + cred, + GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, + usage, + GSS_C_INDEFINITE, + GSS_C_INDEFINITE, + &cred2, + NULL, + NULL, + NULL); + + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "add_cred %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_add_cred(&min_stat, + cred2, + GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, + GSS_C_BOTH, + GSS_C_INDEFINITE, + GSS_C_INDEFINITE, + NULL, + NULL, + NULL, + NULL); + + maj_stat = gss_release_cred(&min_stat, &cred2); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat); +} + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, "service@host"); + exit (ret); +} + + +int +main(int argc, char **argv) +{ + struct gss_buffer_desc_struct name_buffer; + OM_uint32 maj_stat, min_stat; + gss_name_t name; + int optidx = 0; + + setprogname(argv[0]); + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc < 1) + errx(1, "argc < 1"); + + name_buffer.value = argv[0]; + name_buffer.length = strlen(argv[0]); + + maj_stat = gss_import_name(&min_stat, &name_buffer, + GSS_C_NT_HOSTBASED_SERVICE, + &name); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import name error"); + + acquire_release_loop(name, 100, GSS_C_ACCEPT); + acquire_release_loop(name, 100, GSS_C_INITIATE); + acquire_release_loop(name, 100, GSS_C_BOTH); + + acquire_add_release_add(name, GSS_C_ACCEPT); + acquire_add_release_add(name, GSS_C_INITIATE); + acquire_add_release_add(name, GSS_C_BOTH); + + add_add_release_add(name, GSS_C_ACCEPT); + add_add_release_add(name, GSS_C_INITIATE); + add_add_release_add(name, GSS_C_BOTH); + + gss_release_name(&min_stat, &name); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/test_kcred.c b/third_party/heimdal/lib/gssapi/krb5/test_kcred.c new file mode 100644 index 0000000..c90a144 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/test_kcred.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2003-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" +#include <err.h> +#include <getarg.h> + +static int version_flag = 0; +static int help_flag = 0; + +static void +copy_import(void) +{ + gss_cred_id_t cred1, cred2; + OM_uint32 maj_stat, min_stat; + gss_name_t name1, name2; + OM_uint32 lifetime1, lifetime2; + gss_cred_usage_t usage1, usage2; + gss_OID_set mechs1, mechs2; + krb5_ccache id; + krb5_error_code ret; + krb5_context context; + int equal; + + maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_INITIATE, + &cred1, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_acquire_cred"); + + maj_stat = gss_inquire_cred(&min_stat, cred1, &name1, &lifetime1, + &usage1, &mechs1); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_inquire_cred"); + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_init_context"); + + ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_new_unique"); + + maj_stat = gss_krb5_copy_ccache(&min_stat, context, cred1, id); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_copy_ccache"); + + maj_stat = gss_krb5_import_cred(&min_stat, id, NULL, NULL, &cred2); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_import_cred"); + + maj_stat = gss_inquire_cred(&min_stat, cred2, &name2, &lifetime2, + &usage2, &mechs2); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_inquire_cred 2"); + + maj_stat = gss_compare_name(&min_stat, name1, name2, &equal); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_compare_name"); + if (!equal) + errx(1, "names not equal"); + + /* This check is racy! */ + if (getenv("TESTS_ENVIRONMENT") == NULL) && lifetime1 != lifetime2) + errx(1, "lifetime not equal"); + if (lifetime1 != lifetime2) + warnx("lifetime not equal"); + + if (usage1 != usage1) + errx(1, "usage not equal"); + + gss_release_cred(&min_stat, &cred1); + gss_release_cred(&min_stat, &cred2); + + gss_release_name(&min_stat, &name1); + gss_release_name(&min_stat, &name2); + +#if 0 + compare(mechs1, mechs2); +#endif + + gss_release_oid_set(&min_stat, &mechs1); + gss_release_oid_set(&min_stat, &mechs2); + + krb5_cc_destroy(context, id); + krb5_free_context(context); +} + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int optidx = 0; + + setprogname(argv[0]); + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + copy_import(); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/test_oid.c b/third_party/heimdal/lib/gssapi/krb5/test_oid.c new file mode 100644 index 0000000..00219b9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/test_oid.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +int +main(int argc, char **argv) +{ + OM_uint32 minor_status, maj_stat; + gss_buffer_desc data; + int ret; + + maj_stat = gss_oid_to_str(&minor_status, GSS_KRB5_MECHANISM, &data); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_oid_to_str failed"); + ret = strncmp(data.value, "1 2 840 113554 1 2 2", data.length); + gss_release_buffer(&maj_stat, &data); + if (ret) + return 1; + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/test_sequence.c b/third_party/heimdal/lib/gssapi/krb5/test_sequence.c new file mode 100644 index 0000000..33a4aac --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/test_sequence.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +/* correct ordering */ +OM_uint32 pattern1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 +}; + +/* gap 10 */ +OM_uint32 pattern2[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13 +}; + +/* dup 9 */ +OM_uint32 pattern3[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13 +}; + +/* gaps */ +OM_uint32 pattern4[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16, 18, 100 +}; + +/* 11 before 10 */ +OM_uint32 pattern5[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 +}; + +/* long */ +OM_uint32 pattern6[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 +}; + +/* don't start at 0 */ +OM_uint32 pattern7[] = { + 11, 12, 13 +}; + +/* wrap around */ +OM_uint32 pattern8[] = { + 4294967293U, 4294967294U, 4294967295U, 0, 1, 2 +}; + +static int +test_seq(int t, OM_uint32 flags, OM_uint32 start_seq, + OM_uint32 *pattern, int pattern_len, OM_uint32 expected_error) +{ + struct gss_msg_order *o; + OM_uint32 maj_stat, min_stat; + krb5_storage *sp; + int i; + + maj_stat = _gssapi_msg_order_create(&min_stat, &o, flags, + start_seq, 20, 0); + if (maj_stat) + errx(1, "create: %d %d", maj_stat, min_stat); + + sp = krb5_storage_emem(); + if (sp == NULL) + errx(1, "krb5_storage_from_emem"); + + _gssapi_msg_order_export(sp, o); + + for (i = 0; i < pattern_len; i++) { + maj_stat = _gssapi_msg_order_check(o, pattern[i]); + if (maj_stat) + break; + } + if (maj_stat != expected_error) { + printf("test pattern %d failed with %d (should have been %d)\n", + t, maj_stat, expected_error); + krb5_storage_free(sp); + _gssapi_msg_order_destroy(&o); + return 1; + } + + + _gssapi_msg_order_destroy(&o); + + /* try again, now with export/imported blob */ + krb5_storage_seek(sp, 0, SEEK_SET); + + maj_stat = _gssapi_msg_order_import(&min_stat, sp, &o); + if (maj_stat) + errx(1, "import: %d %d", maj_stat, min_stat); + + for (i = 0; i < pattern_len; i++) { + maj_stat = _gssapi_msg_order_check(o, pattern[i]); + if (maj_stat) + break; + } + if (maj_stat != expected_error) { + printf("import/export test pattern %d failed " + "with %d (should have been %d)\n", + t, maj_stat, expected_error); + _gssapi_msg_order_destroy(&o); + krb5_storage_free(sp); + return 1; + } + + _gssapi_msg_order_destroy(&o); + krb5_storage_free(sp); + + return 0; +} + +struct { + OM_uint32 flags; + OM_uint32 *pattern; + int pattern_len; + OM_uint32 error_code; + OM_uint32 start_seq; +} pl[] = { + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern1, + sizeof(pattern1)/sizeof(pattern1[0]), + 0 + }, + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern2, + sizeof(pattern2)/sizeof(pattern2[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern3, + sizeof(pattern3)/sizeof(pattern3[0]), + GSS_S_DUPLICATE_TOKEN + }, + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern4, + sizeof(pattern4)/sizeof(pattern4[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern5, + sizeof(pattern5)/sizeof(pattern5[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern6, + sizeof(pattern6)/sizeof(pattern6[0]), + GSS_S_COMPLETE + }, + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern7, + sizeof(pattern7)/sizeof(pattern7[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG, + pattern8, + sizeof(pattern8)/sizeof(pattern8[0]), + GSS_S_COMPLETE, + 4294967293U + }, + { + 0, + pattern1, + sizeof(pattern1)/sizeof(pattern1[0]), + GSS_S_COMPLETE + }, + { + 0, + pattern2, + sizeof(pattern2)/sizeof(pattern2[0]), + GSS_S_COMPLETE + }, + { + 0, + pattern3, + sizeof(pattern3)/sizeof(pattern3[0]), + GSS_S_COMPLETE + }, + { + 0, + pattern4, + sizeof(pattern4)/sizeof(pattern4[0]), + GSS_S_COMPLETE + }, + { + 0, + pattern5, + sizeof(pattern5)/sizeof(pattern5[0]), + GSS_S_COMPLETE + }, + { + 0, + pattern6, + sizeof(pattern6)/sizeof(pattern6[0]), + GSS_S_COMPLETE + }, + { + 0, + pattern7, + sizeof(pattern7)/sizeof(pattern7[0]), + GSS_S_COMPLETE + }, + { + 0, + pattern8, + sizeof(pattern8)/sizeof(pattern8[0]), + GSS_S_COMPLETE, + 4294967293U + + }, + { + GSS_C_REPLAY_FLAG, + pattern1, + sizeof(pattern1)/sizeof(pattern1[0]), + GSS_S_COMPLETE + }, + { + GSS_C_REPLAY_FLAG, + pattern2, + sizeof(pattern2)/sizeof(pattern2[0]), + GSS_S_COMPLETE + }, + { + GSS_C_REPLAY_FLAG, + pattern3, + sizeof(pattern3)/sizeof(pattern3[0]), + GSS_S_DUPLICATE_TOKEN + }, + { + GSS_C_REPLAY_FLAG, + pattern4, + sizeof(pattern4)/sizeof(pattern4[0]), + GSS_S_COMPLETE + }, + { + GSS_C_REPLAY_FLAG, + pattern5, + sizeof(pattern5)/sizeof(pattern5[0]), + 0 + }, + { + GSS_C_REPLAY_FLAG, + pattern6, + sizeof(pattern6)/sizeof(pattern6[0]), + GSS_S_COMPLETE + }, + { + GSS_C_REPLAY_FLAG, + pattern7, + sizeof(pattern7)/sizeof(pattern7[0]), + GSS_S_COMPLETE + }, + { + GSS_C_SEQUENCE_FLAG, + pattern8, + sizeof(pattern8)/sizeof(pattern8[0]), + GSS_S_COMPLETE, + 4294967293U + }, + { + GSS_C_SEQUENCE_FLAG, + pattern1, + sizeof(pattern1)/sizeof(pattern1[0]), + 0 + }, + { + GSS_C_SEQUENCE_FLAG, + pattern2, + sizeof(pattern2)/sizeof(pattern2[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_SEQUENCE_FLAG, + pattern3, + sizeof(pattern3)/sizeof(pattern3[0]), + GSS_S_DUPLICATE_TOKEN + }, + { + GSS_C_SEQUENCE_FLAG, + pattern4, + sizeof(pattern4)/sizeof(pattern4[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_SEQUENCE_FLAG, + pattern5, + sizeof(pattern5)/sizeof(pattern5[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_SEQUENCE_FLAG, + pattern6, + sizeof(pattern6)/sizeof(pattern6[0]), + GSS_S_COMPLETE + }, + { + GSS_C_SEQUENCE_FLAG, + pattern7, + sizeof(pattern7)/sizeof(pattern7[0]), + GSS_S_GAP_TOKEN + }, + { + GSS_C_REPLAY_FLAG, + pattern8, + sizeof(pattern8)/sizeof(pattern8[0]), + GSS_S_COMPLETE, + 4294967293U + } +}; + +int +main(int argc, char **argv) +{ + int i, failed = 0; + + for (i = 0; i < sizeof(pl)/sizeof(pl[0]); i++) { + if (test_seq(i, + pl[i].flags, + pl[i].start_seq, + pl[i].pattern, + pl[i].pattern_len, + pl[i].error_code)) + failed++; + } + if (failed) + printf("FAILED %d tests\n", failed); + return failed != 0; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/ticket_flags.c b/third_party/heimdal/lib/gssapi/krb5/ticket_flags.c new file mode 100644 index 0000000..df5f11d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/ticket_flags.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 +_gsskrb5_get_tkt_flags(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + OM_uint32 *tkt_flags) +{ + if (ctx == NULL) { + *minor_status = EINVAL; + return GSS_S_NO_CONTEXT; + } + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (ctx->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = EINVAL; + return GSS_S_BAD_MECH; + } + + *tkt_flags = TicketFlags2int(ctx->ticket->ticket.flags); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/unwrap.c b/third_party/heimdal/lib/gssapi/krb5/unwrap.c new file mode 100644 index 0000000..6461369 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/unwrap.c @@ -0,0 +1,468 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +#ifdef HEIM_WEAK_CRYPTO + +static OM_uint32 +unwrap_des + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state, + krb5_keyblock *key + ) +{ + u_char *p, *seq; + size_t len; + EVP_MD_CTX *md5; + u_char hash[16]; + EVP_CIPHER_CTX des_ctx; + DES_key_schedule schedule; + DES_cblock deskey; + DES_cblock zero; + size_t i; + uint32_t seq_number; + size_t padlength; + OM_uint32 ret; + int cstate; + int cmp; + int token_len; + + if (IS_DCE_STYLE(context_handle)) { + token_len = 22 + 8 + 15; /* 45 */ + if (input_message_buffer->length < token_len) + return GSS_S_BAD_MECH; + } else { + token_len = input_message_buffer->length; + } + + p = input_message_buffer->value; + ret = _gsskrb5_verify_header (&p, + token_len, + "\x02\x01", + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + len = (p - (u_char *)input_message_buffer->value) + + 22 + 8; + if (input_message_buffer->length < len) + return GSS_S_BAD_MECH; + + if (memcmp (p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\x00\x00", 2) == 0) { + cstate = 1; + } else if (memcmp (p, "\xFF\xFF", 2) == 0) { + cstate = 0; + } else + return GSS_S_BAD_MIC; + p += 2; + if(conf_state != NULL) + *conf_state = cstate; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 2; + p += 16; + + len = p - (u_char *)input_message_buffer->value; + + if(cstate) { + /* decrypt data */ + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + memset (&zero, 0, sizeof(zero)); + + for (i = 0; i < sizeof(deskey); ++i) + deskey[i] ^= 0xf0; + + + EVP_CIPHER_CTX_init(&des_ctx); + EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0); + EVP_Cipher(&des_ctx, p, p, input_message_buffer->length - len); + EVP_CIPHER_CTX_cleanup(&des_ctx); + + memset (&deskey, 0, sizeof(deskey)); + } + + if (IS_DCE_STYLE(context_handle)) { + padlength = 0; + } else { + /* check pad */ + ret = _gssapi_verify_pad(input_message_buffer, + input_message_buffer->length - len - 8, + &padlength); + if (ret) + return ret; + } + + md5 = EVP_MD_CTX_create(); + EVP_DigestInit_ex(md5, EVP_md5(), NULL); + EVP_DigestUpdate(md5, p - 24, 8); + EVP_DigestUpdate(md5, p, input_message_buffer->length - len); + EVP_DigestFinal_ex(md5, hash, NULL); + EVP_MD_CTX_destroy(md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + DES_set_key_unchecked (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + if (ct_memcmp (p - 8, hash, 8) != 0) { + memset_s(&deskey, sizeof(deskey), 0, sizeof(deskey)); + memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); + return GSS_S_BAD_MIC; + } + + /* verify sequence number */ + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + p -= 16; + + EVP_CIPHER_CTX_init(&des_ctx); + EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); + EVP_Cipher(&des_ctx, p, p, 8); + EVP_CIPHER_CTX_cleanup(&des_ctx); + + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + + seq = p; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + if (cmp != 0) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + /* copy out data */ + + output_message_buffer->length = input_message_buffer->length + - len - padlength - 8; + output_message_buffer->value = malloc(output_message_buffer->length); + if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) + return GSS_S_FAILURE; + if (output_message_buffer->value != NULL) + memcpy (output_message_buffer->value, + p + 24, + output_message_buffer->length); + return GSS_S_COMPLETE; +} +#endif + +static OM_uint32 +unwrap_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state, + krb5_keyblock *key + ) +{ + u_char *p; + size_t len; + u_char *seq; + krb5_data seq_data; + u_char cksum[20]; + uint32_t seq_number; + size_t padlength; + OM_uint32 ret; + int cstate; + krb5_crypto crypto; + Checksum csum; + int cmp; + int token_len; + + if (IS_DCE_STYLE(context_handle)) { + token_len = 34 + 8 + 15; /* 57 */ + if (input_message_buffer->length < token_len) + return GSS_S_BAD_MECH; + } else { + token_len = input_message_buffer->length; + } + + p = input_message_buffer->value; + ret = _gsskrb5_verify_header (&p, + token_len, + "\x02\x01", + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + len = (p - (u_char *)input_message_buffer->value) + + 34 + 8; + if (input_message_buffer->length < len) + return GSS_S_BAD_MECH; + + if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ + return GSS_S_BAD_SIG; + p += 2; + if (ct_memcmp (p, "\x02\x00", 2) == 0) { + cstate = 1; + } else if (ct_memcmp (p, "\xff\xff", 2) == 0) { + cstate = 0; + } else + return GSS_S_BAD_MIC; + p += 2; + if(conf_state != NULL) + *conf_state = cstate; + if (ct_memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 2; + p += 28; + + len = p - (u_char *)input_message_buffer->value; + + if(cstate) { + /* decrypt data */ + krb5_data tmp; + + ret = krb5_crypto_init(context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, + p, input_message_buffer->length - len, &tmp); + krb5_crypto_destroy(context, crypto); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + assert (tmp.length == input_message_buffer->length - len); + + memcpy (p, tmp.data, tmp.length); + krb5_data_free(&tmp); + } + + if (IS_DCE_STYLE(context_handle)) { + padlength = 0; + } else { + /* check pad */ + ret = _gssapi_verify_pad(input_message_buffer, + input_message_buffer->length - len - 8, + &padlength); + if (ret) + return ret; + } + + /* verify sequence number */ + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + p -= 28; + + ret = krb5_crypto_init(context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret) { + *minor_status = ret; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_FAILURE; + } + { + DES_cblock ivec; + + memcpy(&ivec, p + 8, 8); + ret = krb5_decrypt_ivec (context, + crypto, + KRB5_KU_USAGE_SEQ, + p, 8, &seq_data, + &ivec); + } + krb5_crypto_destroy (context, crypto); + if (ret) { + *minor_status = ret; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_FAILURE; + } + if (seq_data.length != 8) { + krb5_data_free (&seq_data); + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + seq = seq_data.data; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + krb5_data_free (&seq_data); + if (cmp != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + /* verify checksum */ + + memcpy (cksum, p + 8, 20); + + memcpy (p + 20, p - 8, 8); + + csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; + csum.checksum.length = 20; + csum.checksum.data = cksum; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_verify_checksum (context, crypto, + KRB5_KU_USAGE_SIGN, + p + 20, + input_message_buffer->length - len + 8, + &csum); + krb5_crypto_destroy (context, crypto); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* copy out data */ + + output_message_buffer->length = input_message_buffer->length + - len - padlength - 8; + output_message_buffer->value = malloc(output_message_buffer->length); + if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) + return GSS_S_FAILURE; + if (output_message_buffer->value != NULL) + memcpy (output_message_buffer->value, + p + 36, + output_message_buffer->length); + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + krb5_keyblock *key; + krb5_context context; + OM_uint32 ret; + gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; + + output_message_buffer->value = NULL; + output_message_buffer->length = 0; + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + GSSAPI_KRB5_INIT (&context); + + if (ctx->more_flags & IS_CFX) + return _gssapi_unwrap_cfx (minor_status, ctx, context, + input_message_buffer, output_message_buffer, + conf_state, qop_state); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + *minor_status = 0; + + switch (key->keytype) { + case KRB5_ENCTYPE_DES_CBC_CRC : + case KRB5_ENCTYPE_DES_CBC_MD4 : + case KRB5_ENCTYPE_DES_CBC_MD5 : +#ifdef HEIM_WEAK_CRYPTO + ret = unwrap_des (minor_status, ctx, + input_message_buffer, output_message_buffer, + conf_state, qop_state, key); +#else + ret = GSS_S_FAILURE; +#endif + break; + case KRB5_ENCTYPE_DES3_CBC_MD5 : + case KRB5_ENCTYPE_DES3_CBC_SHA1 : + ret = unwrap_des3 (minor_status, ctx, context, + input_message_buffer, output_message_buffer, + conf_state, qop_state, key); + break; + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: + ret = _gssapi_unwrap_arcfour (minor_status, ctx, context, + input_message_buffer, output_message_buffer, + conf_state, qop_state, key); + break; + default : + abort(); + break; + } + krb5_free_keyblock (context, key); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/verify_mic.c b/third_party/heimdal/lib/gssapi/krb5/verify_mic.c new file mode 100644 index 0000000..7070f3d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/verify_mic.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +#ifdef HEIM_WEAK_CRYPTO + +static OM_uint32 +verify_mic_des + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + krb5_keyblock *key, + const char *type + ) +{ + u_char *p; + EVP_MD_CTX *md5; + u_char hash[16], *seq; + DES_key_schedule schedule; + EVP_CIPHER_CTX des_ctx; + DES_cblock zero; + DES_cblock deskey; + uint32_t seq_number; + OM_uint32 ret; + int cmp; + + p = token_buffer->value; + ret = _gsskrb5_verify_header (&p, + token_buffer->length, + type, + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + if (memcmp(p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + p += 16; + + /* verify checksum */ + md5 = EVP_MD_CTX_create(); + EVP_DigestInit_ex(md5, EVP_md5(), NULL); + EVP_DigestUpdate(md5, p - 24, 8); + EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length); + EVP_DigestFinal_ex(md5, hash, NULL); + EVP_MD_CTX_destroy(md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + + DES_set_key_unchecked (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + if (ct_memcmp (p - 8, hash, 8) != 0) { + memset_s(deskey, sizeof(deskey), 0, sizeof(deskey)); + memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); + return GSS_S_BAD_MIC; + } + + /* verify sequence number */ + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + p -= 16; + + EVP_CIPHER_CTX_init(&des_ctx); + EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); + EVP_Cipher(&des_ctx, p, p, 8); + EVP_CIPHER_CTX_cleanup(&des_ctx); + + memset_s(deskey, sizeof(deskey), 0, sizeof(deskey)); + memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); + + seq = p; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + if (cmp != 0) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + return GSS_S_COMPLETE; +} +#endif + +static OM_uint32 +verify_mic_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + krb5_context context, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + krb5_keyblock *key, + const char *type + ) +{ + u_char *p; + u_char *seq; + uint32_t seq_number; + OM_uint32 ret; + krb5_crypto crypto; + krb5_data seq_data; + int cmp, docompat; + Checksum csum; + char *tmp; + char ivec[8]; + + p = token_buffer->value; + ret = _gsskrb5_verify_header (&p, + token_buffer->length, + type, + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */ + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + + ret = krb5_crypto_init(context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret){ + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* verify sequence number */ + docompat = 0; +retry: + if (docompat) + memset(ivec, 0, 8); + else + memcpy(ivec, p + 8, 8); + + ret = krb5_decrypt_ivec (context, + crypto, + KRB5_KU_USAGE_SEQ, + p, 8, &seq_data, ivec); + if (ret) { + if (docompat++) { + krb5_crypto_destroy (context, crypto); + *minor_status = ret; + return GSS_S_FAILURE; + } else + goto retry; + } + + if (seq_data.length != 8) { + krb5_data_free (&seq_data); + if (docompat++) { + krb5_crypto_destroy (context, crypto); + return GSS_S_BAD_MIC; + } else + goto retry; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + seq = seq_data.data; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + krb5_data_free (&seq_data); + if (cmp != 0) { + krb5_crypto_destroy (context, crypto); + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + krb5_crypto_destroy (context, crypto); + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + /* verify checksum */ + + tmp = malloc (message_buffer->length + 8); + if (tmp == NULL) { + krb5_crypto_destroy (context, crypto); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy (tmp, p - 8, 8); + memcpy (tmp + 8, message_buffer->value, message_buffer->length); + + csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; + csum.checksum.length = 20; + csum.checksum.data = p + 8; + + krb5_crypto_destroy (context, crypto); + ret = krb5_crypto_init(context, key, + ETYPE_DES3_CBC_SHA1, &crypto); + if (ret == 0) + ret = krb5_verify_checksum(context, crypto, + KRB5_KU_USAGE_SIGN, + tmp, message_buffer->length + 8, + &csum); + free (tmp); + if (ret) { + krb5_crypto_destroy (context, crypto); + *minor_status = ret; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + krb5_crypto_destroy (context, crypto); + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_verify_mic_internal + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + const char * type + ) +{ + krb5_keyblock *key; + OM_uint32 ret; + + if (ctx->more_flags & IS_CFX) + return _gssapi_verify_mic_cfx (minor_status, ctx, + context, message_buffer, token_buffer, + qop_state); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + *minor_status = 0; + + switch (key->keytype) { + case KRB5_ENCTYPE_DES_CBC_CRC : + case KRB5_ENCTYPE_DES_CBC_MD4 : + case KRB5_ENCTYPE_DES_CBC_MD5 : +#ifdef HEIM_WEAK_CRYPTO + ret = verify_mic_des (minor_status, ctx, context, + message_buffer, token_buffer, qop_state, key, + type); +#else + ret = GSS_S_FAILURE; +#endif + break; + case KRB5_ENCTYPE_DES3_CBC_MD5 : + case KRB5_ENCTYPE_DES3_CBC_SHA1 : + ret = verify_mic_des3 (minor_status, ctx, context, + message_buffer, token_buffer, qop_state, key, + type); + break; + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: + ret = _gssapi_verify_mic_arcfour (minor_status, ctx, + context, + message_buffer, token_buffer, + qop_state, key, type); + break; + default : + abort(); + } + krb5_free_keyblock (context, key); + + return ret; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_verify_mic + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + krb5_context context; + OM_uint32 ret; + + GSSAPI_KRB5_INIT (&context); + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + ret = _gsskrb5_verify_mic_internal(minor_status, + (gsskrb5_ctx)context_handle, + context, + message_buffer, token_buffer, + qop_state, (void *)(intptr_t)"\x01\x01"); + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/krb5/wrap.c b/third_party/heimdal/lib/gssapi/krb5/wrap.c new file mode 100644 index 0000000..481e303 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/krb5/wrap.c @@ -0,0 +1,592 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +/* + * Return initiator subkey, or if that doesn't exists, the subkey. + */ + +krb5_error_code +_gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx, + krb5_context context, + krb5_keyblock **key) +{ + krb5_error_code ret; + *key = NULL; + + if (ctx->more_flags & LOCAL) { + ret = krb5_auth_con_getlocalsubkey(context, + ctx->auth_context, + key); + } else { + ret = krb5_auth_con_getremotesubkey(context, + ctx->auth_context, + key); + } + if (ret == 0 && *key == NULL) + ret = krb5_auth_con_getkey(context, + ctx->auth_context, + key); + if (ret == 0 && *key == NULL) { + krb5_set_error_message(context, 0, "No initiator subkey available"); + return GSS_KRB5_S_KG_NO_SUBKEY; + } + return ret; +} + +krb5_error_code +_gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx, + krb5_context context, + krb5_keyblock **key) +{ + krb5_error_code ret; + *key = NULL; + + if (ctx->more_flags & LOCAL) { + ret = krb5_auth_con_getremotesubkey(context, + ctx->auth_context, + key); + } else { + ret = krb5_auth_con_getlocalsubkey(context, + ctx->auth_context, + key); + } + if (ret == 0 && *key == NULL) { + krb5_set_error_message(context, 0, "No acceptor subkey available"); + return GSS_KRB5_S_KG_NO_SUBKEY; + } + return ret; +} + +OM_uint32 +_gsskrb5i_get_token_key(const gsskrb5_ctx ctx, + krb5_context context, + krb5_keyblock **key) +{ + _gsskrb5i_get_acceptor_subkey(ctx, context, key); + if(*key == NULL) { + /* + * Only use the initiator subkey or ticket session key if an + * acceptor subkey was not required. + */ + if ((ctx->more_flags & ACCEPTOR_SUBKEY) == 0) + _gsskrb5i_get_initiator_subkey(ctx, context, key); + } + if (*key == NULL) { + krb5_set_error_message(context, 0, "No token key available"); + return GSS_KRB5_S_KG_NO_SUBKEY; + } + return 0; +} + +static OM_uint32 +sub_wrap_size ( + OM_uint32 req_output_size, + OM_uint32 * max_input_size, + int blocksize, + int extrasize + ) +{ + size_t len, total_len; + + len = 8 + req_output_size + blocksize + extrasize; + + _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + total_len -= req_output_size; /* token length */ + if (total_len < req_output_size) { + *max_input_size = (req_output_size - total_len); + (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); + } else { + *max_input_size = 0; + } + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_wrap_size_limit ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ) +{ + krb5_context context; + krb5_keyblock *key; + OM_uint32 ret; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + + GSSAPI_KRB5_INIT (&context); + + if (ctx->more_flags & IS_CFX) + return _gssapi_wrap_size_cfx(minor_status, ctx, context, + conf_req_flag, qop_req, + req_output_size, max_input_size); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + switch (key->keytype) { + case KRB5_ENCTYPE_DES_CBC_CRC : + case KRB5_ENCTYPE_DES_CBC_MD4 : + case KRB5_ENCTYPE_DES_CBC_MD5 : +#ifdef HEIM_WEAK_CRYPTO + ret = sub_wrap_size(req_output_size, max_input_size, 8, 22); +#else + ret = GSS_S_FAILURE; +#endif + break; + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: + ret = _gssapi_wrap_size_arcfour(minor_status, ctx, context, + conf_req_flag, qop_req, + req_output_size, max_input_size, key); + break; + case KRB5_ENCTYPE_DES3_CBC_MD5 : + case KRB5_ENCTYPE_DES3_CBC_SHA1 : + ret = sub_wrap_size(req_output_size, max_input_size, 8, 34); + break; + default : + abort(); + break; + } + krb5_free_keyblock (context, key); + *minor_status = 0; + return ret; +} + +#ifdef HEIM_WEAK_CRYPTO + +static OM_uint32 +wrap_des + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer, + krb5_keyblock *key + ) +{ + u_char *p; + EVP_MD_CTX *md5; + u_char hash[16]; + DES_key_schedule schedule; + EVP_CIPHER_CTX des_ctx; + DES_cblock deskey; + DES_cblock zero; + size_t i; + int32_t seq_number; + size_t len, total_len, padlength, datalen; + + if (IS_DCE_STYLE(ctx)) { + padlength = 0; + datalen = input_message_buffer->length; + len = 22 + 8; + _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); + total_len += datalen; + datalen += 8; + } else { + padlength = 8 - (input_message_buffer->length % 8); + datalen = input_message_buffer->length + padlength + 8; + len = datalen + 22; + _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); + } + + output_message_buffer->length = total_len; + output_message_buffer->value = malloc (total_len); + if (output_message_buffer->value == NULL) { + output_message_buffer->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(output_message_buffer->value, + len, + "\x02\x01", /* TOK_ID */ + GSS_KRB5_MECHANISM); + + /* SGN_ALG */ + memcpy (p, "\x00\x00", 2); + p += 2; + /* SEAL_ALG */ + if(conf_req_flag) + memcpy (p, "\x00\x00", 2); + else + memcpy (p, "\xff\xff", 2); + p += 2; + /* Filler */ + memcpy (p, "\xff\xff", 2); + p += 2; + + /* fill in later */ + memset (p, 0, 16); + p += 16; + + /* confounder + data + pad */ + krb5_generate_random_block(p, 8); + memcpy (p + 8, input_message_buffer->value, + input_message_buffer->length); + memset (p + 8 + input_message_buffer->length, padlength, padlength); + + /* checksum */ + md5 = EVP_MD_CTX_create(); + EVP_DigestInit_ex(md5, EVP_md5(), NULL); + EVP_DigestUpdate(md5, p - 24, 8); + EVP_DigestUpdate(md5, p, datalen); + EVP_DigestFinal_ex(md5, hash, NULL); + EVP_MD_CTX_destroy(md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + DES_set_key_unchecked (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + memcpy (p - 8, hash, 8); + + /* sequence number */ + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber (context, + ctx->auth_context, + &seq_number); + + p -= 16; + p[0] = (seq_number >> 0) & 0xFF; + p[1] = (seq_number >> 8) & 0xFF; + p[2] = (seq_number >> 16) & 0xFF; + p[3] = (seq_number >> 24) & 0xFF; + memset (p + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + EVP_CIPHER_CTX_init(&des_ctx); + EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); + EVP_Cipher(&des_ctx, p, p, 8); + EVP_CIPHER_CTX_cleanup(&des_ctx); + + krb5_auth_con_setlocalseqnumber (context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* encrypt the data */ + p += 16; + + if(conf_req_flag) { + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + + for (i = 0; i < sizeof(deskey); ++i) + deskey[i] ^= 0xf0; + + EVP_CIPHER_CTX_init(&des_ctx); + EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 1); + EVP_Cipher(&des_ctx, p, p, datalen); + EVP_CIPHER_CTX_cleanup(&des_ctx); + } + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + + if(conf_state != NULL) + *conf_state = conf_req_flag; + *minor_status = 0; + return GSS_S_COMPLETE; +} + +#endif + +static OM_uint32 +wrap_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer, + krb5_keyblock *key + ) +{ + u_char *p; + u_char seq[8]; + int32_t seq_number; + size_t len, total_len, padlength, datalen; + uint32_t ret; + krb5_crypto crypto; + Checksum cksum; + krb5_data encdata; + + if (IS_DCE_STYLE(ctx)) { + padlength = 0; + datalen = input_message_buffer->length; + len = 34 + 8; + _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); + total_len += datalen; + datalen += 8; + } else { + padlength = 8 - (input_message_buffer->length % 8); + datalen = input_message_buffer->length + padlength + 8; + len = datalen + 34; + _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); + } + + output_message_buffer->length = total_len; + output_message_buffer->value = malloc (total_len); + if (output_message_buffer->value == NULL) { + output_message_buffer->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(output_message_buffer->value, + len, + "\x02\x01", /* TOK_ID */ + GSS_KRB5_MECHANISM); + + /* SGN_ALG */ + memcpy (p, "\x04\x00", 2); /* HMAC SHA1 DES3-KD */ + p += 2; + /* SEAL_ALG */ + if(conf_req_flag) + memcpy (p, "\x02\x00", 2); /* DES3-KD */ + else + memcpy (p, "\xff\xff", 2); + p += 2; + /* Filler */ + memcpy (p, "\xff\xff", 2); + p += 2; + + /* calculate checksum (the above + confounder + data + pad) */ + + memcpy (p + 20, p - 8, 8); + krb5_generate_random_block(p + 28, 8); + memcpy (p + 28 + 8, input_message_buffer->value, + input_message_buffer->length); + memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength); + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_create_checksum (context, + crypto, + KRB5_KU_USAGE_SIGN, + 0, + p + 20, + datalen + 8, + &cksum); + krb5_crypto_destroy (context, crypto); + if (ret) { + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* zero out SND_SEQ + SGN_CKSUM in case */ + memset (p, 0, 28); + + memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); + free_Checksum (&cksum); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + /* sequence number */ + krb5_auth_con_getlocalseqnumber (context, + ctx->auth_context, + &seq_number); + + seq[0] = (seq_number >> 0) & 0xFF; + seq[1] = (seq_number >> 8) & 0xFF; + seq[2] = (seq_number >> 16) & 0xFF; + seq[3] = (seq_number >> 24) & 0xFF; + memset (seq + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + + ret = krb5_crypto_init(context, key, ETYPE_DES3_CBC_NONE, + &crypto); + if (ret) { + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + { + DES_cblock ivec; + + memcpy (&ivec, p + 8, 8); + ret = krb5_encrypt_ivec (context, + crypto, + KRB5_KU_USAGE_SEQ, + seq, 8, &encdata, + &ivec); + } + krb5_crypto_destroy (context, crypto); + if (ret) { + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + assert (encdata.length == 8); + + memcpy (p, encdata.data, encdata.length); + krb5_data_free (&encdata); + + krb5_auth_con_setlocalseqnumber (context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* encrypt the data */ + p += 28; + + if(conf_req_flag) { + krb5_data tmp; + + ret = krb5_crypto_init(context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret) { + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + ret = krb5_encrypt(context, crypto, KRB5_KU_USAGE_SEAL, + p, datalen, &tmp); + krb5_crypto_destroy(context, crypto); + if (ret) { + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + assert (tmp.length == datalen); + + memcpy (p, tmp.data, datalen); + krb5_data_free(&tmp); + } + if(conf_state != NULL) + *conf_state = conf_req_flag; + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gsskrb5_wrap + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + krb5_context context; + krb5_keyblock *key; + OM_uint32 ret; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + + output_message_buffer->value = NULL; + output_message_buffer->length = 0; + + GSSAPI_KRB5_INIT (&context); + + if (ctx->more_flags & IS_CFX) + return _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag, + input_message_buffer, conf_state, + output_message_buffer); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, context, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + switch (key->keytype) { + case KRB5_ENCTYPE_DES_CBC_CRC : + case KRB5_ENCTYPE_DES_CBC_MD4 : + case KRB5_ENCTYPE_DES_CBC_MD5 : +#ifdef HEIM_WEAK_CRYPTO + ret = wrap_des (minor_status, ctx, context, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, key); +#else + ret = GSS_S_FAILURE; +#endif + break; + case KRB5_ENCTYPE_DES3_CBC_MD5 : + case KRB5_ENCTYPE_DES3_CBC_SHA1 : + ret = wrap_des3 (minor_status, ctx, context, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, key); + break; + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: + case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: + ret = _gssapi_wrap_arcfour (minor_status, ctx, context, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, key); + break; + default : + abort(); + break; + } + krb5_free_keyblock (context, key); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/libgssapi-exports.def b/third_party/heimdal/lib/gssapi/libgssapi-exports.def new file mode 100644 index 0000000..6077c8e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/libgssapi-exports.def @@ -0,0 +1,203 @@ +EXPORTS + __gss_c_nt_anonymous_oid_desc DATA + __gss_c_nt_composite_export_oid_desc DATA + __gss_c_nt_export_name_oid_desc DATA + __gss_c_nt_hostbased_service_oid_desc DATA + __gss_c_nt_hostbased_service_x_oid_desc DATA + __gss_c_nt_machine_uid_name_oid_desc DATA + __gss_c_nt_string_uid_name_oid_desc DATA + __gss_c_nt_user_name_oid_desc DATA + __gss_krb5_nt_principal_name_oid_desc DATA + __gss_c_attr_stream_sizes_oid_desc DATA + __gss_c_attr_local_login_user DATA + gss_accept_sec_context + gss_acquire_cred + gss_acquire_cred_impersonate_name + gss_acquire_cred_from + gss_acquire_cred_with_password + gss_add_buffer_set_member + gss_add_cred + gss_add_cred_from + gss_add_cred_with_password + gss_add_oid_set_member + gss_authorize_localname + gss_canonicalize_name + gss_compare_name + gss_context_query_attributes + gss_context_time + gss_create_empty_buffer_set + gss_create_empty_oid_set + gss_decapsulate_token + gss_delete_name_attribute + gss_delete_sec_context + gss_display_mech_attr + gss_display_name + gss_display_name_ext + gss_display_status + gss_duplicate_name + gss_duplicate_oid + gss_duplicate_oid_set + gss_encapsulate_token + gss_export_cred + gss_export_name + gss_export_name_composite + gss_export_sec_context + gss_get_mic + gss_get_neg_mechs + gss_get_name_attribute + gss_import_cred + gss_import_name + gss_import_sec_context + gss_indicate_mechs + gss_indicate_mechs_by_attrs + gss_init_sec_context + gss_inquire_attrs_for_mech + gss_inquire_context + gss_inquire_cred + gss_inquire_cred_by_mech + gss_inquire_cred_by_oid + gss_inquire_mech_for_saslname + gss_inquire_mechs_for_name + gss_inquire_name + gss_inquire_names_for_mech + gss_inquire_saslname_for_mech + gss_inquire_sec_context_by_oid ;! + gss_krb5_ccache_name + gss_krb5_copy_ccache + gss_krb5_export_lucid_sec_context + gss_krb5_free_lucid_sec_context + gss_krb5_get_tkt_flags + gss_krb5_import_cred + gss_krb5_set_allowable_enctypes + gss_localname + gss_mg_collect_error + gss_mo_get + gss_mo_set + gss_mo_list + gss_mo_name + gss_name_to_oid + gss_oid_to_name + gss_oid_equal + gss_oid_to_str + gss_pname_to_uid + gss_process_context_token + gss_pseudo_random + gss_release_buffer + gss_release_buffer_set + gss_release_cred + gss_release_iov_buffer + gss_release_name + gss_release_oid + gss_release_oid_set + gss_seal + gss_set_cred_option + gss_set_name_attribute + gss_set_log_function + gss_set_neg_mechs + gss_set_sec_context_option + gss_sign + gss_store_cred + gss_store_cred_into + gss_store_cred_into2 + gss_test_oid_set_member + gss_unseal + gss_unwrap + gss_unwrap_aead + gss_unwrap_iov + gss_userok + gss_verify + gss_verify_mic + gss_wrap + gss_wrap_aead + gss_wrap_iov + gss_wrap_iov_length + gss_wrap_size_limit + gsskrb5_extract_authtime_from_sec_context + gsskrb5_extract_authz_data_from_sec_context + gsskrb5_extract_service_keyblock + gsskrb5_get_initiator_subkey + gsskrb5_get_subkey + gsskrb5_get_time_offset + gsskrb5_register_acceptor_identity + gsskrb5_set_default_realm + gsskrb5_set_dns_canonicalize + gsskrb5_set_send_to_kdc + gsskrb5_set_time_offset + krb5_gss_register_acceptor_identity + +; _gsskrb5cfx_ are really internal symbols, but export +; then now to make testing easier. + _gsskrb5cfx_wrap_length_cfx + _gssapi_wrap_size_cfx + + initialize_gk5_error_table_r ;! + + __gss_krb5_copy_ccache_x_oid_desc DATA + __gss_krb5_get_tkt_flags_x_oid_desc DATA + __gss_krb5_extract_authz_data_from_sec_context_x_oid_desc DATA + __gss_krb5_compat_des3_mic_x_oid_desc DATA + __gss_krb5_register_acceptor_identity_x_oid_desc DATA + __gss_krb5_export_lucid_context_x_oid_desc DATA + __gss_krb5_export_lucid_context_v1_x_oid_desc DATA + __gss_krb5_set_dns_canonicalize_x_oid_desc DATA + __gss_krb5_get_subkey_x_oid_desc DATA + __gss_krb5_get_initiator_subkey_x_oid_desc DATA + __gss_krb5_get_acceptor_subkey_x_oid_desc DATA + __gss_krb5_send_to_kdc_x_oid_desc DATA + __gss_krb5_get_authtime_x_oid_desc DATA + __gss_krb5_get_service_keyblock_x_oid_desc DATA + __gss_krb5_set_allowable_enctypes_x_oid_desc DATA + __gss_krb5_set_default_realm_x_oid_desc DATA + __gss_krb5_ccache_name_x_oid_desc DATA + __gss_krb5_set_time_offset_x_oid_desc DATA + __gss_krb5_get_time_offset_x_oid_desc DATA + __gss_krb5_plugin_register_x_oid_desc DATA + __gss_ntlm_get_session_key_x_oid_desc DATA + __gss_c_nt_ntlm_oid_desc DATA + __gss_c_nt_dn_oid_desc DATA + __gss_krb5_nt_principal_name_referral_oid_desc DATA + __gss_c_ntlm_avguest_oid_desc DATA + __gss_c_ntlm_v1_oid_desc DATA + __gss_c_ntlm_v2_oid_desc DATA + __gss_c_ntlm_session_key_oid_desc DATA + __gss_c_ntlm_force_v1_oid_desc DATA + __gss_krb5_cred_no_ci_flags_x_oid_desc DATA + __gss_krb5_import_cred_x_oid_desc DATA + __gss_c_ma_sasl_mech_name_oid_desc DATA + __gss_c_ma_mech_name_oid_desc DATA + __gss_c_ma_mech_description_oid_desc DATA + __gss_sasl_digest_md5_mechanism_oid_desc DATA + __gss_krb5_mechanism_oid_desc DATA + __gss_ntlm_mechanism_oid_desc DATA + __gss_spnego_mechanism_oid_desc DATA + __gss_sanon_x25519_mechanism_oid_desc DATA + __gss_c_ma_mech_concrete_oid_desc DATA + __gss_c_ma_mech_pseudo_oid_desc DATA + __gss_c_ma_mech_composite_oid_desc DATA + __gss_c_ma_mech_nego_oid_desc DATA + __gss_c_ma_mech_glue_oid_desc DATA + __gss_c_ma_not_mech_oid_desc DATA + __gss_c_ma_deprecated_oid_desc DATA + __gss_c_ma_not_dflt_mech_oid_desc DATA + __gss_c_ma_itok_framed_oid_desc DATA + __gss_c_ma_auth_init_oid_desc DATA + __gss_c_ma_auth_targ_oid_desc DATA + __gss_c_ma_auth_init_init_oid_desc DATA + __gss_c_ma_auth_targ_init_oid_desc DATA + __gss_c_ma_auth_init_anon_oid_desc DATA + __gss_c_ma_auth_targ_anon_oid_desc DATA + __gss_c_ma_deleg_cred_oid_desc DATA + __gss_c_ma_integ_prot_oid_desc DATA + __gss_c_ma_conf_prot_oid_desc DATA + __gss_c_ma_mic_oid_desc DATA + __gss_c_ma_wrap_oid_desc DATA + __gss_c_ma_prot_ready_oid_desc DATA + __gss_c_ma_replay_det_oid_desc DATA + __gss_c_ma_oos_det_oid_desc DATA + __gss_c_ma_cbindings_oid_desc DATA + __gss_c_ma_pfs_oid_desc DATA + __gss_c_ma_compress_oid_desc DATA + __gss_c_ma_ctx_trans_oid_desc DATA + __gss_c_ma_negoex_and_spnego_oid_desc DATA + __gss_c_inq_negoex_key_oid_desc DATA + __gss_c_inq_negoex_verify_key_oid_desc DATA diff --git a/third_party/heimdal/lib/gssapi/libgssapi-version.rc b/third_party/heimdal/lib/gssapi/libgssapi-version.rc new file mode 100644 index 0000000..074066f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/libgssapi-version.rc @@ -0,0 +1,36 @@ +/*********************************************************************** + * Copyright (c) 2010, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + **********************************************************************/ + +#define RC_FILE_TYPE VFT_DLL +#define RC_FILE_DESC_0409 "Generic Security Service Application Program Interface library" +#define RC_FILE_ORIG_0409 "gssapi.dll" + +#include "../../windows/version.rc" diff --git a/third_party/heimdal/lib/gssapi/mech/compat.h b/third_party/heimdal/lib/gssapi/mech/compat.h new file mode 100644 index 0000000..d23a6e9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/compat.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_saslname_for_mech_t ( + OM_uint32 *, /* minor_status */ + const gss_OID, /* desired_mech */ + gss_buffer_t, /* sasl_mech_name */ + gss_buffer_t, /* mech_name */ + gss_buffer_t /* mech_description */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_mech_for_saslname_t ( + OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* sasl_mech_name */ + gss_OID * /* mech_type */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_attrs_for_mech_t ( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech */ + gss_OID_set *, /* mech_attrs */ + gss_OID_set * /* known_mech_attrs */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_acquire_cred_with_password_t + (OM_uint32 *, /* minor_status */ + gss_const_name_t, /* desired_name */ + const gss_buffer_t, /* password */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_add_cred_with_password_t ( + OM_uint32 *, /* minor_status */ + gss_const_cred_id_t, /* input_cred_handle */ + gss_const_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + const gss_buffer_t, /* password */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 * /* acceptor_time_rec */ + ); + +/* + * API-as-SPI compatibility for compatibility with MIT mechanisms; + * native Heimdal mechanisms should not use these. + */ +struct gss_mech_compat_desc_struct { + _gss_inquire_saslname_for_mech_t *gmc_inquire_saslname_for_mech; + _gss_inquire_mech_for_saslname_t *gmc_inquire_mech_for_saslname; + _gss_inquire_attrs_for_mech_t *gmc_inquire_attrs_for_mech; + _gss_acquire_cred_with_password_t *gmc_acquire_cred_with_password; +#if 0 + _gss_add_cred_with_password_t *gmc_add_cred_with_password; +#endif +}; + diff --git a/third_party/heimdal/lib/gssapi/mech/context.c b/third_party/heimdal/lib/gssapi/mech/context.c new file mode 100644 index 0000000..83e2cef --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/context.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +#include "heim_threads.h" +#include <krb5.h> +#include "krb5_locl.h" +#include "negoex_err.h" + +struct mg_thread_ctx { + gss_OID mech; + OM_uint32 min_stat; + gss_buffer_desc min_error; + krb5_context context; +}; + +static HEIMDAL_MUTEX context_mutex = HEIMDAL_MUTEX_INITIALIZER; +static int created_key; +static HEIMDAL_thread_key context_key; + + +static void +destroy_context(void *ptr) +{ + struct mg_thread_ctx *mg = ptr; + OM_uint32 junk; + + if (mg == NULL) + return; + + gss_release_buffer(&junk, &mg->min_error); + + if (mg->context) + krb5_free_context(mg->context); + + free(mg); +} + + +static struct mg_thread_ctx * +_gss_mechglue_thread(void) +{ + struct mg_thread_ctx *ctx; + int ret = 0; + + HEIMDAL_MUTEX_lock(&context_mutex); + + if (!created_key) { + HEIMDAL_key_create(&context_key, destroy_context, ret); + if (ret) { + HEIMDAL_MUTEX_unlock(&context_mutex); + return NULL; + } + created_key = 1; + } + HEIMDAL_MUTEX_unlock(&context_mutex); + + ctx = HEIMDAL_getspecific(context_key); + if (ctx == NULL) { + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ret = krb5_init_context(&ctx->context); + if (ret) { + free(ctx); + return NULL; + } + + krb5_add_et_list(ctx->context, initialize_ngex_error_table_r); + + HEIMDAL_setspecific(context_key, ctx, ret); + if (ret) { + krb5_free_context(ctx->context); + free(ctx); + return NULL; + } + } + return ctx; +} + +krb5_context +_gss_mg_krb5_context(void) +{ + struct mg_thread_ctx *mg; + + mg = _gss_mechglue_thread(); + + return mg ? mg->context : NULL; +} + +OM_uint32 +_gss_mg_get_error(const gss_OID mech, + OM_uint32 value, + gss_buffer_t string) +{ + struct mg_thread_ctx *mg; + + mg = _gss_mechglue_thread(); + if (mg == NULL) + return GSS_S_BAD_STATUS; + + if (value != mg->min_stat || mg->min_error.length == 0) { + _mg_buffer_zero(string); + return GSS_S_BAD_STATUS; + } + string->value = malloc(mg->min_error.length); + if (string->value == NULL) { + _mg_buffer_zero(string); + return GSS_S_FAILURE; + } + string->length = mg->min_error.length; + memcpy(string->value, mg->min_error.value, mg->min_error.length); + return GSS_S_COMPLETE; +} + +void +_gss_mg_error(struct gssapi_mech_interface_desc *m, OM_uint32 min) +{ + OM_uint32 major_status, minor_status; + OM_uint32 message_content = 0; + struct mg_thread_ctx *mg; + + /* + * Mechs without gss_display_status() does + * gss_mg_collect_error() by themself. + */ + if (m->gm_display_status == NULL) + return ; + + mg = _gss_mechglue_thread(); + if (mg == NULL) + return; + + gss_release_buffer(&minor_status, &mg->min_error); + + mg->mech = &m->gm_mech_oid; + mg->min_stat = min; + + major_status = m->gm_display_status(&minor_status, + min, + GSS_C_MECH_CODE, + &m->gm_mech_oid, + &message_content, + &mg->min_error); + if (major_status != GSS_S_COMPLETE) { + _mg_buffer_zero(&mg->min_error); + } else { + _gss_mg_log(5, "_gss_mg_error: captured %.*s (%d) from underlying mech %s", + (int)mg->min_error.length, (const char *)mg->min_error.value, + (int)min, m->gm_name); + } +} + +void +gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min) +{ + gssapi_mech_interface m = __gss_get_mechanism(mech); + if (m == NULL) + return; + _gss_mg_error(m, min); +} + +OM_uint32 +gss_mg_set_error_string(gss_OID mech, + OM_uint32 maj, OM_uint32 min, + const char *fmt, ...) +{ + struct mg_thread_ctx *mg; + char *str = NULL; + OM_uint32 junk; + va_list ap; + int vasprintf_ret; + + mg = _gss_mechglue_thread(); + if (mg == NULL) + return maj; + + va_start(ap, fmt); + vasprintf_ret = vasprintf(&str, fmt, ap); + va_end(ap); + + if (vasprintf_ret >= 0 && str) { + gss_release_buffer(&junk, &mg->min_error); + + mg->mech = mech; + mg->min_stat = min; + + mg->min_error.value = str; + mg->min_error.length = strlen(str); + + _gss_mg_log(5, "gss_mg_set_error_string: %.*s (%d/%d)", + (int)mg->min_error.length, (const char *)mg->min_error.value, + (int)maj, (int)min); + } + return maj; +} + +static void *log_ctx = NULL; +static void (*log_func)(void *ctx, int level, const char *fmt, va_list) = NULL; + +void GSSAPI_LIB_CALL +gss_set_log_function(void *ctx, void (*func)(void * ctx, int level, const char *fmt, va_list)) +{ + if (log_func == NULL) { + log_func = func; + log_ctx = ctx; + } +} + +int +_gss_mg_log_level(int level) +{ + struct mg_thread_ctx *mg; + + mg = _gss_mechglue_thread(); + if (mg == NULL) + return 0; + + return _krb5_have_debug(mg->context, level); +} + +/* + * TODO: refactor logging so that it no longer depends on libkrb5 + * and can be configured independently. + */ +void +_gss_mg_log(int level, const char *fmt, ...) +{ + struct mg_thread_ctx *mg; + va_list ap; + + if (!_gss_mg_log_level(level)) + return; + + mg = _gss_mechglue_thread(); + if (mg == NULL) + return; + + if (mg->context && _krb5_have_debug(mg->context, level)) { + va_start(ap, fmt); + krb5_vlog(mg->context, heim_get_debug_dest(mg->context->hcontext), + level, fmt, ap); + va_end(ap); + } + + if (log_func) { + va_start(ap, fmt); + log_func(log_ctx, level, fmt, ap); + va_end(ap); + } +} + +void +_gss_mg_log_name(int level, + struct _gss_name *name, + gss_OID mech_type, + const char *fmt, ...) +{ + struct _gss_mechanism_name *mn = NULL; + gssapi_mech_interface m; + OM_uint32 junk; + + if (!_gss_mg_log_level(level)) + return; + + m = __gss_get_mechanism(mech_type); + if (m == NULL) + return; + + if (_gss_find_mn(&junk, name, mech_type, &mn) == GSS_S_COMPLETE) { + OM_uint32 maj_stat = GSS_S_COMPLETE; + gss_buffer_desc namebuf; + int ret; + + if (mn == NULL) { + namebuf.value = "no name"; + namebuf.length = strlen((char *)namebuf.value); + } else { + maj_stat = m->gm_display_name(&junk, mn->gmn_name, + &namebuf, NULL); + } + if (maj_stat == GSS_S_COMPLETE) { + char *str = NULL; + va_list ap; + + va_start(ap, fmt); + ret = vasprintf(&str, fmt, ap); + va_end(ap); + + if (ret >= 0 && str) + _gss_mg_log(level, "%s %.*s", str, + (int)namebuf.length, (char *)namebuf.value); + free(str); + if (mn != NULL) + gss_release_buffer(&junk, &namebuf); + } + } + +} + +void +_gss_mg_log_cred(int level, + struct _gss_cred *cred, + const char *fmt, ...) +{ + struct _gss_mechanism_cred *mc; + char *str; + va_list ap; + int ret; + + if (!_gss_mg_log_level(level)) + return; + + va_start(ap, fmt); + ret = vasprintf(&str, fmt, ap); + va_end(ap); + + if (ret >=0 && cred) { + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + _gss_mg_log(1, "%s: %s", str, mc->gmc_mech->gm_name); + } + } else { + _gss_mg_log(1, "%s: GSS_C_NO_CREDENTIAL", str); + } + free(str); +} + diff --git a/third_party/heimdal/lib/gssapi/mech/context.h b/third_party/heimdal/lib/gssapi/mech/context.h new file mode 100644 index 0000000..5029171 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/context.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/context.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id$ + */ + +#include <gssapi_mech.h> + +struct _gss_context { + gss_buffer_desc gc_input; + char *gc_free_this; + size_t gc_target_len; + size_t gc_oid_offset; + gssapi_mech_interface gc_mech; + gss_ctx_id_t gc_ctx; + uint8_t gc_initial; +}; + +#define EXPORT_CONTEXT_VERSION_MASK 0x03 +#define EXPORT_CONTEXT_FLAGS_MASK 0xfc +#define EXPORT_CONTEXT_FLAG_ACCUMULATING 0x04 +#define EXPORT_CONTEXT_FLAG_MECH_CTX 0x08 + +void +_gss_mg_error(gssapi_mech_interface, OM_uint32); + +OM_uint32 +_gss_mg_get_error(const gss_OID, OM_uint32, gss_buffer_t); diff --git a/third_party/heimdal/lib/gssapi/mech/cred.c b/third_party/heimdal/lib/gssapi/mech/cred.c new file mode 100644 index 0000000..92cc61a --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/cred.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mech_locl.h" +#include "heim_threads.h" +#include "heimbase.h" + +static OM_uint32 +release_mech_cred(OM_uint32 *minor, struct _gss_mechanism_cred *mc) +{ + OM_uint32 major; + + if (mc->gmc_mech->gm_release_cred != NULL) + major = mc->gmc_mech->gm_release_cred(minor, &mc->gmc_cred); + else + major = GSS_S_COMPLETE; + + free(mc); + + return major; +} + + +void +_gss_mg_release_cred(struct _gss_cred *cred) +{ + struct _gss_mechanism_cred *mc, *next; + OM_uint32 junk; + + HEIM_TAILQ_FOREACH_SAFE(mc, &cred->gc_mc, gmc_link, next) { + HEIM_TAILQ_REMOVE(&cred->gc_mc, mc, gmc_link); + release_mech_cred(&junk, mc); + } + gss_release_oid_set(&junk, &cred->gc_neg_mechs); + free(cred); +} + +struct _gss_cred * +_gss_mg_alloc_cred(void) +{ + struct _gss_cred *cred; + cred = calloc(1, sizeof(struct _gss_cred)); + if (cred == NULL) + return NULL; + HEIM_TAILQ_INIT(&cred->gc_mc); + + return cred; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/cred.h b/third_party/heimdal/lib/gssapi/mech/cred.h new file mode 100644 index 0000000..eed4a82 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/cred.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/cred.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id$ + */ + +struct _gss_mechanism_cred { + HEIM_TAILQ_ENTRY(_gss_mechanism_cred) gmc_link; + gssapi_mech_interface gmc_mech; /* mechanism ops for MC */ + gss_OID gmc_mech_oid; /* mechanism oid for MC */ + gss_cred_id_t gmc_cred; /* underlying MC */ +}; +HEIM_TAILQ_HEAD(_gss_mechanism_cred_list, _gss_mechanism_cred); + +struct _gss_cred { + struct _gss_mechanism_cred_list gc_mc; + gss_OID_set gc_neg_mechs; +}; + +struct _gss_cred * +_gss_mg_alloc_cred(void); + +void +_gss_mg_release_cred(struct _gss_cred *cred); + +struct _gss_mechanism_cred * +_gss_copy_cred(struct _gss_mechanism_cred *mc); + +struct _gss_mechanism_name; + +OM_uint32 +_gss_mg_add_mech_cred(OM_uint32 *minor_status, + gssapi_mech_interface m, + const struct _gss_mechanism_cred *mc, + const struct _gss_mechanism_name *mn, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_const_key_value_set_t cred_store, + struct _gss_mechanism_cred **output_cred_handle, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec); diff --git a/third_party/heimdal/lib/gssapi/mech/doxygen.c b/third_party/heimdal/lib/gssapi/mech/doxygen.c new file mode 100644 index 0000000..4ead9f1 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/doxygen.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*! @mainpage Heimdal GSS-API Library + * + * Heimdal implements the following mechanisms: + * + * - Kerberos 5 + * - SPNEGO + * - NTLM + * + * @sa + * + * - @ref gssapi_services_intro + * - @ref gssapi_mechs + * - @ref gssapi_api_INvsMN + * - The project web page: http://www.h5l.org/ + */ + +/** + * @page gssapi_services_intro Introduction to GSS-API services + * @section gssapi_services GSS-API services + * + * @subsection gssapi_services_context Context creation + * + * - delegation + * - mutual authentication + * - anonymous + * - use per message before context creation has completed + * + * return status: + * - support conf + * - support int + * + * @subsection gssapi_context_flags Context creation flags + * + * - GSS_C_DELEG_FLAG + * - GSS_C_MUTUAL_FLAG + * - GSS_C_REPLAY_FLAG + * - GSS_C_SEQUENCE_FLAG + * - GSS_C_CONF_FLAG + * - GSS_C_INTEG_FLAG + * - GSS_C_ANON_FLAG + * - GSS_C_PROT_READY_FLAG + * - GSS_C_TRANS_FLAG + * - GSS_C_DCE_STYLE + * - GSS_C_IDENTIFY_FLAG + * - GSS_C_EXTENDED_ERROR_FLAG + * - GSS_C_DELEG_POLICY_FLAG + * + * + * @subsection gssapi_services_permessage Per-message services + * + * - conf + * - int + * - message integrity + * - replay detection + * - out of sequence + * + */ + +/** + * @page gssapi_mechs_intro GSS-API mechanisms + * @section gssapi_mechs GSS-API mechanisms + * + * - Kerberos 5 - GSS_KRB5_MECHANISM + * - SPNEGO - GSS_SPNEGO_MECHANISM + * - NTLM - GSS_NTLM_MECHANISM + + */ + + +/** + * @page internalVSmechname Internal names and mechanism names + * @section gssapi_api_INvsMN Name forms + * + * There are two name representations in GSS-API: Internal form and + * Contiguous string ("flat") form. Functions gss_export_name() and + * gss_import_name() can be used to convert between the two forms. + * + * - The contiguous string form is described by an oid specificing the + * type and an octet string. A special form of the contiguous + * string form is the exported name object. The exported name + * defined for each mechanism, is something that can be stored and + * compared later. The exported name is what should be used for + * ACLs comparisons. + * + * - The Internal form is opaque to the application programmer and + * is implementation-dependent. + * + * - There is also a special form of the Internal Name (IN), and that is + * the Mechanism Name (MN). In the mechanism name all the generic + * information is stripped of and only contain the information for + * one mechanism. In GSS-API some function return MN and some + * require MN as input. Each of these function is marked up as such. + * + * @FIXME Describe relationship between import_name, canonicalize_name, + * export_name and friends. Also, update for RFC2743 language + * ("contiguous" and "flat" are gone, leaving just "exported name + * token", "internal", and "MN"). + */ + +/** @defgroup gssapi Heimdal GSS-API functions */ diff --git a/third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c new file mode 100644 index 0000000..1cb0b36 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c @@ -0,0 +1,519 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_accept_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +/* + * accumulate_token() tries to assemble a complete GSS token which may + * be fed to it in pieces. Microsoft does this when tokens are too large + * in CIFS, e.g. It may occur in other places as well. It is specified in: + * + * [MS-SPNG]: Simple and Protected GSS-API Negotiation + * Mechanism (SPNEGO) Extension + * + * https://winprotocoldoc.blob.core.windows.net/ + * productionwindowsarchives/MS-SPNG/%5bMS-SPNG%5d.pdf + * + * Sections 3.1.5.4 to 3.1.5.9. + * + * We only accumulate if we see the appropriate application tag in the + * first byte of 0x60 because in the absence of this, we cannot interpret + * the following bytes as a DER length. + * + * We only allocate an accumulating buffer if we detect that the token + * is split between multiple packets as this is the uncommon case and + * we want to optimise for the common case. If we aren't accumulating, + * we simply return success. + * + * Our return value is GSS_S_CONTINUE_NEEDED if we need more input. + * We return GSS_S_COMPLETE if we are either finished accumulating or + * if we decide that we do not understand this token. We only return + * an error if we think that we should understand the token and still + * fail to understand it. + */ + +static OM_uint32 +accumulate_token(struct _gss_context *ctx, gss_buffer_t input_token) +{ + unsigned char *p = input_token->value; + size_t len = input_token->length; + gss_buffer_t gci; + size_t l; + + /* + * Token must start with [APPLICATION 0] SEQUENCE. + * But if it doesn't assume it is DCE-STYLE Kerberos! + */ + if (!ctx->gc_target_len) { + free(ctx->gc_free_this); + ctx->gc_free_this = NULL; + _mg_buffer_zero(&ctx->gc_input); + + /* + * Let's prepare gc_input for the case where + * we aren't accumulating. + */ + + ctx->gc_input.length = len; + ctx->gc_input.value = p; + + if (len == 0) + return GSS_S_COMPLETE; + + /* Not our DER w/ a length */ + if (*p != 0x60) + return GSS_S_COMPLETE; + + if (der_get_length(p+1, len-1, &ctx->gc_target_len, &l) != 0) + return GSS_S_DEFECTIVE_TOKEN; + + _gss_mg_log(10, "gss-asc: DER length: %zu", + ctx->gc_target_len); + + ctx->gc_oid_offset = l + 1; + ctx->gc_target_len += ctx->gc_oid_offset; + + _gss_mg_log(10, "gss-asc: total length: %zu", + ctx->gc_target_len); + + if (ctx->gc_target_len == ASN1_INDEFINITE || + ctx->gc_target_len < len) + return GSS_S_DEFECTIVE_TOKEN; + + /* We've got it all, short-circuit the accumulating */ + if (ctx->gc_target_len == len) + goto done; + + _gss_mg_log(10, "gss-asc: accumulating partial token"); + + ctx->gc_input.length = 0; + ctx->gc_input.value = calloc(ctx->gc_target_len, 1); + if (!ctx->gc_input.value) + return GSS_S_FAILURE; + ctx->gc_free_this = ctx->gc_input.value; + } + + if (len == 0) + return GSS_S_DEFECTIVE_TOKEN; + + gci = &ctx->gc_input; + + if (ctx->gc_target_len > gci->length) { + if (gci->length + len > ctx->gc_target_len) { + _gss_mg_log(10, "gss-asc: accumulation exceeded " + "target length: bailing"); + return GSS_S_DEFECTIVE_TOKEN; + } + memcpy((char *)gci->value + gci->length, p, len); + gci->length += len; + } + + if (gci->length != ctx->gc_target_len) { + _gss_mg_log(10, "gss-asc: collected %zu/%zu bytes", + gci->length, ctx->gc_target_len); + return GSS_S_CONTINUE_NEEDED; + } + +done: + _gss_mg_log(10, "gss-asc: received complete %zu byte token", + ctx->gc_target_len); + ctx->gc_target_len = 0; + + return GSS_S_COMPLETE; +} + +static void +log_oid(const char *str, gss_OID mech) +{ + OM_uint32 maj, min; + gss_buffer_desc buf; + + maj = gss_oid_to_str(&min, mech, &buf); + if (maj == GSS_S_COMPLETE) { + _gss_mg_log(10, "%s: %.*s", str, (int)buf.length, + (char *)buf.value); + gss_release_buffer(&min, &buf); + } +} + +static OM_uint32 +choose_mech(struct _gss_context *ctx) +{ + gss_OID_desc mech; + gss_OID mech_oid; + unsigned char *p = ctx->gc_input.value; + size_t len = ctx->gc_input.length; + + if (len == 0) { + /* + * There is the a wierd mode of SPNEGO (in CIFS and + * SASL GSS-SPENGO where the first token is zero + * length and the acceptor returns a mech_list, lets + * hope that is what is happening now. + * + * http://msdn.microsoft.com/en-us/library/cc213114.aspx + * "NegTokenInit2 Variation for Server-Initiation" + */ + mech_oid = &__gss_spnego_mechanism_oid_desc; + goto gss_get_mechanism; + } + + p += ctx->gc_oid_offset; + len -= ctx->gc_oid_offset; + + /* + * Decode the OID for the mechanism. Simplify life by + * assuming that the OID length is less than 128 bytes. + */ + if (len < 2 || *p != 0x06) + goto bail; + if ((p[1] & 0x80) || p[1] > (len - 2)) + goto bail; + mech.length = p[1]; + p += 2; + len -= 2; + mech.elements = p; + + mech_oid = _gss_mg_support_mechanism(&mech); + if (mech_oid == GSS_C_NO_OID) + return GSS_S_COMPLETE; + +gss_get_mechanism: + /* + * If mech_oid == GSS_C_NO_OID then the mech is non-standard + * and we have to try all mechs (that we have a cred element + * for, if we have a cred). + */ + if (mech_oid != GSS_C_NO_OID) { + log_oid("mech oid", mech_oid); + ctx->gc_mech = __gss_get_mechanism(mech_oid); + if (!ctx->gc_mech) { + _gss_mg_log(10, "mechanism client used is unknown"); + return (GSS_S_BAD_MECH); + } + _gss_mg_log(10, "using mech \"%s\"", ctx->gc_mech->gm_name); + return GSS_S_COMPLETE; + } + +bail: + _gss_mg_log(10, "no mech oid found"); + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_accept_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 major_status, mech_ret_flags, junk; + gssapi_mech_interface m = NULL; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + struct _gss_cred *cred = (struct _gss_cred *) acceptor_cred_handle; + struct _gss_mechanism_cred *mc; + gss_buffer_desc defective_token_error; + gss_const_cred_id_t acceptor_mc; + gss_cred_id_t delegated_mc = GSS_C_NO_CREDENTIAL; + gss_name_t src_mn = GSS_C_NO_NAME; + gss_OID mech_ret_type = GSS_C_NO_OID; + int initial; + + defective_token_error.length = 0; + defective_token_error.value = NULL; + + *minor_status = 0; + if (src_name) + *src_name = GSS_C_NO_NAME; + if (mech_type) + *mech_type = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + _mg_buffer_zero(output_token); + + if (!*context_handle) { + ctx = calloc(sizeof(*ctx), 1); + if (!ctx) { + *minor_status = ENOMEM; + return (GSS_S_DEFECTIVE_TOKEN); + } + *context_handle = (gss_ctx_id_t)ctx; + ctx->gc_initial = 1; + } + + major_status = accumulate_token(ctx, input_token); + if (major_status != GSS_S_COMPLETE) + return major_status; + + /* + * If we get here, then we have a complete token. Please note + * that we may have a major_status of GSS_S_DEFECTIVE_TOKEN. This + * + */ + + initial = ctx->gc_initial; + ctx->gc_initial = 0; + + if (major_status == GSS_S_COMPLETE && initial) { + major_status = choose_mech(ctx); + if (major_status != GSS_S_COMPLETE) + return major_status; + } + m = ctx->gc_mech; + + if (initial && !m && acceptor_cred_handle == GSS_C_NO_CREDENTIAL) { + /* + * No header, not a standard mechanism. Try all the mechanisms + * (because default credential). + */ + struct _gss_mech_switch *ms; + + _gss_load_mech(); + acceptor_mc = GSS_C_NO_CREDENTIAL; + HEIM_TAILQ_FOREACH(ms, &_gss_mechs, gm_link) { + m = &ms->gm_mech; + mech_ret_flags = 0; + major_status = m->gm_accept_sec_context(minor_status, + &ctx->gc_ctx, + acceptor_mc, + &ctx->gc_input, + input_chan_bindings, + &src_mn, + &mech_ret_type, + output_token, + &mech_ret_flags, + time_rec, + &delegated_mc); + if (major_status == GSS_S_DEFECTIVE_TOKEN) { + /* + * Try to retain and output one error token for + * GSS_S_DEFECTIVE_TOKEN. The first one. + */ + if (output_token->length && + defective_token_error.length == 0) { + defective_token_error = *output_token; + output_token->length = 0; + output_token->value = NULL; + } + gss_release_buffer(&junk, output_token); + continue; + } + gss_release_buffer(&junk, &defective_token_error); + ctx->gc_mech = m; + goto got_one; + } + m = NULL; + acceptor_mc = GSS_C_NO_CREDENTIAL; + } else if (initial && !m) { + /* + * No header, not a standard mechanism. Try all the mechanisms + * that we have a credential element for if we have a + * non-default credential. + */ + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + m = mc->gmc_mech; + acceptor_mc = (m->gm_flags & GM_USE_MG_CRED) ? + acceptor_cred_handle : mc->gmc_cred; + mech_ret_flags = 0; + major_status = m->gm_accept_sec_context(minor_status, + &ctx->gc_ctx, + acceptor_mc, + &ctx->gc_input, + input_chan_bindings, + &src_mn, + &mech_ret_type, + output_token, + &mech_ret_flags, + time_rec, + &delegated_mc); + if (major_status == GSS_S_DEFECTIVE_TOKEN) { + if (output_token->length && + defective_token_error.length == 0) { + defective_token_error = *output_token; + output_token->length = 0; + output_token->value = NULL; + } + gss_release_buffer(&junk, output_token); + continue; + } + gss_release_buffer(&junk, &defective_token_error); + ctx->gc_mech = m; + goto got_one; + } + m = NULL; + acceptor_mc = GSS_C_NO_CREDENTIAL; + } + + if (m == NULL) { + gss_delete_sec_context(&junk, context_handle, NULL); + _gss_mg_log(10, "No mechanism accepted the non-standard initial security context token"); + *output_token = defective_token_error; + return GSS_S_BAD_MECH; + } + + if (m->gm_flags & GM_USE_MG_CRED) { + acceptor_mc = acceptor_cred_handle; + } else if (cred) { + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) + if (mc->gmc_mech == m) + break; + if (!mc) { + gss_delete_sec_context(&junk, context_handle, NULL); + _gss_mg_log(10, "gss-asc: client sent mech %s " + "but no credential was matching", + m->gm_name); + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) + _gss_mg_log(10, "gss-asc: available creds were %s", mc->gmc_mech->gm_name); + return (GSS_S_BAD_MECH); + } + acceptor_mc = mc->gmc_cred; + } else { + acceptor_mc = GSS_C_NO_CREDENTIAL; + } + + mech_ret_flags = 0; + major_status = m->gm_accept_sec_context(minor_status, + &ctx->gc_ctx, + acceptor_mc, + &ctx->gc_input, + input_chan_bindings, + &src_mn, + &mech_ret_type, + output_token, + &mech_ret_flags, + time_rec, + &delegated_mc); + +got_one: + if (major_status != GSS_S_COMPLETE && + major_status != GSS_S_CONTINUE_NEEDED) + { + _gss_mg_error(m, *minor_status); + gss_delete_sec_context(&junk, context_handle, NULL); + return (major_status); + } + + if (mech_type) + *mech_type = mech_ret_type; + + if (src_name && src_mn) { + if (ctx->gc_mech->gm_flags & GM_USE_MG_NAME) { + /* Negotiation mechanisms use mechglue names as names */ + *src_name = src_mn; + src_mn = GSS_C_NO_NAME; + } else { + /* + * Make a new name and mark it as an MN. + * + * Note that _gss_create_name() consumes `src_mn' but doesn't + * take a pointer, so it can't set it to GSS_C_NO_NAME. + */ + struct _gss_name *name = _gss_create_name(src_mn, m); + + if (!name) { + m->gm_release_name(minor_status, &src_mn); + gss_delete_sec_context(&junk, context_handle, NULL); + return (GSS_S_FAILURE); + } + *src_name = (gss_name_t) name; + src_mn = GSS_C_NO_NAME; + } + } else if (src_mn) { + if (ctx->gc_mech->gm_flags & GM_USE_MG_NAME) { + _gss_mg_release_name((struct _gss_name *)src_mn); + src_mn = GSS_C_NO_NAME; + } else { + m->gm_release_name(minor_status, &src_mn); + } + } + + if (mech_ret_flags & GSS_C_DELEG_FLAG) { + if (!delegated_cred_handle) { + if (m->gm_flags & GM_USE_MG_CRED) + gss_release_cred(minor_status, &delegated_mc); + else + m->gm_release_cred(minor_status, &delegated_mc); + mech_ret_flags &= + ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); + } else if ((m->gm_flags & GM_USE_MG_CRED) != 0) { + /* + * If credential is uses mechglue cred, assume it + * returns one too. + */ + *delegated_cred_handle = delegated_mc; + } else if (gss_oid_equal(mech_ret_type, &m->gm_mech_oid) == 0) { + /* + * If the returned mech_type is not the same + * as the mech, assume its pseudo mech type + * and the returned type is already a + * mech-glue object + */ + *delegated_cred_handle = delegated_mc; + + } else if (delegated_mc) { + struct _gss_cred *dcred; + struct _gss_mechanism_cred *dmc; + + dcred = _gss_mg_alloc_cred(); + if (!dcred) { + *minor_status = ENOMEM; + gss_delete_sec_context(&junk, context_handle, NULL); + return (GSS_S_FAILURE); + } + dmc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!dmc) { + free(dcred); + *minor_status = ENOMEM; + gss_delete_sec_context(&junk, context_handle, NULL); + return (GSS_S_FAILURE); + } + dmc->gmc_mech = m; + dmc->gmc_mech_oid = &m->gm_mech_oid; + dmc->gmc_cred = delegated_mc; + HEIM_TAILQ_INSERT_TAIL(&dcred->gc_mc, dmc, gmc_link); + + *delegated_cred_handle = (gss_cred_id_t) dcred; + } + } + + _gss_mg_log(10, "gss-asc: return %d/%d", (int)major_status, (int)*minor_status); + + if (ret_flags) + *ret_flags = mech_ret_flags; + return (major_status); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred.c new file mode 100644 index 0000000..fd92a25 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_acquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_acquire_cred(OM_uint32 *minor_status, + gss_const_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + return gss_acquire_cred_from(minor_status, + desired_name, + time_req, + desired_mechs, + cred_usage, + GSS_C_NO_CRED_STORE, + output_cred_handle, + actual_mechs, + time_rec); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_from.c b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_from.c new file mode 100644 index 0000000..5bb956c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_from.c @@ -0,0 +1,302 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * Portions Copyright (c) 2011, 2018 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_acquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +/* + * Shim for gss_acquire_cred_with_password() + */ +static const char * +find_password_in_cred_store(gss_const_key_value_set_t cred_store) +{ + size_t i; + + if (cred_store == GSS_C_NO_CRED_STORE) + return NULL; + + for (i = 0; i < cred_store->count; i++) { + if (strcmp(cred_store->elements[i].key, "password") == 0) + return cred_store->elements[i].value; + } + + return NULL; +} + +static OM_uint32 +acquire_mech_cred(OM_uint32 *minor_status, + gssapi_mech_interface m, + const struct _gss_mechanism_name *mn, + OM_uint32 time_req, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + struct _gss_mechanism_cred **out, + OM_uint32 *time_rec) +{ + OM_uint32 major_status; + struct _gss_mechanism_cred *mc; + gss_OID_set_desc mech; + const char *spassword; + + *out = NULL; + if (time_rec) + *time_rec = 0; + + mc = calloc(1, sizeof(struct _gss_mechanism_cred)); + if (mc == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + + mech.count = 1; + mech.elements = mc->gmc_mech_oid; + + if (m->gm_acquire_cred_from) { + major_status = m->gm_acquire_cred_from(minor_status, + mn ? mn->gmn_name : GSS_C_NO_NAME, + time_req, + &mech, + cred_usage, + cred_store, + &mc->gmc_cred, + NULL, + time_rec); + } else if ((cred_store == GSS_C_NO_CRED_STORE || cred_store->count == 0) && + m->gm_acquire_cred) { + major_status = m->gm_acquire_cred(minor_status, + mn ? mn->gmn_name : GSS_C_NO_NAME, + time_req, + &mech, + cred_usage, + &mc->gmc_cred, + NULL, + time_rec); + } else if (m->gm_compat && + m->gm_compat->gmc_acquire_cred_with_password && + (spassword = find_password_in_cred_store(cred_store)) != NULL) { + gss_buffer_desc password; + + password.length = strlen(spassword); + password.value = rk_UNCONST(spassword); + + /* compat glue for loadable mechanisms that implement API-as-SPI */ + major_status = m->gm_compat->gmc_acquire_cred_with_password(minor_status, + mn ? mn->gmn_name : GSS_C_NO_NAME, + &password, + time_req, + &mech, + cred_usage, + &mc->gmc_cred, + NULL, + time_rec); + } else + major_status = GSS_S_UNAVAILABLE; + + heim_assert(major_status == GSS_S_COMPLETE || mc->gmc_cred == NULL, + "gss_acquire_cred_from: mech succeeded but did not return a credential"); + + if (major_status == GSS_S_COMPLETE) + *out = mc; + else + free(mc); + + return major_status; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_acquire_cred_from(OM_uint32 *minor_status, + gss_const_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 major_status, minor; + struct _gss_name *name = (struct _gss_name *)desired_name; + gssapi_mech_interface m; + struct _gss_cred *cred = NULL; + size_t i; + OM_uint32 min_time = GSS_C_INDEFINITE; + gss_OID_set mechs = GSS_C_NO_OID_SET; + + *minor_status = 0; + if (output_cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + if (time_rec) + *time_rec = 0; + + _gss_load_mech(); + + if (desired_mechs != GSS_C_NO_OID_SET) { + int only_mg_cred_mechs = -1; + + for (i = 0; i < desired_mechs->count; i++) { + m = __gss_get_mechanism(&desired_mechs->elements[i]); + if (m != NULL) { + if ((m->gm_flags & GM_USE_MG_CRED) == 0) + only_mg_cred_mechs = 0; + else if (only_mg_cred_mechs == -1) + only_mg_cred_mechs = 1; + } + } + /* + * Now SPNEGO supports GM_USE_MG_CRED it's no longer necessary + * to specifically acquire SPNEGO credentials. If the caller + * did not specify any concrete mechanisms then we will acquire + * credentials for all of them. + */ + if (only_mg_cred_mechs == -1) { + *minor_status = 0; + major_status = GSS_S_BAD_MECH; + goto cleanup; + } else if (only_mg_cred_mechs == 0) + mechs = desired_mechs; + else + mechs = _gss_mech_oids; + } else + mechs = _gss_mech_oids; + + cred = _gss_mg_alloc_cred(); + if (cred == NULL) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto cleanup; + } + + if (actual_mechs) { + major_status = gss_create_empty_oid_set(minor_status, actual_mechs); + if (GSS_ERROR(major_status)) + goto cleanup; + } + + major_status = GSS_S_UNAVAILABLE; /* in case of no mechs */ + + for (i = 0; i < mechs->count; i++) { + struct _gss_mechanism_name *mn = NULL; + struct _gss_mechanism_cred *mc = NULL; + OM_uint32 cred_time; + + m = __gss_get_mechanism(&mechs->elements[i]); + if (m == NULL || (m->gm_flags & GM_USE_MG_CRED) != 0) + continue; + + if (desired_name != GSS_C_NO_NAME) { + major_status = _gss_find_mn(minor_status, name, + &mechs->elements[i], &mn); + if (major_status != GSS_S_COMPLETE) + continue; + } + + major_status = acquire_mech_cred(minor_status, m, mn, + time_req, cred_usage, + cred_store, &mc, &cred_time); + if (major_status != GSS_S_COMPLETE) { + if (mechs->count == 1) + _gss_mg_error(m, *minor_status); + continue; + } + + _gss_mg_log_name(10, name, &mechs->elements[i], + "gss_acquire_cred %s name: %ld/%ld", + m->gm_name, + (long)major_status, (long)*minor_status); + + HEIM_TAILQ_INSERT_TAIL(&cred->gc_mc, mc, gmc_link); + + if (cred_time < min_time) + min_time = cred_time; + if (actual_mechs != NULL) { + major_status = gss_add_oid_set_member(minor_status, + mc->gmc_mech_oid, + actual_mechs); + if (GSS_ERROR(major_status)) + goto cleanup; + } + } + + /* + * If we didn't manage to create a single credential, return + * an error. + */ + if (!HEIM_TAILQ_FIRST(&cred->gc_mc)) { + if (mechs->count > 1) { + *minor_status = 0; + major_status = GSS_S_NO_CRED; + } + heim_assert(major_status != GSS_S_COMPLETE, + "lack of credentials must result in an error"); + goto cleanup; + } + + /* add all GM_USE_MG_CRED mechs such as SPNEGO */ + if (actual_mechs != NULL) { + struct _gss_mech_switch *ms; + + HEIM_TAILQ_FOREACH(ms, &_gss_mechs, gm_link) { + m = &ms->gm_mech; + + if ((m->gm_flags & GM_USE_MG_CRED) == 0) + continue; + + major_status = gss_add_oid_set_member(minor_status, + &m->gm_mech_oid, + actual_mechs); + if (GSS_ERROR(major_status)) + goto cleanup; + } + } + + *minor_status = 0; + major_status = GSS_S_COMPLETE; + + *output_cred_handle = (gss_cred_id_t)cred; + if (time_rec) + *time_rec = min_time; + + _gss_mg_log_cred(10, cred, "gss_acquire_cred_from"); + +cleanup: + if (major_status != GSS_S_COMPLETE) { + gss_release_cred(&minor, (gss_cred_id_t *)&cred); + if (actual_mechs) + gss_release_oid_set(&minor, actual_mechs); + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_impersonate_name.c b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_impersonate_name.c new file mode 100644 index 0000000..ec027ed --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_impersonate_name.c @@ -0,0 +1,51 @@ +/*- + * Copyright 2021, Dr Robert Harvey Crowston. <crowston@protonmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_acquire_cred_impersonate_name( + OM_uint32 *minor_status, + gss_const_cred_id_t icred_handle, + gss_const_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *ocred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + *minor_status = 0; + + if (ocred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *ocred_handle = GSS_C_NO_CREDENTIAL; + + /* Not implemented. */ + return GSS_S_UNAVAILABLE; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_with_password.c b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_with_password.c new file mode 100644 index 0000000..4e6138b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_acquire_cred_with_password.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_acquire_cred_with_password(OM_uint32 *minor_status, + gss_const_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 major_status; + gss_key_value_element_desc kv; + gss_key_value_set_desc store; + char *spassword = NULL; + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (password == GSS_C_NO_BUFFER || password->value == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + spassword = malloc(password->length + 1); + if (spassword == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(spassword, password->value, password->length); + spassword[password->length] = '\0'; + + kv.key = "password"; + kv.value = spassword; + + store.count = 1; + store.elements = &kv; + + major_status = gss_acquire_cred_from(minor_status, + desired_name, + time_req, + desired_mechs, + cred_usage, + &store, + output_cred_handle, + actual_mechs, + time_rec); + if (spassword) { + memset_s(spassword, password->length, 0, password->length); + free(spassword); + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_add_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_add_cred.c new file mode 100644 index 0000000..6d44f5c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_add_cred.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * Copyright (c) 2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_add_cred(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + return gss_add_cred_from(minor_status, + rk_UNCONST(input_cred_handle), + desired_name, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + GSS_C_NO_CRED_STORE, + output_cred_handle, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_add_cred_from.c b/third_party/heimdal/lib/gssapi/mech/gss_add_cred_from.c new file mode 100644 index 0000000..9f761e8 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_add_cred_from.c @@ -0,0 +1,292 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * Copyright (c) 2018 Kungliga Tekniska Högskolan + * Copyright (c) 2018 AuriStor, Inc. + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +OM_uint32 +_gss_mg_add_mech_cred(OM_uint32 *minor_status, + gssapi_mech_interface m, + const struct _gss_mechanism_cred *mc, + const struct _gss_mechanism_name *mn, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_const_key_value_set_t cred_store, + struct _gss_mechanism_cred **out, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 major_status; + struct _gss_mechanism_cred *new_mc = NULL; + + if (out) { + *out = NULL; + + new_mc = calloc(1, sizeof(struct _gss_mechanism_cred)); + if (new_mc == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + new_mc->gmc_mech = m; + new_mc->gmc_mech_oid = &m->gm_mech_oid; + } + + if (m->gm_add_cred_from) { + major_status = m->gm_add_cred_from(minor_status, + mc ? mc->gmc_cred : GSS_C_NO_CREDENTIAL, + mn ? mn->gmn_name : GSS_C_NO_NAME, + &m->gm_mech_oid, + cred_usage, + initiator_time_req, + acceptor_time_req, + cred_store, + new_mc ? &new_mc->gmc_cred : NULL, + NULL, + initiator_time_rec, + acceptor_time_rec); + } else if (cred_store == GSS_C_NO_CRED_STORE && m->gm_add_cred) { + major_status = m->gm_add_cred(minor_status, + mc ? mc->gmc_cred : GSS_C_NO_CREDENTIAL, + mn ? mn->gmn_name : GSS_C_NO_NAME, + &m->gm_mech_oid, + cred_usage, + initiator_time_req, + acceptor_time_req, + new_mc ? &new_mc->gmc_cred : NULL, + NULL, + initiator_time_rec, + acceptor_time_rec); + } else + major_status = GSS_S_UNAVAILABLE; + + if (major_status == GSS_S_COMPLETE && out) { + heim_assert(new_mc->gmc_cred != GSS_C_NO_CREDENTIAL, + "mechanism gss_add_cred did not return a cred"); + *out = new_mc; + } else + free(new_mc); + + return major_status; +} + +static OM_uint32 +add_mech_cred_internal(OM_uint32 *minor_status, + gss_const_name_t desired_name, + gssapi_mech_interface m, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_const_key_value_set_t cred_store, + struct _gss_cred *mut_cred, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 major_status; + struct _gss_mechanism_cred *mc; + struct _gss_mechanism_name *mn; + + heim_assert((m->gm_flags & GM_USE_MG_CRED) == 0, + "add_mech_cred_internal must be called with concrete mechanism"); + + if (desired_name != GSS_C_NO_NAME) { + major_status = _gss_find_mn(minor_status, + (struct _gss_name *)desired_name, + &m->gm_mech_oid, &mn); + if (major_status != GSS_S_COMPLETE) + return major_status; + } else + mn = NULL; + + /* + * If we have an existing mechanism credential for mechanism m, then + * add the desired credential to it; otherwise, create a new one and + * add it to mut_cred. + */ + HEIM_TAILQ_FOREACH(mc, &mut_cred->gc_mc, gmc_link) { + if (gss_oid_equal(&m->gm_mech_oid, mc->gmc_mech_oid)) + break; + } + + if (mc) { + major_status = _gss_mg_add_mech_cred(minor_status, m, + mc, mn, cred_usage, + initiator_time_req, acceptor_time_req, + cred_store, NULL, + initiator_time_rec, acceptor_time_rec); + } else { + struct _gss_mechanism_cred *new_mc = NULL; + + major_status = _gss_mg_add_mech_cred(minor_status, m, + NULL, mn, cred_usage, + initiator_time_req, acceptor_time_req, + cred_store, &new_mc, + initiator_time_rec, acceptor_time_rec); + if (major_status == GSS_S_COMPLETE) + HEIM_TAILQ_INSERT_TAIL(&mut_cred->gc_mc, new_mc, gmc_link); + } + + return major_status; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_add_cred_from(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + gss_cred_id_t release_cred = GSS_C_NO_CREDENTIAL; + struct _gss_cred *mut_cred; + OM_uint32 junk; + + *minor_status = 0; + + /* Input validation */ + if (output_cred_handle) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (initiator_time_rec) + *initiator_time_rec = 0; + if (acceptor_time_rec) + *acceptor_time_rec = 0; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + if ((m = __gss_get_mechanism(desired_mech)) == NULL) + return GSS_S_BAD_MECH; + if (input_cred_handle == GSS_C_NO_CREDENTIAL && + output_cred_handle == NULL) { + return GSS_S_CALL_INACCESSIBLE_WRITE; + } + + /* Setup mut_cred to be the credential we mutate */ + if (input_cred_handle != GSS_C_NO_CREDENTIAL && + output_cred_handle != NULL) { + gss_cred_id_t new_cred; + + /* Duplicate the input credential */ + major_status = gss_duplicate_cred(minor_status, input_cred_handle, + &new_cred); + if (major_status != GSS_S_COMPLETE) + return major_status; + mut_cred = (struct _gss_cred *)new_cred; + release_cred = (gss_cred_id_t)mut_cred; + } else if (input_cred_handle != GSS_C_NO_CREDENTIAL) { + /* Mutate the input credentials */ + mut_cred = rk_UNCONST(input_cred_handle); + } else { + mut_cred = _gss_mg_alloc_cred(); + if (mut_cred == NULL) { + *minor_status = ENOMEM; + return GSS_S_UNAVAILABLE; + } + release_cred = (gss_cred_id_t)mut_cred; + } + + if (m->gm_flags & GM_USE_MG_CRED) { + struct _gss_mech_switch *ms; + OM_uint32 initiator_time_min = GSS_C_INDEFINITE; + OM_uint32 acceptor_time_min = GSS_C_INDEFINITE; + + major_status = GSS_S_UNAVAILABLE; /* in case of no mechs */ + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + HEIM_TAILQ_FOREACH(ms, &_gss_mechs, gm_link) { + m = &ms->gm_mech; /* for _gss_mg_error() */ + + if (m->gm_flags & GM_USE_MG_CRED) + continue; + + major_status = add_mech_cred_internal(minor_status, desired_name, m, + cred_usage, + initiator_time_req, acceptor_time_req, + cred_store, mut_cred, + initiator_time_rec, acceptor_time_rec); + if (major_status != GSS_S_COMPLETE) + continue; + + if (initiator_time_rec && *initiator_time_rec < initiator_time_min) + initiator_time_min = *initiator_time_rec; + if (acceptor_time_rec && *acceptor_time_rec < acceptor_time_min) + acceptor_time_min = *acceptor_time_rec; + } + } else { + OM_uint32 lifetime; + gss_cred_usage_t usage = GSS_C_BOTH; + + major_status = gss_inquire_cred(minor_status, input_cred_handle, + NULL, &lifetime, &usage, NULL); + if (major_status == GSS_S_COMPLETE) { + if (usage == GSS_C_BOTH || usage == GSS_C_INITIATE) + initiator_time_min = lifetime; + if (usage == GSS_C_BOTH || usage == GSS_C_ACCEPT) + acceptor_time_min = lifetime; + } + } + + if (initiator_time_rec) + *initiator_time_rec = initiator_time_min; + if (acceptor_time_rec) + *acceptor_time_rec = acceptor_time_min; + } else { + major_status = add_mech_cred_internal(minor_status, desired_name, m, + cred_usage, + initiator_time_req, acceptor_time_req, + cred_store, mut_cred, + initiator_time_rec, acceptor_time_rec); + } + + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, *minor_status); + + /* Lastly, we have to inquire the cred to get the actual_mechs */ + if (major_status == GSS_S_COMPLETE && actual_mechs != NULL) { + major_status = gss_inquire_cred(minor_status, + (gss_const_cred_id_t)mut_cred, NULL, + NULL, NULL, actual_mechs); + } + if (major_status == GSS_S_COMPLETE) { + if (output_cred_handle != NULL) + *output_cred_handle = (gss_cred_id_t)mut_cred; + } else { + gss_release_cred(&junk, &release_cred); + } + return major_status; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_add_cred_with_password.c b/third_party/heimdal/lib/gssapi/mech/gss_add_cred_with_password.c new file mode 100644 index 0000000..eeb5949 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_add_cred_with_password.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_add_cred_with_password(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + const gss_buffer_t password, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 major_status; + gss_key_value_element_desc kv; + gss_key_value_set_desc store; + char *spassword = NULL; + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (password == GSS_C_NO_BUFFER || password->value == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + spassword = malloc(password->length + 1); + if (spassword == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(spassword, password->value, password->length); + spassword[password->length] = '\0'; + + kv.key = "password"; + kv.value = spassword; + + store.count = 1; + store.elements = &kv; + + major_status = gss_add_cred_from(minor_status, + rk_UNCONST(input_cred_handle), + desired_name, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + &store, + output_cred_handle, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + + if (spassword) { + memset_s(spassword, password->length, 0, password->length); + free(spassword); + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c b/third_party/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c new file mode 100644 index 0000000..8574224 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +/** + * Add a oid to the oid set. + * + * If there is a duplicate member of the oid, the new member is not + * added to to the set. + * + * @param minor_status minor status code. + * @param member_oid member to add to the oid set + * @param oid_set oid set to add the member too + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_add_oid_set_member (OM_uint32 * minor_status, + const gss_OID member_oid, + gss_OID_set * oid_set) +{ + gss_OID tmp, interned_oid; + size_t n; + OM_uint32 res; + int present; + + res = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &present); + if (res != GSS_S_COMPLETE) + return res; + + if (present) { + *minor_status = 0; + return GSS_S_COMPLETE; + } + + n = (*oid_set)->count + 1; + tmp = realloc ((*oid_set)->elements, n * sizeof(gss_OID_desc)); + if (tmp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + (*oid_set)->elements = tmp; + + res = _gss_intern_oid(minor_status, member_oid, &interned_oid); + if (res != GSS_S_COMPLETE) + return res; + + (*oid_set)->count = n; + (*oid_set)->elements[n-1] = *interned_oid; + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_aeap.c b/third_party/heimdal/lib/gssapi/mech/gss_aeap.c new file mode 100644 index 0000000..dbcd611 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_aeap.c @@ -0,0 +1,334 @@ +/* + * AEAD support + */ + +#include "mech_locl.h" + +/** + * Encrypts or sign the data. + * + * This is a more complicated version of gss_wrap(), it allows the + * caller to use AEAD data (signed header/trailer) and allow greater + * controll over where the encrypted data is placed. + * + * The maximum packet size is gss_context_stream_sizes.max_msg_size. + * + * The caller needs provide the folloing buffers when using in conf_req_flag=1 mode: + * + * - HEADER (of size gss_context_stream_sizes.header) + * { DATA or SIGN_ONLY } (optional, zero or more) + * PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted) + * TRAILER (of size gss_context_stream_sizes.trailer) + * + * - on DCE-RPC mode, the caller can skip PADDING and TRAILER if the + * DATA elements is padded to a block bountry and header is of at + * least size gss_context_stream_sizes.header + gss_context_stream_sizes.trailer. + * + * HEADER, PADDING, TRAILER will be shrunken to the size required to transmit any of them too large. + * + * To generate gss_wrap() compatible packets, use: HEADER | DATA | PADDING | TRAILER + * + * When used in conf_req_flag=0, + * + * - HEADER (of size gss_context_stream_sizes.header) + * { DATA or SIGN_ONLY } (optional, zero or more) + * PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted) + * TRAILER (of size gss_context_stream_sizes.trailer) + * + * + * The input sizes of HEADER, PADDING and TRAILER can be fetched using gss_wrap_iov_length() or + * gss_context_query_attributes(). + * + * @ingroup gssapi + */ + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_iov(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int * conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + if (minor_status) + *minor_status = 0; + if (conf_state) + *conf_state = 0; + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + if (iov == NULL && iov_count != 0) + return GSS_S_CALL_INACCESSIBLE_READ; + + m = ctx->gc_mech; + + if (m->gm_wrap_iov == NULL) + return GSS_S_UNAVAILABLE; + + return (m->gm_wrap_iov)(minor_status, ctx->gc_ctx, + conf_req_flag, qop_req, conf_state, + iov, iov_count); +} + +/** + * Decrypt or verifies the signature on the data. + * + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + if (minor_status) + *minor_status = 0; + if (conf_state) + *conf_state = 0; + if (qop_state) + *qop_state = 0; + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + if (iov == NULL && iov_count != 0) + return GSS_S_CALL_INACCESSIBLE_READ; + + m = ctx->gc_mech; + + if (m->gm_unwrap_iov == NULL) + return GSS_S_UNAVAILABLE; + + return (m->gm_unwrap_iov)(minor_status, ctx->gc_ctx, + conf_state, qop_state, + iov, iov_count); +} + +/** + * Update the length fields in iov buffer for the types: + * - GSS_IOV_BUFFER_TYPE_HEADER + * - GSS_IOV_BUFFER_TYPE_PADDING + * - GSS_IOV_BUFFER_TYPE_TRAILER + * + * Consider using gss_context_query_attributes() to fetch the data instead. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_iov_length(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + if (minor_status) + *minor_status = 0; + if (conf_state) + *conf_state = 0; + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + if (iov == NULL && iov_count != 0) + return GSS_S_CALL_INACCESSIBLE_READ; + + m = ctx->gc_mech; + + if (m->gm_wrap_iov_length == NULL) + return GSS_S_UNAVAILABLE; + + return (m->gm_wrap_iov_length)(minor_status, ctx->gc_ctx, + conf_req_flag, qop_req, conf_state, + iov, iov_count); +} + +/** + * Free all buffer allocated by gss_wrap_iov() or gss_unwrap_iov() by + * looking at the GSS_IOV_BUFFER_FLAG_ALLOCATED flag. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_iov_buffer(OM_uint32 *minor_status, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 junk; + int i; + + if (minor_status) + *minor_status = 0; + if (iov == NULL && iov_count != 0) + return GSS_S_CALL_INACCESSIBLE_READ; + + for (i = 0; i < iov_count; i++) { + if ((iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) == 0) + continue; + gss_release_buffer(&junk, &iov[i].buffer); + iov[i].type &= ~GSS_IOV_BUFFER_FLAG_ALLOCATED; + } + return GSS_S_COMPLETE; +} + +/** + * Query the context for parameters. + * + * SSPI equivalent if this function is QueryContextAttributes. + * + * - GSS_C_ATTR_STREAM_SIZES data is a gss_context_stream_sizes. + * + * @ingroup gssapi + */ + +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_attr_stream_sizes_oid_desc = + {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03")}; + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_context_query_attributes(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID attribute, + void *data, + size_t len) +{ + if (minor_status) + *minor_status = 0; + + if (gss_oid_equal(GSS_C_ATTR_STREAM_SIZES, attribute)) { + memset(data, 0, len); + return GSS_S_COMPLETE; + } + + return GSS_S_FAILURE; +} + +/* + * AEAD wrap API for a single piece of associated data, for compatibility + * with MIT and as specified by draft-howard-gssapi-aead-00.txt. + * + * @ingroup gssapi + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + OM_uint32 major_status, tmp, flags = 0; + gss_iov_buffer_desc iov[5]; + size_t i; + unsigned char *p; + + memset(iov, 0, sizeof(iov)); + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + if (input_assoc_buffer) + iov[1].buffer = *input_assoc_buffer; + + iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; + if (input_payload_buffer) + iov[2].buffer.length = input_payload_buffer->length; + + gss_inquire_context(minor_status, context_handle, NULL, NULL, + NULL, NULL, &flags, NULL, NULL); + + /* krb5 mech rejects padding/trailer if DCE-style is set */ + iov[3].type = (flags & GSS_C_DCE_STYLE) ? GSS_IOV_BUFFER_TYPE_EMPTY + : GSS_IOV_BUFFER_TYPE_PADDING; + iov[4].type = (flags & GSS_C_DCE_STYLE) ? GSS_IOV_BUFFER_TYPE_EMPTY + : GSS_IOV_BUFFER_TYPE_TRAILER; + + major_status = gss_wrap_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, conf_state, + iov, 5); + if (GSS_ERROR(major_status)) + return major_status; + + for (i = 0, output_message_buffer->length = 0; i < 5; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + continue; + + output_message_buffer->length += iov[i].buffer.length; + } + + output_message_buffer->value = malloc(output_message_buffer->length); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + for (i = 0, p = output_message_buffer->value; i < 5; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + continue; + else if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) + memcpy(p, input_payload_buffer->value, input_payload_buffer->length); + + iov[i].buffer.value = p; + p += iov[i].buffer.length; + } + + major_status = gss_wrap_iov(minor_status, context_handle, conf_req_flag, + qop_req, conf_state, iov, 5); + if (GSS_ERROR(major_status)) + gss_release_buffer(&tmp, output_message_buffer); + + return major_status; +} + +/* + * AEAD unwrap for a single piece of associated data, for compatibility + * with MIT and as specified by draft-howard-gssapi-aead-00.txt. + * + * @ingroup gssapi + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_unwrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 major_status, tmp; + gss_iov_buffer_desc iov[3]; + + memset(iov, 0, sizeof(iov)); + + iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + iov[0].buffer = *input_message_buffer; + + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + if (input_assoc_buffer) + iov[1].buffer = *input_assoc_buffer; + + iov[2].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE; + + major_status = gss_unwrap_iov(minor_status, context_handle, conf_state, + qop_state, iov, 3); + if (GSS_ERROR(major_status)) + gss_release_iov_buffer(&tmp, &iov[2], 1); + else + *output_payload_buffer = iov[2].buffer; + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_authorize_localname.c b/third_party/heimdal/lib/gssapi/mech/gss_authorize_localname.c new file mode 100644 index 0000000..b72b7bd --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_authorize_localname.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +gss_buffer_desc GSSAPI_LIB_VARIABLE __gss_c_attr_local_login_user = { + sizeof("local-login-user") - 1, + "local-login-user" +}; + +static OM_uint32 +mech_authorize_localname(OM_uint32 *minor_status, + const struct _gss_name *name, + const struct _gss_name *user) +{ + OM_uint32 major_status = GSS_S_NAME_NOT_MN; + struct _gss_mechanism_name *mn; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (m->gm_authorize_localname == NULL) { + major_status = GSS_S_UNAVAILABLE; + continue; + } + + major_status = m->gm_authorize_localname(minor_status, + mn->gmn_name, + &user->gn_value, + user->gn_type); + if (major_status != GSS_S_UNAUTHORIZED) + break; + } + + return major_status; +} + +/* + * Naming extensions based local login authorization. + */ +static OM_uint32 +attr_authorize_localname(OM_uint32 *minor_status, + const struct _gss_name *name, + const struct _gss_name *user) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + int more = -1; + + if (!gss_oid_equal(user->gn_type, GSS_C_NT_USER_NAME)) + return GSS_S_BAD_NAMETYPE; + + while (more != 0 && major_status != GSS_S_COMPLETE) { + OM_uint32 tmpMajor, tmpMinor; + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0, complete = 0; + + tmpMajor = gss_get_name_attribute(minor_status, + (gss_name_t)name, + GSS_C_ATTR_LOCAL_LOGIN_USER, + &authenticated, + &complete, + &value, + &display_value, + &more); + if (GSS_ERROR(tmpMajor)) { + major_status = tmpMajor; + break; + } + + /* If attribute is present, return an authoritative error code. */ + if (authenticated && + value.length == user->gn_value.length && + memcmp(value.value, user->gn_value.value, user->gn_value.length) == 0) + major_status = GSS_S_COMPLETE; + else + major_status = GSS_S_UNAUTHORIZED; + + gss_release_buffer(&tmpMinor, &value); + gss_release_buffer(&tmpMinor, &display_value); + } + + return major_status; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_authorize_localname(OM_uint32 *minor_status, + gss_const_name_t gss_name, + gss_const_name_t gss_user) + +{ + OM_uint32 major_status; + const struct _gss_name *name = (const struct _gss_name *) gss_name; + const struct _gss_name *user = (const struct _gss_name *) gss_user; + int mechAvailable = 0; + + *minor_status = 0; + + if (gss_name == GSS_C_NO_NAME || gss_user == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ; + + /* + * We should check that the user name is not a mechanism name, but + * as Heimdal always calls the mechanism's gss_import_name(), it's + * not possible to make this check. + */ +#if 0 + if (HEIM_TAILQ_FIRST(&user->gn_mn) != NULL) + return GSS_S_BAD_NAME; +#endif + + /* If mech returns yes, we return yes */ + major_status = mech_authorize_localname(minor_status, name, user); + if (major_status == GSS_S_COMPLETE) + return GSS_S_COMPLETE; + else if (major_status != GSS_S_UNAVAILABLE) + mechAvailable = 1; + + /* If attribute exists, it is authoritative */ + major_status = attr_authorize_localname(minor_status, name, user); + if (major_status == GSS_S_COMPLETE || major_status == GSS_S_UNAUTHORIZED) + return major_status; + + /* If mechanism did not implement SPI, compare the local name */ + if (mechAvailable == 0) { + int match = 0; + + major_status = gss_compare_name(minor_status, gss_name, + gss_user, &match); + if (major_status == GSS_S_COMPLETE && match == 0) + major_status = GSS_S_UNAUTHORIZED; + } + + return major_status; +} + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_userok(gss_const_name_t name, + const char *user) +{ + OM_uint32 major_status, minor_status; + gss_buffer_desc userBuf; + gss_name_t userName; + + userBuf.value = (void *)user; + userBuf.length = strlen(user); + + major_status = gss_import_name(&minor_status, &userBuf, + GSS_C_NT_USER_NAME, &userName); + if (GSS_ERROR(major_status)) + return 0; + + major_status = gss_authorize_localname(&minor_status, name, userName); + + gss_release_name(&minor_status, &userName); + + return (major_status == GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_buffer_set.c b/third_party/heimdal/lib/gssapi/mech/gss_buffer_set.c new file mode 100644 index 0000000..48fb720 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_buffer_set.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + + set = (gss_buffer_set_desc *) malloc(sizeof(*set)); + if (set == GSS_C_NO_BUFFER_SET) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + set->count = 0; + set->elements = NULL; + + *buffer_set = set; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + gss_buffer_t p; + OM_uint32 ret; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) { + ret = gss_create_empty_buffer_set(minor_status, + buffer_set); + if (ret) { + return ret; + } + } + + set = *buffer_set; + set->elements = realloc(set->elements, + (set->count + 1) * sizeof(set->elements[0])); + if (set->elements == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = &set->elements[set->count]; + + p->value = malloc(member_buffer->length); + if (p->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(p->value, member_buffer->value, member_buffer->length); + p->length = member_buffer->length; + + set->count++; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_buffer_set(OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + size_t i; + OM_uint32 minor; + + *minor_status = 0; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) + return GSS_S_COMPLETE; + + for (i = 0; i < (*buffer_set)->count; i++) + gss_release_buffer(&minor, &((*buffer_set)->elements[i])); + + free((*buffer_set)->elements); + + (*buffer_set)->elements = NULL; + (*buffer_set)->count = 0; + + free(*buffer_set); + *buffer_set = GSS_C_NO_BUFFER_SET; + + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_canonicalize_name.c b/third_party/heimdal/lib/gssapi/mech/gss_canonicalize_name.c new file mode 100644 index 0000000..859c688 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_canonicalize_name.c @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_canonicalize_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +/** + * gss_canonicalize_name takes a Internal Name (IN) and converts in into a + * mechanism specific Mechanism Name (MN). + * + * The input name may multiple name, or generic name types. + * + * If the input_name if of the GSS_C_NT_USER_NAME, and the Kerberos + * mechanism is specified, the resulting MN type is a + * GSS_KRB5_NT_PRINCIPAL_NAME. + * + * For more information about @ref internalVSmechname. + * + * @param minor_status minor status code. + * @param input_name name to covert, unchanged by gss_canonicalize_name(). + * @param mech_type the type to convert Name too. + * @param output_name the resulting type, release with + * gss_release_name(), independent of input_name. + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_canonicalize_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + const gss_OID mech_type, + gss_name_t *output_name) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + gssapi_mech_interface m; + gss_name_t new_canonical_name; + + *minor_status = 0; + *output_name = GSS_C_NO_NAME; + + if ((m = __gss_get_mechanism(mech_type)) == NULL || + (m->gm_flags & GM_USE_MG_NAME)) + return GSS_S_BAD_MECH; + + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (major_status) + return major_status; + if (mn == NULL) + return GSS_S_BAD_NAME; + + m = mn->gmn_mech; + major_status = m->gm_canonicalize_name(minor_status, + mn->gmn_name, mech_type, &new_canonical_name); + if (major_status) { + _gss_mg_error(m, *minor_status); + return (major_status); + } + + /* + * Now we make a new name and mark it as an MN. + */ + *minor_status = 0; + name = _gss_create_name(new_canonical_name, m); + if (!name) { + m->gm_release_name(minor_status, &new_canonical_name); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + *output_name = (gss_name_t) name; + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c b/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c new file mode 100644 index 0000000..97ef578 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_compare_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_compare_name(OM_uint32 *minor_status, + gss_const_name_t name1_arg, + gss_const_name_t name2_arg, + int *name_equal) +{ + struct _gss_name *name1 = (struct _gss_name *) name1_arg; + struct _gss_name *name2 = (struct _gss_name *) name2_arg; + + /* + * First check the implementation-independant name if both + * names have one. Otherwise, try to find common mechanism + * names and compare them. + */ + if (name1->gn_value.value && name2->gn_value.value && + name1->gn_type == GSS_C_NO_OID && name2->gn_type == GSS_C_NO_OID) { + *name_equal = + name1->gn_value.length == name2->gn_value.length && + memcmp(name1->gn_value.value, name2->gn_value.value, + name1->gn_value.length) == 0; + } else if (name1->gn_value.value && name2->gn_value.value && + name1->gn_type != GSS_C_NO_OID && + name2->gn_type != GSS_C_NO_OID) { + *name_equal = 1; + /* RFC 2743: anonymous names always compare false */ + if (gss_oid_equal(name1->gn_type, GSS_C_NT_ANONYMOUS) || + gss_oid_equal(name2->gn_type, GSS_C_NT_ANONYMOUS) || + !gss_oid_equal(name1->gn_type, name2->gn_type)) { + *name_equal = 0; + } else if (name1->gn_value.length != name2->gn_value.length || + memcmp(name1->gn_value.value, name2->gn_value.value, + name1->gn_value.length) != 0) { + *name_equal = 0; + } + } else { + struct _gss_mechanism_name *mn1; + struct _gss_mechanism_name *mn2; + + HEIM_TAILQ_FOREACH(mn1, &name1->gn_mn, gmn_link) { + OM_uint32 major_status; + + major_status = _gss_find_mn(minor_status, name2, + mn1->gmn_mech_oid, &mn2); + if (major_status == GSS_S_COMPLETE && mn2) { + return (mn1->gmn_mech->gm_compare_name( + minor_status, + mn1->gmn_name, + mn2->gmn_name, + name_equal)); + } + } + HEIM_TAILQ_FOREACH(mn2, &name2->gn_mn, gmn_link) { + OM_uint32 major_status; + + major_status = _gss_find_mn(minor_status, name1, + mn2->gmn_mech_oid, &mn1); + if (major_status == GSS_S_COMPLETE && mn1) { + return (mn2->gmn_mech->gm_compare_name( + minor_status, + mn2->gmn_name, + mn1->gmn_name, + name_equal)); + } + } + *name_equal = 0; + } + + *minor_status = 0; + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_context_time.c b/third_party/heimdal/lib/gssapi/mech/gss_context_time.c new file mode 100644 index 0000000..a5b646c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_context_time.c @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_context_time.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_context_time(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + OM_uint32 *time_rec) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_context_time(minor_status, ctx->gc_ctx, time_rec)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c b/third_party/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c new file mode 100644 index 0000000..8d880f5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_create_empty_oid_set.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_create_empty_oid_set(OM_uint32 *minor_status, + gss_OID_set *oid_set) +{ + gss_OID_set set; + + *minor_status = 0; + *oid_set = GSS_C_NO_OID_SET; + + set = malloc(sizeof(gss_OID_set_desc)); + if (!set) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + set->count = 0; + set->elements = 0; + *oid_set = set; + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_cred.c new file mode 100644 index 0000000..00561ce --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_cred.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2017 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mech_locl.h" +#include <krb5.h> + +static OM_uint32 +store_mech_oid_and_oid_set(OM_uint32 *minor_status, + krb5_storage *sp, + gss_const_OID mech, + gss_const_OID_set oids) +{ + OM_uint32 ret; + size_t i, len; + + ret = _gss_mg_store_oid(minor_status, sp, mech); + if (ret) + return ret; + + for (i = 0, len = 0; i < oids->count; i++) + len += 4 + oids->elements[i].length; + + *minor_status = krb5_store_uint32(sp, len); + if (*minor_status) + return GSS_S_FAILURE; + + for (i = 0; i < oids->count; i++) { + ret = _gss_mg_store_oid(minor_status, sp, &oids->elements[i]); + if (ret) + return ret; + } + + return GSS_S_COMPLETE; +} + + +/* + * format: any number of: + * mech-len: int32 + * mech-data: char * (not alligned) + * cred-len: int32 + * cred-data char * (not alligned) + * + * where neg_mechs is encoded for GSS_SPNEGO_MECHANISM +*/ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_export_cred(OM_uint32 * minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t token) +{ + struct _gss_cred *cred = (struct _gss_cred *)cred_handle; + struct _gss_mechanism_cred *mc; + gss_buffer_desc buffer; + krb5_error_code ret; + krb5_ssize_t bytes; + krb5_storage *sp; + OM_uint32 major; + krb5_data data; + + _mg_buffer_zero(token); + + if (cred == NULL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + if (mc->gmc_mech->gm_export_cred == NULL) { + *minor_status = 0; + gss_mg_set_error_string(&mc->gmc_mech->gm_mech_oid, + GSS_S_NO_CRED, *minor_status, + "Credential doesn't support exporting"); + return GSS_S_NO_CRED; + } + } + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + major = mc->gmc_mech->gm_export_cred(minor_status, + mc->gmc_cred, &buffer); + if (major) { + krb5_storage_free(sp); + return major; + } + + if (buffer.length) { + bytes = krb5_storage_write(sp, buffer.value, buffer.length); + if (bytes < 0 || (size_t)bytes != buffer.length) { + _gss_secure_release_buffer(minor_status, &buffer); + krb5_storage_free(sp); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + _gss_secure_release_buffer(minor_status, &buffer); + } + + if (cred->gc_neg_mechs != GSS_C_NO_OID_SET) { + major = store_mech_oid_and_oid_set(minor_status, sp, + GSS_SPNEGO_MECHANISM, + cred->gc_neg_mechs); + if (major != GSS_S_COMPLETE) { + krb5_storage_free(sp); + return major; + } + } + + ret = krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (data.length == 0) { + *minor_status = 0; + gss_mg_set_error_string(GSS_C_NO_OID, + GSS_S_NO_CRED, *minor_status, + "Credential was not exportable"); + return GSS_S_NO_CRED; + } + + token->value = data.data; + token->length = data.length; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +import_oid_set(OM_uint32 *minor_status, + gss_const_buffer_t token, + gss_OID_set *oids) +{ + OM_uint32 major, junk; + krb5_storage *sp = NULL; + + *oids = GSS_C_NO_OID_SET; + + if (token->length == 0) + return GSS_S_COMPLETE; + + major = gss_create_empty_oid_set(minor_status, oids); + if (major != GSS_S_COMPLETE) + goto out; + + sp = krb5_storage_from_readonly_mem(token->value, token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + major = GSS_S_FAILURE; + goto out; + } + + while (1) { + gss_OID oid; + + major = _gss_mg_ret_oid(minor_status, sp, &oid); + if (*minor_status == (OM_uint32)HEIM_ERR_EOF) + break; + else if (major) + goto out; + + major = gss_add_oid_set_member(minor_status, oid, oids); + if (major != GSS_S_COMPLETE) + goto out; + } + + major = GSS_S_COMPLETE; + *minor_status = 0; + +out: + if (major != GSS_S_COMPLETE) + gss_release_oid_set(&junk, oids); + krb5_storage_free(sp); + + return major; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_import_cred(OM_uint32 * minor_status, + gss_buffer_t token, + gss_cred_id_t * cred_handle) +{ + gssapi_mech_interface m; + struct _gss_cred *cred; + krb5_storage *sp = NULL; + OM_uint32 major, junk; + + *cred_handle = GSS_C_NO_CREDENTIAL; + + if (token->length == 0) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + sp = krb5_storage_from_readonly_mem(token->value, token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + cred = _gss_mg_alloc_cred(); + if (cred == NULL) { + krb5_storage_free(sp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *cred_handle = (gss_cred_id_t)cred; + + while(1) { + struct _gss_mechanism_cred *mc; + gss_buffer_desc buffer; + gss_cred_id_t mcred; + gss_OID oid; + + major = _gss_mg_ret_oid(minor_status, sp, &oid); + if (*minor_status == (OM_uint32)HEIM_ERR_EOF) + break; + else if (major != GSS_S_COMPLETE) + goto out; + + m = __gss_get_mechanism(oid); + if (!m) { + *minor_status = 0; + major = GSS_S_BAD_MECH; + goto out; + } + + if (m->gm_import_cred == NULL) { + *minor_status = 0; + major = GSS_S_BAD_MECH; + goto out; + } + + major = _gss_mg_ret_buffer(minor_status, sp, &buffer); + if (major != GSS_S_COMPLETE) + goto out; + + if (buffer.value == NULL) { + major = GSS_S_DEFECTIVE_TOKEN; + goto out; + } + + if (gss_oid_equal(&m->gm_mech_oid, GSS_SPNEGO_MECHANISM)) { + major = import_oid_set(minor_status, &buffer, &cred->gc_neg_mechs); + gss_release_buffer(&junk, &buffer); + if (major != GSS_S_COMPLETE) + goto out; + else + continue; + } + + major = m->gm_import_cred(minor_status, &buffer, &mcred); + gss_release_buffer(&junk, &buffer); + if (major != GSS_S_COMPLETE) + goto out; + + mc = calloc(1, sizeof(struct _gss_mechanism_cred)); + if (mc == NULL) { + *minor_status = EINVAL; + major = GSS_S_FAILURE; + goto out; + } + + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + mc->gmc_cred = mcred; + + HEIM_TAILQ_INSERT_TAIL(&cred->gc_mc, mc, gmc_link); + } + krb5_storage_free(sp); + sp = NULL; + + if (HEIM_TAILQ_EMPTY(&cred->gc_mc)) { + major = GSS_S_NO_CRED; + goto out; + } + + return GSS_S_COMPLETE; + + out: + if (sp) + krb5_storage_free(sp); + + gss_release_cred(&junk, cred_handle); + + return major; + +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_decapsulate_token.c b/third_party/heimdal/lib/gssapi/mech/gss_decapsulate_token.c new file mode 100644 index 0000000..5d9eca0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_decapsulate_token.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_decapsulate_token(gss_const_buffer_t input_token, + gss_const_OID oid, + gss_buffer_t output_token) +{ + GSSAPIContextToken ct; + heim_oid o; + OM_uint32 status; + int ret; + size_t size; + + _mg_buffer_zero(output_token); + + ret = der_get_oid (oid->elements, oid->length, &o, &size); + if (ret) + return GSS_S_FAILURE; + + ret = decode_GSSAPIContextToken(input_token->value, input_token->length, + &ct, NULL); + if (ret) { + der_free_oid(&o); + return GSS_S_DEFECTIVE_TOKEN; + } + + if (der_heim_oid_cmp(&ct.thisMech, &o) == 0) { + status = GSS_S_COMPLETE; + output_token->value = ct.innerContextToken.data; + output_token->length = ct.innerContextToken.length; + der_free_oid(&ct.thisMech); + } else { + free_GSSAPIContextToken(&ct); + status = GSS_S_BAD_MECH; + } + der_free_oid(&o); + + return status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_delete_name_attribute.c b/third_party/heimdal/lib/gssapi/mech/gss_delete_name_attribute.c new file mode 100644 index 0000000..a1ca5da --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_delete_name_attribute.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t input_name, + gss_buffer_t attr) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (!m->gm_delete_name_attribute) + continue; + + major_status = m->gm_delete_name_attribute(minor_status, + mn->gmn_name, + attr); + if (GSS_ERROR(major_status)) + _gss_mg_error(m, *minor_status); + else + break; + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_delete_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_delete_sec_context.c new file mode 100644 index 0000000..8e1f98c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_delete_sec_context.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_delete_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_delete_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token) +{ + OM_uint32 major_status; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + + if (output_token) + _mg_buffer_zero(output_token); + + *minor_status = 0; + major_status = GSS_S_COMPLETE; + + if (!ctx) + return GSS_S_COMPLETE; + + free(ctx->gc_free_this); + + /* + * If we have an implementation ctx, delete it, + * otherwise fake an empty token. + */ + if (ctx->gc_ctx) { + major_status = ctx->gc_mech->gm_delete_sec_context( + minor_status, &ctx->gc_ctx, output_token); + } + free(ctx); + *context_handle = GSS_C_NO_CONTEXT; + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_destroy_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_destroy_cred.c new file mode 100644 index 0000000..5b7fafc --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_destroy_cred.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +#include <heim_threads.h> + +/** + * Destroy a credential + * + * gss_release_cred() frees the memory, gss_destroy_cred() removes the credentials from memory/disk and then call gss_release_cred() on the credential. + * + * @param min_stat minor status code + * @param cred_handle credentail to destory + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_destroy_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle) +{ + struct _gss_cred *cred; + struct _gss_mechanism_cred *mc, *next; + + OM_uint32 junk; + + if (cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + if (*cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_COMPLETE; + + cred = (struct _gss_cred *)*cred_handle; + *cred_handle = GSS_C_NO_CREDENTIAL; + + HEIM_TAILQ_FOREACH_SAFE(mc, &cred->gc_mc, gmc_link, next) { + HEIM_TAILQ_REMOVE(&cred->gc_mc, mc, gmc_link); + if (mc->gmc_mech->gm_destroy_cred) + mc->gmc_mech->gm_destroy_cred(&junk, &mc->gmc_cred); + else + mc->gmc_mech->gm_release_cred(&junk, &mc->gmc_cred); + free(mc); + } + free(cred); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_display_name.c b/third_party/heimdal/lib/gssapi/mech/gss_display_name.c new file mode 100644 index 0000000..fadd68b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_display_name.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_display_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_display_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + _mg_buffer_zero(output_name_buffer); + if (output_name_type) + *output_name_type = GSS_C_NO_OID; + + if (name == NULL) { + *minor_status = 0; + return (GSS_S_BAD_NAME); + } + + /* + * If we know it, copy the buffer used to import the name in + * the first place. Otherwise, ask all the MNs in turn if + * they can display the thing. + */ + if (name->gn_value.value) { + output_name_buffer->value = malloc(name->gn_value.length); + if (!output_name_buffer->value) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + output_name_buffer->length = name->gn_value.length; + memcpy(output_name_buffer->value, name->gn_value.value, + output_name_buffer->length); + if (output_name_type) + *output_name_type = name->gn_type; + + *minor_status = 0; + return (GSS_S_COMPLETE); + } else { + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + major_status = mn->gmn_mech->gm_display_name( + minor_status, mn->gmn_name, + output_name_buffer, + output_name_type); + if (major_status == GSS_S_COMPLETE) + return (GSS_S_COMPLETE); + } + } + + *minor_status = 0; + return (GSS_S_FAILURE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_display_name_ext.c b/third_party/heimdal/lib/gssapi/mech/gss_display_name_ext.c new file mode 100644 index 0000000..80ea72b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_display_name_ext.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_display_name_ext(OM_uint32 *minor_status, + gss_name_t input_name, + gss_OID display_as_name_type, + gss_buffer_t display_name) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + _mg_buffer_zero(display_name); + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (!m->gm_display_name_ext) + continue; + + major_status = m->gm_display_name_ext(minor_status, + mn->gmn_name, + display_as_name_type, + display_name); + if (GSS_ERROR(major_status)) + _gss_mg_error(m, *minor_status); + else + break; + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_display_status.c b/third_party/heimdal/lib/gssapi/mech/gss_display_status.c new file mode 100644 index 0000000..dca5d1b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_display_status.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_display_status.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ +/* + * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +static const char * +calling_error(OM_uint32 v) +{ + static const char *msgs[] = { + NULL, /* 0 */ + "A required input parameter could not be read.", /* */ + "A required output parameter could not be written.", /* */ + "A parameter was malformed" + }; + + v >>= GSS_C_CALLING_ERROR_OFFSET; + + if (v == 0) + return ""; + else if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown calling error"; + else + return msgs[v]; +} + +static const char * +routine_error(OM_uint32 v) +{ + static const char *msgs[] = { + "Function completed successfully", /* 0 */ + "An unsupported mechanism was requested", + "An invalid name was supplied", + "A supplied name was of an unsupported type", + "Incorrect channel bindings were supplied", + "An invalid status code was supplied", + "A token had an invalid MIC", + "No credentials were supplied, or the credentials were unavailable or inaccessible.", + "No context has been established", + "A token was invalid", + "A credential was invalid", + "The referenced credentials have expired", + "The context has expired", + "Miscellaneous failure (see text)", + "The quality-of-protection requested could not be provide", + "The operation is forbidden by local security policy", + "The operation or option is not available", + "The requested credential element already exists", + "The provided name was not a mechanism name.", + }; + + v >>= GSS_C_ROUTINE_ERROR_OFFSET; + + if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + +static const char * +supplementary_error(OM_uint32 v) +{ + static const char *msgs[] = { + "normal completion", + "continuation call to routine required", + "duplicate per-message token detected", + "timed-out per-message token detected", + "reordered (early) per-message token detected", + "skipped predecessor token(s) detected" + }; + + v >>= GSS_C_SUPPLEMENTARY_OFFSET; + + if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + +/** + * Convert a GSS-API status code to text + * + * @param minor_status minor status code + * @param status_value status value to convert + * @param status_type One of: + * GSS_C_GSS_CODE - status_value is a GSS status code, + * GSS_C_MECH_CODE - status_value is a mechanism status code + * @param mech_type underlying mechanism. Use GSS_C_NO_OID to obtain the + * system default. + * @param message_context state information to extract further messages from the + * status_value + * @param status_string the allocated text representation. Release with + * gss_release_buffer() + * + * @returns a gss_error code. + * + * @ingroup gssapi + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_display_status(OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + OM_uint32 major_status; + + _mg_buffer_zero(status_string); + *message_context = 0; + + *minor_status = 0; + switch (status_type) { + case GSS_C_GSS_CODE: { + char *buf = NULL; + int e; + + if (GSS_SUPPLEMENTARY_INFO(status_value)) + e = asprintf(&buf, "%s", supplementary_error( + GSS_SUPPLEMENTARY_INFO(status_value))); + else + e = asprintf (&buf, "%s %s", + calling_error(GSS_CALLING_ERROR(status_value)), + routine_error(GSS_ROUTINE_ERROR(status_value))); + + if (e < 0 || buf == NULL) + break; + + status_string->length = strlen(buf); + status_string->value = buf; + + return GSS_S_COMPLETE; + } + case GSS_C_MECH_CODE: { + OM_uint32 maj_junk, min_junk; + gss_buffer_desc oid; + char *buf = NULL; + int e; + + major_status = _gss_mg_get_error(mech_type, status_value, + status_string); + if (major_status == GSS_S_COMPLETE) { + *message_context = 0; + *minor_status = 0; + return GSS_S_COMPLETE; + } + + maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); + if (maj_junk != GSS_S_COMPLETE) { + oid.value = rk_UNCONST("unknown"); + oid.length = 7; + } + + e = asprintf (&buf, "unknown mech-code %lu for mech %.*s", + (unsigned long)status_value, + (int)oid.length, (char *)oid.value); + if (maj_junk == GSS_S_COMPLETE) + gss_release_buffer(&min_junk, &oid); + + if (e < 0 || buf == NULL) + break; + + status_string->length = strlen(buf); + status_string->value = buf; + + return GSS_S_COMPLETE; + } + } + _mg_buffer_zero(status_string); + return (GSS_S_BAD_STATUS); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_duplicate_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_cred.c new file mode 100644 index 0000000..0c25ce9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_cred.c @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * Copyright (c) 2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +static OM_uint32 +copy_cred_element(OM_uint32 *minor_status, + struct _gss_mechanism_cred *mc, + struct _gss_mechanism_cred **out) +{ + gssapi_mech_interface m = mc->gmc_mech; + OM_uint32 major_status, tmp; + struct _gss_mechanism_cred *new_mc; + OM_uint32 initiator_lifetime, acceptor_lifetime; + gss_cred_usage_t cred_usage; + gss_cred_id_t dup_cred = GSS_C_NO_CREDENTIAL; + + *out = NULL; + + if (m->gm_duplicate_cred) { + major_status = m->gm_duplicate_cred(minor_status, + mc->gmc_cred, &dup_cred); + } else if (m->gm_import_cred && m->gm_export_cred) { + gss_buffer_desc export; + + major_status = m->gm_export_cred(minor_status, mc->gmc_cred, &export); + if (major_status == GSS_S_COMPLETE) { + major_status = m->gm_import_cred(minor_status, &export, &dup_cred); + _gss_secure_release_buffer(&tmp, &export); + } + } else { + struct _gss_mechanism_name mn; + + mn.gmn_mech = m; + mn.gmn_mech_oid = mc->gmc_mech_oid; + mn.gmn_name = GSS_C_NO_NAME; + + /* This path won't work for ephemeral creds or cred stores */ + major_status = m->gm_inquire_cred_by_mech(minor_status, mc->gmc_cred, + mc->gmc_mech_oid, &mn.gmn_name, + &initiator_lifetime, + &acceptor_lifetime, &cred_usage); + if (major_status == GSS_S_COMPLETE) { + major_status = _gss_mg_add_mech_cred(minor_status, + m, + NULL, /* mc */ + &mn, + cred_usage, + initiator_lifetime, + acceptor_lifetime, + GSS_C_NO_CRED_STORE, + &new_mc, + NULL, + NULL); + m->gm_release_name(&tmp, &mn.gmn_name); + } + } + + if (major_status == GSS_S_COMPLETE) { + new_mc = calloc(1, sizeof(*new_mc)); + if (new_mc == NULL) { + *minor_status = ENOMEM; + m->gm_release_cred(&tmp, &dup_cred); + return GSS_S_FAILURE; + } + + new_mc->gmc_mech = m; + new_mc->gmc_mech_oid = mc->gmc_mech_oid; + new_mc->gmc_cred = dup_cred; + + *out = new_mc; + } else + _gss_mg_error(m, *minor_status); + + return major_status; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_duplicate_cred(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_id_t *output_cred_handle) +{ + struct _gss_mechanism_cred *mc; + struct _gss_cred *new_cred; + struct _gss_cred *cred = (struct _gss_cred *)input_cred_handle; + OM_uint32 major_status, junk; + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + /* + * "Copy" the default credential by acquiring a cred handle for the + * default credential's name, GSS_C_NO_NAME. + */ + return gss_acquire_cred(minor_status, GSS_C_NO_NAME, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_BOTH, + output_cred_handle, NULL, NULL); + } + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + new_cred = _gss_mg_alloc_cred(); + if (!new_cred) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *minor_status = 0; + major_status = GSS_S_NO_CRED; + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + struct _gss_mechanism_cred *copy_mc; + + major_status = copy_cred_element(minor_status, mc, ©_mc); + if (major_status != GSS_S_COMPLETE) + break; + + HEIM_TAILQ_INSERT_TAIL(&new_cred->gc_mc, copy_mc, gmc_link); + } + + if (major_status != GSS_S_COMPLETE) { + gss_cred_id_t release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + new_cred = NULL; + } + + *output_cred_handle = (gss_cred_id_t)new_cred; + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_duplicate_name.c b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_name.c new file mode 100644 index 0000000..e8d1e32 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_name.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_duplicate_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_duplicate_name(OM_uint32 *minor_status, + gss_const_name_t src_name, + gss_name_t *dest_name) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) src_name; + struct _gss_name *new_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + *dest_name = GSS_C_NO_NAME; + + /* + * If this name has a value (i.e. it didn't come from + * gss_canonicalize_name(), we re-import the thing. Otherwise, + * we make copy of each mech names. + */ + if (name->gn_value.value) { + major_status = gss_import_name(minor_status, + &name->gn_value, name->gn_type, dest_name); + if (major_status != GSS_S_COMPLETE) + return (major_status); + new_name = (struct _gss_name *) *dest_name; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + struct _gss_mechanism_name *mn2; + _gss_find_mn(minor_status, new_name, + mn->gmn_mech_oid, &mn2); + } + } else { + new_name = _gss_create_name(NULL, NULL); + if (!new_name) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + *dest_name = (gss_name_t) new_name; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + struct _gss_mechanism_name *new_mn; + + new_mn = malloc(sizeof(*new_mn)); + if (!new_mn) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + new_mn->gmn_mech = mn->gmn_mech; + new_mn->gmn_mech_oid = mn->gmn_mech_oid; + + major_status = + mn->gmn_mech->gm_duplicate_name(minor_status, + mn->gmn_name, &new_mn->gmn_name); + if (major_status != GSS_S_COMPLETE) { + free(new_mn); + continue; + } + HEIM_TAILQ_INSERT_TAIL(&new_name->gn_mn, new_mn, gmn_link); + } + + } + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_duplicate_oid.c b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_oid.c new file mode 100644 index 0000000..29a9cf8 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_oid.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_duplicate_oid ( + OM_uint32 *minor_status, + gss_OID src_oid, + gss_OID *dest_oid + ) +{ + *minor_status = 0; + + if (src_oid == GSS_C_NO_OID) { + *dest_oid = GSS_C_NO_OID; + return GSS_S_COMPLETE; + } + + return _gss_intern_oid(minor_status, src_oid, dest_oid); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_duplicate_oid_set.c b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_oid_set.c new file mode 100644 index 0000000..ae0ab8d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_duplicate_oid_set.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_duplicate_oid_set(OM_uint32 *minor_status, + gss_OID_set src_oid_set, + gss_OID_set *dest_oid_set) +{ + OM_uint32 major_status, junk; + size_t i; + + *dest_oid_set = GSS_C_NO_OID_SET; + + major_status = gss_create_empty_oid_set(minor_status, dest_oid_set); + + for (i = 0; major_status == GSS_S_COMPLETE && i < src_oid_set->count; i++) + major_status = gss_add_oid_set_member(minor_status, + &src_oid_set->elements[i], + dest_oid_set); + + if (major_status != GSS_S_COMPLETE) + gss_release_oid_set(&junk, dest_oid_set); + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_encapsulate_token.c b/third_party/heimdal/lib/gssapi/mech/gss_encapsulate_token.c new file mode 100644 index 0000000..1b1f973 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_encapsulate_token.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_encapsulate_token(gss_const_buffer_t input_token, + gss_const_OID oid, + gss_buffer_t output_token) +{ + GSSAPIContextToken ct; + int ret; + size_t size; + + ret = der_get_oid (oid->elements, oid->length, &ct.thisMech, &size); + if (ret) { + _mg_buffer_zero(output_token); + return GSS_S_FAILURE; + } + + ct.innerContextToken.data = input_token->value; + ct.innerContextToken.length = input_token->length; + + ASN1_MALLOC_ENCODE(GSSAPIContextToken, + output_token->value, output_token->length, + &ct, &size, ret); + der_free_oid(&ct.thisMech); + if (ret) { + _mg_buffer_zero(output_token); + return GSS_S_FAILURE; + } + if (output_token->length != size) + abort(); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_export_name.c b/third_party/heimdal/lib/gssapi/mech/gss_export_name.c new file mode 100644 index 0000000..92b7a8f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_export_name.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_export_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +/** + * Convert a GGS-API name from internal form to contiguous string. + * + * @sa gss_import_name(), @ref internalVSmechname. + * + * @param minor_status minor status code + * @param input_name input name in internal name form + * @param exported_name output name in contiguos string form + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_export_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + gss_buffer_t exported_name) +{ + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + _mg_buffer_zero(exported_name); + + /* + * If this name already has any attached MNs, export the first + * one, otherwise export based on the first mechanism in our + * list. + */ + mn = HEIM_TAILQ_FIRST(&name->gn_mn); + if (!mn) { + *minor_status = 0; + return (GSS_S_NAME_NOT_MN); + } + + return mn->gmn_mech->gm_export_name(minor_status, + mn->gmn_name, exported_name); +} + +OM_uint32 +gss_mg_export_name(OM_uint32 *minor_status, + const gss_const_OID mech, + const void *name, + size_t length, + gss_buffer_t exported_name) +{ + uint8_t *buf; + + exported_name->length = 10 + length + mech->length; + exported_name->value = malloc(exported_name->length); + if (exported_name->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + buf = exported_name->value; + memcpy(buf, "\x04\x01", 2); + buf += 2; + buf[0] = ((mech->length + 2) >> 8) & 0xff; + buf[1] = (mech->length + 2) & 0xff; + buf+= 2; + buf[0] = 0x06; + buf[1] = (mech->length) & 0xFF; + buf+= 2; + + memcpy(buf, mech->elements, mech->length); + buf += mech->length; + + buf[0] = (length >> 24) & 0xff; + buf[1] = (length >> 16) & 0xff; + buf[2] = (length >> 8) & 0xff; + buf[3] = (length) & 0xff; + buf += 4; + + memcpy (buf, name, length); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_export_name_composite.c b/third_party/heimdal/lib/gssapi/mech/gss_export_name_composite.c new file mode 100644 index 0000000..d833ebb --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_export_name_composite.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_export_name_composite(OM_uint32 *minor_status, + gss_name_t input_name, + gss_buffer_t exp_composite_name) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + _mg_buffer_zero(exp_composite_name); + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (!m->gm_export_name_composite) + continue; + + major_status = m->gm_export_name_composite(minor_status, + mn->gmn_name, + exp_composite_name); + if (GSS_ERROR(major_status)) + _gss_mg_error(m, *minor_status); + else + break; + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c new file mode 100644 index 0000000..c030980 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_export_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_export_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token) +{ + OM_uint32 major_status = GSS_S_FAILURE, tmp_minor; + krb5_storage *sp; + krb5_data data; + krb5_error_code kret; + struct _gss_context *ctx; + gssapi_mech_interface m; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + unsigned char verflags; + + *minor_status = 0; + + if (!interprocess_token) + return GSS_S_CALL_INACCESSIBLE_READ; + + _mg_buffer_zero(interprocess_token); + + if (context_handle == NULL) + return GSS_S_NO_CONTEXT; + + ctx = (struct _gss_context *) *context_handle; + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + goto failure; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_PACKED); + + verflags = 0x00; /* Version 0 */ + + if (ctx->gc_target_len) + verflags |= EXPORT_CONTEXT_FLAG_ACCUMULATING; + + if (ctx->gc_ctx) + verflags |= EXPORT_CONTEXT_FLAG_MECH_CTX; + + kret = krb5_store_uint8(sp, verflags); + if (kret) { + *minor_status = kret; + goto failure; + } + + if (ctx->gc_target_len) { + _gss_mg_log(10, "gss-esc: exporting partial token %zu/%zu", + ctx->gc_input.length, ctx->gc_target_len); + kret = krb5_store_uint8(sp, ctx->gc_initial); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_uint32(sp, ctx->gc_target_len); + if (kret) { + *minor_status = kret; + goto failure; + } + major_status = _gss_mg_store_buffer(minor_status, sp, + &ctx->gc_input); + if (major_status != GSS_S_COMPLETE) + goto failure; + } else if (ctx->gc_ctx == GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&tmp_minor, context_handle, + GSS_C_NO_BUFFER); + return GSS_S_NO_CONTEXT; + } + + if (ctx->gc_ctx) { + m = ctx->gc_mech; + + major_status = m->gm_export_sec_context(minor_status, + &ctx->gc_ctx, &buf); + + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, *minor_status); + goto failure; + } + + major_status = _gss_mg_store_oid(minor_status, sp, + &m->gm_mech_oid); + if (major_status != GSS_S_COMPLETE) + goto failure; + + major_status = _gss_mg_store_buffer(minor_status, sp, &buf); + if (major_status != GSS_S_COMPLETE) + goto failure; + } + + kret = krb5_storage_to_data(sp, &data); + if (kret) { + *minor_status = kret; + goto failure; + } + + interprocess_token->length = data.length; + interprocess_token->value = data.data; + + major_status = GSS_S_COMPLETE; + + _gss_mg_log(1, "gss-esc: token length %zu", data.length); + +failure: + if (major_status == GSS_S_COMPLETE && *minor_status == 0) + gss_delete_sec_context(&tmp_minor, context_handle, + GSS_C_NO_BUFFER); + else if (*minor_status) + major_status = GSS_S_FAILURE; + + _gss_secure_release_buffer(minor_status, &buf); + krb5_storage_free(sp); + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_get_mic.c b/third_party/heimdal/lib/gssapi/mech/gss_get_mic.c new file mode 100644 index 0000000..8663053 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_get_mic.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_get_mic.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_get_mic(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + _mg_buffer_zero(message_token); + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + m = ctx->gc_mech; + + return (m->gm_get_mic(minor_status, ctx->gc_ctx, qop_req, + message_buffer, message_token)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_get_name_attribute.c b/third_party/heimdal/lib/gssapi/mech/gss_get_name_attribute.c new file mode 100644 index 0000000..1b7bee5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_get_name_attribute.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_get_name_attribute(OM_uint32 *minor_status, + gss_name_t input_name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + if (authenticated != NULL) + *authenticated = 0; + if (complete != NULL) + *complete = 0; + _mg_buffer_zero(value); + _mg_buffer_zero(display_value); + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + _gss_mg_check_name(input_name); + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (!m->gm_get_name_attribute) + continue; + + major_status = m->gm_get_name_attribute(minor_status, + mn->gmn_name, + attr, + authenticated, + complete, + value, + display_value, + more); + if (GSS_ERROR(major_status)) + _gss_mg_error(m, *minor_status); + else + break; + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_get_neg_mechs.c b/third_party/heimdal/lib/gssapi/mech/gss_get_neg_mechs.c new file mode 100644 index 0000000..cbc3786 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_get_neg_mechs.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_get_neg_mechs(OM_uint32 *minor_status, + gss_const_cred_id_t cred_handle, + gss_OID_set *mechs) +{ + struct _gss_cred *cred = (struct _gss_cred *)cred_handle; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (mechs == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (cred->gc_neg_mechs != GSS_C_NO_OID_SET) + return gss_duplicate_oid_set(minor_status, cred->gc_neg_mechs, mechs); + + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_import_name.c b/third_party/heimdal/lib/gssapi/mech/gss_import_name.c new file mode 100644 index 0000000..54930bf --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_import_name.c @@ -0,0 +1,323 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_import_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +static OM_uint32 +_gss_import_export_name(OM_uint32 *minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID name_type, + gss_name_t *output_name) +{ + OM_uint32 major_status; + unsigned char *p = input_name_buffer->value; + size_t len = input_name_buffer->length; + size_t t; + gss_OID_desc mech_oid; + gssapi_mech_interface m; + struct _gss_name *name; + gss_name_t new_canonical_name; + int composite = 0; + + *minor_status = 0; + *output_name = 0; + + /* + * Make sure that TOK_ID is {4, 1}. + */ + if (len < 2) + return (GSS_S_BAD_NAME); + if (p[0] != 4) + return (GSS_S_BAD_NAME); + switch (p[1]) { + case 1: /* non-composite name */ + break; + case 2: /* composite name */ + composite = 1; + break; + default: + return (GSS_S_BAD_NAME); + } + p += 2; + len -= 2; + + /* + * If the name token is a composite token (TOK_ID 0x04 0x02) then per + * RFC6680 everything after that is implementation-specific. This + * mech-glue is pluggable however, so we need the format of the rest of + * the header to be stable, otherwise we couldn't reliably determine + * what mechanism the token is for and we'd have to try all of them. + * + * So... we keep the same format for the exported composite name token + * as for normal exported name tokens (see RFC2743, section 3.2), with + * the TOK_ID 0x04 0x02, but only up to the mechanism OID. We don't + * enforce that there be a NAME_LEN in the exported composite name + * token, or that it match the length of the remainder of the token. + * + * FYI, at least one out-of-tree mechanism implements exported + * composite name tokens as the same as exported name tokens with + * attributes appended and the NAME_LEN not modified to match. + */ + + /* + * Get the mech length and the name length and sanity + * check the size of of the buffer. + */ + if (len < 2) + return (GSS_S_BAD_NAME); + t = (p[0] << 8) + p[1]; + p += 2; + len -= 2; + + /* + * Check the DER encoded OID to make sure it agrees with the + * length we just decoded. + */ + if (p[0] != 6) /* 6=OID */ + return (GSS_S_BAD_NAME); + p++; + len--; + t--; + if (p[0] & 0x80) { + int digits = p[0]; + p++; + len--; + t--; + mech_oid.length = 0; + while (digits--) { + mech_oid.length = (mech_oid.length << 8) | p[0]; + p++; + len--; + t--; + } + } else { + mech_oid.length = p[0]; + p++; + len--; + t--; + } + if (mech_oid.length != t) + return (GSS_S_BAD_NAME); + + mech_oid.elements = p; + + if (!composite) { + if (len < t + 4) + return (GSS_S_BAD_NAME); + p += t; + len -= t; + + t = ((unsigned long)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + /* p += 4; // we're done using `p' now */ + len -= 4; + + if (len != t) + return (GSS_S_BAD_NAME); + } + + m = __gss_get_mechanism(&mech_oid); + if (!m || !m->gm_import_name) + return (GSS_S_BAD_MECH); + + /* + * Ask the mechanism to import the name. + */ + major_status = m->gm_import_name(minor_status, + input_name_buffer, name_type, &new_canonical_name); + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, *minor_status); + return major_status; + } + + /* + * Now we make a new name and mark it as an MN. + */ + name = _gss_create_name(new_canonical_name, m); + if (!name) { + m->gm_release_name(minor_status, &new_canonical_name); + return (GSS_S_FAILURE); + } + + *output_name = (gss_name_t) name; + + *minor_status = 0; + return (GSS_S_COMPLETE); +} + +/** + * Convert a GGS-API name from contiguous string to internal form. + * + * Type of name and their format: + * - GSS_C_NO_OID + * - GSS_C_NT_USER_NAME + * - GSS_C_NT_HOSTBASED_SERVICE + * - GSS_C_NT_EXPORT_NAME + * - GSS_C_NT_COMPOSITE_EXPORT + * - GSS_C_NT_ANONYMOUS + * - GSS_KRB5_NT_PRINCIPAL_NAME + * + * @sa gss_export_name(), @ref internalVSmechname. + * + * @param minor_status minor status code + * @param input_name_buffer import name buffer + * @param input_name_type type of the import name buffer + * @param output_name the resulting type, release with + * gss_release_name(), independent of input_name + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_import_name(OM_uint32 *minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t *output_name) +{ + struct _gss_mechanism_name *mn; + gss_OID name_type = input_name_type; + OM_uint32 major_status, ms; + struct _gss_name *name; + struct _gss_mech_switch *m; + gss_name_t rname; + + if (input_name_buffer == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + if (output_name == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *output_name = GSS_C_NO_NAME; + + /* Allow empty names since that's valid (ANONYMOUS for example) */ + + _gss_load_mech(); + + /* + * If this is an exported name, we need to parse it to find + * the mechanism and then import it as an MN. See RFC 2743 + * section 3.2 for a description of the format. + */ + if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME) || + gss_oid_equal(name_type, GSS_C_NT_COMPOSITE_EXPORT)) { + return _gss_import_export_name(minor_status, input_name_buffer, + name_type, output_name); + } + + + *minor_status = 0; + name = _gss_create_name(NULL, NULL); + if (!name) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + if (name_type != GSS_C_NO_OID) { + major_status = _gss_intern_oid(minor_status, + name_type, &name->gn_type); + if (major_status) { + rname = (gss_name_t)name; + gss_release_name(&ms, (gss_name_t *)&rname); + return (GSS_S_FAILURE); + } + } else + name->gn_type = GSS_C_NO_OID; + + major_status = _gss_copy_buffer(minor_status, + input_name_buffer, &name->gn_value); + if (major_status) + goto out; + + /* + * Walk over the mechs and import the name into a mech name + * for those supported this nametype. + */ + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + int present = 0; + + if ((m->gm_mech.gm_flags & GM_USE_MG_NAME)) + continue; + + if (name_type != GSS_C_NO_OID) { + major_status = gss_test_oid_set_member(minor_status, + name_type, m->gm_name_types, &present); + + if (GSS_ERROR(major_status) || present == 0) + continue; + } + + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto out; + } + + major_status = (*m->gm_mech.gm_import_name)(minor_status, + &name->gn_value, + name->gn_type, + &mn->gmn_name); + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(&m->gm_mech, *minor_status); + free(mn); + /** + * If we failed to import the name in a mechanism, it + * will be ignored as long as its possible to import + * name in some other mechanism. We will catch the + * failure later though in gss_init_sec_context() or + * another function. + */ + continue; + } + + mn->gmn_mech = &m->gm_mech; + mn->gmn_mech_oid = m->gm_mech_oid; + HEIM_TAILQ_INSERT_TAIL(&name->gn_mn, mn, gmn_link); + } + + /* + * If we can't find a mn for the name, bail out already here. + */ + + mn = HEIM_TAILQ_FIRST(&name->gn_mn); + if (!mn) { + *minor_status = 0; + major_status = GSS_S_NAME_NOT_MN; + goto out; + } + + *output_name = (gss_name_t) name; + return (GSS_S_COMPLETE); + + out: + rname = (gss_name_t)name; + gss_release_name(&ms, &rname); + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c new file mode 100644 index 0000000..39b717e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_import_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_import_sec_context(OM_uint32 *minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle) +{ + OM_uint32 ret = GSS_S_FAILURE, tmp_minor; + krb5_storage *sp; + gssapi_mech_interface m; + struct _gss_context *ctx = NULL; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + unsigned char verflags; + + _gss_mg_log(10, "gss-isc called"); + + if (!context_handle) { + *minor_status = EFAULT; + return GSS_S_CALL_INACCESSIBLE_WRITE; + } + + *minor_status = 0; + *context_handle = GSS_C_NO_CONTEXT; + + sp = krb5_storage_from_mem(interprocess_token->value, + interprocess_token->length); + if (!sp) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_PACKED); + + ctx = calloc(1, sizeof(struct _gss_context)); + if (!ctx) { + *minor_status = ENOMEM; + goto failure; + } + + if (krb5_ret_uint8(sp, &verflags)) + goto failure; + + if ((verflags & EXPORT_CONTEXT_VERSION_MASK) != 0) { + _gss_mg_log(10, "gss-isc failed, token version %d not recognised", + (int)(verflags & EXPORT_CONTEXT_VERSION_MASK)); + /* We don't recognise the version */ + goto failure; + } + + if (verflags & EXPORT_CONTEXT_FLAG_ACCUMULATING) { + uint32_t target_len; + + if (krb5_ret_uint8(sp, &ctx->gc_initial)) + goto failure; + + if (krb5_ret_uint32(sp, &target_len)) + goto failure; + + ret = _gss_mg_ret_buffer(minor_status, sp, &buf); + if (ret != GSS_S_COMPLETE) + goto failure; + + ctx->gc_free_this = ctx->gc_input.value = calloc(target_len, 1); + if (ctx->gc_input.value == NULL) + goto failure; + + ctx->gc_target_len = target_len; + ctx->gc_input.length = buf.length; + if (buf.value) + memcpy(ctx->gc_input.value, buf.value, buf.length); + + gss_release_buffer(&tmp_minor, &buf); + } + + if (verflags & EXPORT_CONTEXT_FLAG_MECH_CTX) { + gss_OID mech_oid; + + ret = _gss_mg_ret_oid(minor_status, sp, &mech_oid); + if (ret != GSS_S_COMPLETE) + goto failure; + + if (mech_oid == GSS_C_NO_OID) { + ret = GSS_S_BAD_MECH; + goto failure; + } + + m = __gss_get_mechanism(mech_oid); + if (m == NULL) { + ret = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } + ctx->gc_mech = m; + + ret = _gss_mg_ret_buffer(minor_status, sp, &buf); + if (ret != GSS_S_COMPLETE) + goto failure; + + if (buf.value == NULL) { + ret = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } + + ret = m->gm_import_sec_context(minor_status, &buf, &ctx->gc_ctx); + if (ret != GSS_S_COMPLETE) { + _gss_mg_error(m, *minor_status); + goto failure; + } + } + + *context_handle = (gss_ctx_id_t) ctx; + ctx = NULL; + + ret = GSS_S_COMPLETE; + +failure: + free(ctx); + krb5_storage_free(sp); + _gss_secure_release_buffer(&tmp_minor, &buf); + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_indicate_mechs.c b/third_party/heimdal/lib/gssapi/mech/gss_indicate_mechs.c new file mode 100644 index 0000000..9eef62e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_indicate_mechs.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_indicate_mechs.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_indicate_mechs(OM_uint32 *minor_status, + gss_OID_set *mech_set) +{ + struct _gss_mech_switch *m; + OM_uint32 major_status, junk; + gss_OID_set set; + size_t i; + + _gss_load_mech(); + + major_status = gss_create_empty_oid_set(minor_status, mech_set); + if (major_status) + return (major_status); + + /* XXX We ignore ENOMEM from gss_add_oid_set_member() */ + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_indicate_mechs) { + major_status = m->gm_mech.gm_indicate_mechs( + minor_status, &set); + if (major_status) + continue; + major_status = GSS_S_COMPLETE; + for (i = 0; i < set->count; i++) { + major_status = gss_add_oid_set_member( + minor_status, &set->elements[i], mech_set); + if (major_status) + break; + } + gss_release_oid_set(minor_status, &set); + } else { + major_status = gss_add_oid_set_member( + minor_status, m->gm_mech_oid, mech_set); + } + if (major_status) + break; + } + + if (major_status) + gss_release_oid_set(&junk, mech_set); + + *minor_status = 0; + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_init_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_init_sec_context.c new file mode 100644 index 0000000..6d28938 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_init_sec_context.c @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_init_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +gss_cred_id_t +_gss_mg_find_mech_cred( + gss_const_cred_id_t cred_handle, + gss_const_OID mech_type) +{ + struct _gss_cred *cred = (struct _gss_cred *)cred_handle; + struct _gss_mechanism_cred *mc; + + if (cred == NULL) + return GSS_C_NO_CREDENTIAL; + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + if (gss_oid_equal(mech_type, mc->gmc_mech_oid)) + return mc->gmc_cred; + } + return GSS_C_NO_CREDENTIAL; +} + +static void +log_init_sec_context(struct _gss_context *ctx, + struct _gss_name *target, + OM_uint32 req_flags, + struct _gss_cred *cred, + gss_OID mech_type, + gss_buffer_t input_token) +{ + gssapi_mech_interface m; + + if (ctx) + m = ctx->gc_mech; + else + m = __gss_get_mechanism(mech_type); + if (m == NULL) + return; + + mech_type = &m->gm_mech_oid; + + _gss_mg_log(1, "gss_isc: %s %sfirst flags %08x, %s cred, %stoken", + m->gm_name, + (ctx == NULL) ? "" : "not ", + req_flags, + (cred != NULL) ? "specific" : "default", + (input_token != NULL && input_token->length) ? "" : "no "); + + _gss_mg_log_cred(1, cred, "gss_isc cred"); + + /* print target name */ + _gss_mg_log_name(1, target, mech_type, "gss_isc: target"); +} + +/** + * As the initiator build a context with an acceptor. + * + * Returns in the major + * - GSS_S_COMPLETE - if the context if build + * - GSS_S_CONTINUE_NEEDED - if the caller needs to continue another + * round of gss_i nit_sec_context + * - error code - any other error code + * + * @param minor_status minor status code. + * + * @param initiator_cred_handle the credential to use when building + * the context, if GSS_C_NO_CREDENTIAL is passed, the default + * credential for the mechanism will be used. + * + * @param context_handle a pointer to a context handle, will be + * returned as long as there is not an error. + * + * @param target_name the target name of acceptor, created using + * gss_import_name(). The name is can be of any name types the + * mechanism supports, check supported name types with + * gss_inquire_names_for_mech(). + * + * @param input_mech_type mechanism type to use, if GSS_C_NO_OID is + * used, Kerberos (GSS_KRB5_MECHANISM) will be tried. Other + * available mechanism are listed in the @ref gssapi_mechs_intro + * section. + * + * @param req_flags flags using when building the context, see @ref + * gssapi_context_flags + * + * @param time_req time requested this context should be valid in + * seconds, common used value is GSS_C_INDEFINITE + * + * @param input_chan_bindings Channel bindings used, if not exepected + * otherwise, used GSS_C_NO_CHANNEL_BINDINGS + * + * @param input_token input token sent from the acceptor, for the + * initial packet the buffer of { NULL, 0 } should be used. + * + * @param actual_mech_type the actual mech used, MUST NOT be freed + * since it pointing to static memory. + * + * @param output_token if there is an output token, regardless of + * complete, continue_needed, or error it should be sent to the + * acceptor + * + * @param ret_flags return what flags was negotitated, caller should + * check if they are accetable. For example, if + * GSS_C_MUTUAL_FLAG was negotiated with the acceptor or not. + * + * @param time_rec amount of time this context is valid for + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ + + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_init_sec_context(OM_uint32 * minor_status, + gss_const_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + gss_const_name_t target_name, + const gss_OID input_mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + gss_const_name_t mn_inner = GSS_C_NO_NAME; + struct _gss_name *name = (struct _gss_name *) target_name; + struct _gss_mechanism_name *mn; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + gss_const_cred_id_t cred_handle; + int allocated_ctx; + gss_OID mech_type = input_mech_type; + + *minor_status = 0; + + _mg_buffer_zero(output_token); + if (actual_mech_type) + *actual_mech_type = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + + if (mech_type == GSS_C_NO_OID) + mech_type = GSS_KRB5_MECHANISM; + + _gss_mg_check_name(target_name); + + if (_gss_mg_log_level(1)) + log_init_sec_context(ctx, name, req_flags, + (struct _gss_cred *)initiator_cred_handle, + input_mech_type, input_token); + + /* + * If we haven't allocated a context yet, do so now and lookup + * the mechanism switch table. If we have one already, make + * sure we use the same mechanism switch as before. + */ + if (!ctx) { + ctx = malloc(sizeof(struct _gss_context)); + if (!ctx) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + memset(ctx, 0, sizeof(struct _gss_context)); + m = ctx->gc_mech = __gss_get_mechanism(mech_type); + if (!m) { + free(ctx); + *minor_status = 0; + gss_mg_set_error_string(mech_type, GSS_S_BAD_MECH, + *minor_status, + "Unsupported mechanism requested"); + return (GSS_S_BAD_MECH); + } + allocated_ctx = 1; + } else { + m = ctx->gc_mech; + mech_type = &ctx->gc_mech->gm_mech_oid; + allocated_ctx = 0; + } + + /* + * Find the MN for this mechanism. + */ + if ((m->gm_flags & GM_USE_MG_NAME)) { + mn_inner = target_name; + } else { + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (major_status != GSS_S_COMPLETE) { + if (allocated_ctx) + free(ctx); + return major_status; + } + if (mn) + mn_inner = mn->gmn_name; + } + + /* + * If we have a cred, find the cred for this mechanism. + */ + if (m->gm_flags & GM_USE_MG_CRED) + cred_handle = initiator_cred_handle; + else + cred_handle = _gss_mg_find_mech_cred(initiator_cred_handle, mech_type); + + if (initiator_cred_handle != GSS_C_NO_CREDENTIAL && + cred_handle == NULL) { + *minor_status = 0; + if (allocated_ctx) + free(ctx); + gss_mg_set_error_string(mech_type, GSS_S_UNAVAILABLE, + *minor_status, + "Credential for the requested mechanism " + "not found in credential handle"); + return GSS_S_UNAVAILABLE; + } + + major_status = m->gm_init_sec_context(minor_status, + cred_handle, + &ctx->gc_ctx, + mn_inner, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + + if (major_status != GSS_S_COMPLETE + && major_status != GSS_S_CONTINUE_NEEDED) { + if (allocated_ctx) + free(ctx); + _mg_buffer_zero(output_token); + _gss_mg_error(m, *minor_status); + } else { + *context_handle = (gss_ctx_id_t) ctx; + } + + _gss_mg_log(1, "gss_isc: %s maj_stat: %d/%d", + m->gm_name, (int)major_status, (int)*minor_status); + + return (major_status); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_context.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_context.c new file mode 100644 index 0000000..6140696 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_context.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_context(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *xopen) +{ + OM_uint32 major_status; + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + struct _gss_name *name; + gss_name_t src_mn, targ_mn; + + if (locally_initiated) + *locally_initiated = 0; + if (xopen) + *xopen = 0; + if (lifetime_rec) + *lifetime_rec = 0; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (targ_name) + *targ_name = GSS_C_NO_NAME; + if (mech_type) + *mech_type = GSS_C_NO_OID; + src_mn = targ_mn = GSS_C_NO_NAME; + + if (ctx == NULL || ctx->gc_ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + m = ctx->gc_mech; + + major_status = m->gm_inquire_context(minor_status, + ctx->gc_ctx, + src_name ? &src_mn : NULL, + targ_name ? &targ_mn : NULL, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + xopen); + + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, *minor_status); + return (major_status); + } + + if (src_name && (m->gm_flags & GM_USE_MG_NAME)) { + *src_name = src_mn; + src_mn = GSS_C_NO_NAME; + } else if (src_name && src_mn) { + /* _gss_create_name() consumes `src_mn' on success */ + name = _gss_create_name(src_mn, m); + if (!name) { + if (mech_type) + *mech_type = GSS_C_NO_OID; + m->gm_release_name(minor_status, &src_mn); + *minor_status = 0; + return (GSS_S_FAILURE); + } + *src_name = (gss_name_t) name; + src_mn = GSS_C_NO_NAME; + } + + if (targ_name && (m->gm_flags & GM_USE_MG_NAME)) { + *targ_name = targ_mn; + } else if (targ_name && targ_mn) { + name = _gss_create_name(targ_mn, m); + if (!name) { + if (mech_type) + *mech_type = GSS_C_NO_OID; + if (src_name) + gss_release_name(minor_status, src_name); + m->gm_release_name(minor_status, &targ_mn); + *minor_status = 0; + return (GSS_S_FAILURE); + } + *targ_name = (gss_name_t) name; + targ_mn = GSS_C_NO_NAME; + } + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred.c new file mode 100644 index 0000000..305cae2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred.c @@ -0,0 +1,218 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +#define AUSAGE 1 +#define IUSAGE 2 + +static void +updateusage(gss_cred_usage_t usage, int *usagemask) +{ + if (usage == GSS_C_BOTH) + *usagemask |= AUSAGE | IUSAGE; + else if (usage == GSS_C_ACCEPT) + *usagemask |= AUSAGE; + else if (usage == GSS_C_INITIATE) + *usagemask |= IUSAGE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_cred(OM_uint32 *minor_status, + gss_const_cred_id_t cred_handle, + gss_name_t *name_ret, + OM_uint32 *lifetime, + gss_cred_usage_t *cred_usage, + gss_OID_set *mechanisms) +{ + OM_uint32 major_status; + struct _gss_mech_switch *m; + struct _gss_cred *cred = (struct _gss_cred *) cred_handle; + struct _gss_name *name; + struct _gss_mechanism_name *mn; + OM_uint32 min_lifetime; + int found = FALSE; + int usagemask = 0; + gss_cred_usage_t usage; + + _gss_load_mech(); + + *minor_status = 0; + if (name_ret) + *name_ret = GSS_C_NO_NAME; + if (lifetime) + *lifetime = 0; + if (cred_usage) + *cred_usage = 0; + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; + + if (name_ret) { + name = _gss_create_name(NULL, NULL); + if (name == NULL) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + } else { + name = NULL; + } + + if (mechanisms) { + major_status = gss_create_empty_oid_set(minor_status, + mechanisms); + if (major_status) { + if (name) free(name); + return (major_status); + } + } + + min_lifetime = GSS_C_INDEFINITE; + if (cred) { + struct _gss_mechanism_cred *mc; + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + gss_name_t mc_name = GSS_C_NO_NAME; + OM_uint32 mc_lifetime = GSS_C_INDEFINITE; + + heim_assert((mc->gmc_mech->gm_flags & GM_USE_MG_CRED) == 0, + "should not have mech creds for GM_USE_MG_CRED mechs"); + + if (mc->gmc_mech->gm_inquire_cred == NULL) + continue; + + major_status = mc->gmc_mech->gm_inquire_cred(minor_status, + mc->gmc_cred, &mc_name, &mc_lifetime, &usage, NULL); + if (major_status) + continue; + + updateusage(usage, &usagemask); + if (name) { + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) { + mc->gmc_mech->gm_release_name(minor_status, + &mc_name); + continue; + } + mn->gmn_mech = mc->gmc_mech; + mn->gmn_mech_oid = mc->gmc_mech_oid; + mn->gmn_name = mc_name; + HEIM_TAILQ_INSERT_TAIL(&name->gn_mn, mn, gmn_link); + } else { + mc->gmc_mech->gm_release_name(minor_status, + &mc_name); + } + + if (mc_lifetime < min_lifetime) + min_lifetime = mc_lifetime; + + if (mechanisms) + gss_add_oid_set_member(minor_status, + mc->gmc_mech_oid, mechanisms); + found = TRUE; + } + } else { + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + gss_name_t mc_name; + OM_uint32 mc_lifetime; + + if (m->gm_mech.gm_inquire_cred == NULL || + (m->gm_mech.gm_flags & GM_USE_MG_CRED)) + continue; + + major_status = m->gm_mech.gm_inquire_cred(minor_status, + GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime, + &usage, NULL); + if (major_status) + continue; + + updateusage(usage, &usagemask); + if (name && mc_name) { + mn = malloc( + sizeof(struct _gss_mechanism_name)); + if (!mn) { + m->gm_mech.gm_release_name( + minor_status, &mc_name); + continue; + } + mn->gmn_mech = &m->gm_mech; + mn->gmn_mech_oid = m->gm_mech_oid; + mn->gmn_name = mc_name; + HEIM_TAILQ_INSERT_TAIL(&name->gn_mn, mn, gmn_link); + } else if (mc_name) { + m->gm_mech.gm_release_name(minor_status, + &mc_name); + } + + if (mc_lifetime < min_lifetime) + min_lifetime = mc_lifetime; + + if (mechanisms) + gss_add_oid_set_member(minor_status, + m->gm_mech_oid, mechanisms); + found = TRUE; + } + } + + if (found && mechanisms) { + /* GM_USE_MG_CRED mechs (SPNEGO) always can be used */ + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if ((m->gm_mech.gm_flags & GM_USE_MG_CRED) == 0) + continue; + + gss_add_oid_set_member(minor_status, + m->gm_mech_oid, mechanisms); + } + } + + if (found == FALSE || min_lifetime == 0) { + gss_name_t n = (gss_name_t)name; + if (n) + gss_release_name(minor_status, &n); + gss_release_oid_set(minor_status, mechanisms); + *minor_status = 0; + if (min_lifetime == 0) + return (GSS_S_CREDENTIALS_EXPIRED); + + return (GSS_S_NO_CRED); + } + + *minor_status = 0; + if (name_ret) + *name_ret = (gss_name_t) name; + if (lifetime) + *lifetime = min_lifetime; + if (cred_usage) { + if ((usagemask & (AUSAGE|IUSAGE)) == (AUSAGE|IUSAGE)) + *cred_usage = GSS_C_BOTH; + else if (usagemask & IUSAGE) + *cred_usage = GSS_C_INITIATE; + else if (usagemask & AUSAGE) + *cred_usage = GSS_C_ACCEPT; + } + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c new file mode 100644 index 0000000..10ba9b7 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_cred_by_mech.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_cred_by_mech(OM_uint32 *minor_status, + gss_const_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t *cred_name, + OM_uint32 *initiator_lifetime, + OM_uint32 *acceptor_lifetime, + gss_cred_usage_t *cred_usage) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + struct _gss_mechanism_cred *mcp; + gss_cred_id_t mc; + gss_name_t mn; + struct _gss_name *name; + + *minor_status = 0; + if (cred_name) + *cred_name = GSS_C_NO_NAME; + if (initiator_lifetime) + *initiator_lifetime = 0; + if (acceptor_lifetime) + *acceptor_lifetime = 0; + if (cred_usage) + *cred_usage = 0; + + m = __gss_get_mechanism(mech_type); + if (m == NULL || m->gm_inquire_cred_by_mech == NULL) + return (GSS_S_NO_CRED); + + if (cred_handle != GSS_C_NO_CREDENTIAL) { + struct _gss_cred *cred = (struct _gss_cred *) cred_handle; + HEIM_TAILQ_FOREACH(mcp, &cred->gc_mc, gmc_link) + if (mcp->gmc_mech == m) + break; + if (!mcp) + return (GSS_S_NO_CRED); + mc = mcp->gmc_cred; + } else { + mc = GSS_C_NO_CREDENTIAL; + } + + major_status = m->gm_inquire_cred_by_mech(minor_status, mc, mech_type, + &mn, initiator_lifetime, acceptor_lifetime, cred_usage); + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, *minor_status); + return (major_status); + } + + if (cred_name) { + name = _gss_create_name(mn, m); + if (!name) { + m->gm_release_name(minor_status, &mn); + return (GSS_S_NO_CRED); + } + *cred_name = (gss_name_t) name; + } else + m->gm_release_name(minor_status, &mn); + + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c new file mode 100644 index 0000000..4e7c73f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_cred_by_oid (OM_uint32 *minor_status, + gss_const_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + struct _gss_cred *cred = (struct _gss_cred *) cred_handle; + OM_uint32 status = GSS_S_COMPLETE; + struct _gss_mechanism_cred *mc; + gssapi_mech_interface m; + gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + if (cred == NULL) + return GSS_S_NO_CRED; + + status = GSS_S_FAILURE; + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + gss_buffer_set_t rset = GSS_C_NO_BUFFER_SET; + size_t i; + + m = mc->gmc_mech; + if (m == NULL) { + _gss_secure_release_buffer_set(minor_status, &set); + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + if (m->gm_inquire_cred_by_oid == NULL) + continue; + + status = m->gm_inquire_cred_by_oid(minor_status, + mc->gmc_cred, desired_object, &rset); + if (status != GSS_S_COMPLETE) { + _gss_mg_error(m, *minor_status); + continue; + } + + for (i = 0; rset != NULL && i < rset->count; i++) { + status = gss_add_buffer_set_member(minor_status, + &rset->elements[i], &set); + if (status != GSS_S_COMPLETE) + break; + } + _gss_secure_release_buffer_set(minor_status, &rset); + } + if (set == GSS_C_NO_BUFFER_SET && status == GSS_S_COMPLETE) + status = GSS_S_FAILURE; + *data_set = set; + *minor_status = 0; + return status; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c new file mode 100644 index 0000000..f75dbaa --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_mechs_for_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_mechs_for_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + gss_OID_set *mech_types) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mech_switch *m; + gss_OID_set name_types; + int present; + + *minor_status = 0; + + _gss_load_mech(); + + major_status = gss_create_empty_oid_set(minor_status, mech_types); + if (major_status) + return (major_status); + + /* + * We go through all the loaded mechanisms and see if this + * name's type is supported by the mechanism. If it is, add + * the mechanism to the set. + */ + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + major_status = gss_inquire_names_for_mech(minor_status, + m->gm_mech_oid, &name_types); + if (major_status) { + gss_release_oid_set(minor_status, mech_types); + return (major_status); + } + gss_test_oid_set_member(minor_status, + name->gn_type, name_types, &present); + gss_release_oid_set(minor_status, &name_types); + if (present) { + major_status = gss_add_oid_set_member(minor_status, + m->gm_mech_oid, mech_types); + if (major_status) { + gss_release_oid_set(minor_status, mech_types); + return (major_status); + } + } + } + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_name.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_name.c new file mode 100644 index 0000000..f109a9f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_name.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_name(OM_uint32 *minor_status, + gss_name_t input_name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + if (name_is_MN != NULL) + *name_is_MN = 0; + if (MN_mech != NULL) + *MN_mech = GSS_C_NO_OID; + if (attrs != NULL) + *attrs = GSS_C_NO_BUFFER_SET; + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (!m->gm_inquire_name) + continue; + + major_status = m->gm_inquire_name(minor_status, + mn->gmn_name, + NULL, + MN_mech, + attrs); + if (major_status == GSS_S_COMPLETE) { + if (name_is_MN != NULL) + *name_is_MN = 1; + if (MN_mech != NULL && *MN_mech == GSS_C_NO_OID) + *MN_mech = &m->gm_mech_oid; + break; + } + _gss_mg_error(m, *minor_status); + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c new file mode 100644 index 0000000..595ab73 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_names_for_mech.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_names_for_mech(OM_uint32 *minor_status, + const gss_OID mechanism, + gss_OID_set *name_types) +{ + OM_uint32 major_status; + gssapi_mech_interface m = __gss_get_mechanism(mechanism); + + *minor_status = 0; + *name_types = GSS_C_NO_OID_SET; + if (!m) + return (GSS_S_BAD_MECH); + + /* + * If the implementation can do it, ask it for a list of + * names, otherwise fake it. + */ + if (m->gm_inquire_names_for_mech) { + return (m->gm_inquire_names_for_mech(minor_status, + mechanism, name_types)); + } else { + major_status = gss_create_empty_oid_set(minor_status, + name_types); + if (major_status) + return (major_status); + major_status = gss_add_oid_set_member(minor_status, + GSS_C_NT_HOSTBASED_SERVICE, name_types); + if (major_status) { + OM_uint32 junk; + gss_release_oid_set(&junk, name_types); + return (major_status); + } + major_status = gss_add_oid_set_member(minor_status, + GSS_C_NT_USER_NAME, name_types); + if (major_status) { + OM_uint32 junk; + gss_release_oid_set(&junk, name_types); + return (major_status); + } + } + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c b/third_party/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c new file mode 100644 index 0000000..55ff671 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + OM_uint32 major_status; + gssapi_mech_interface m; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + m = ctx->gc_mech; + + if (m == NULL) + return GSS_S_BAD_MECH; + + if (m->gm_inquire_sec_context_by_oid != NULL) { + major_status = m->gm_inquire_sec_context_by_oid(minor_status, + ctx->gc_ctx, desired_object, data_set); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, *minor_status); + } else + major_status = GSS_S_BAD_MECH; + + return major_status; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_krb5.c b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c new file mode 100644 index 0000000..78c3056 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c @@ -0,0 +1,927 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_krb5.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +#include "krb5/gsskrb5_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_copy_ccache(OM_uint32 *minor_status, + gss_cred_id_t cred, + krb5_ccache out) +{ + gss_key_value_element_desc cred_store_kvs[1]; + gss_key_value_set_desc cred_store; + krb5_context context; + OM_uint32 major = GSS_S_FAILURE; + char *fullname = NULL; + + GSSAPI_KRB5_INIT(&context); + *minor_status = krb5_cc_get_full_name(context, out, &fullname); + if (*minor_status == 0) { + cred_store_kvs[0].key = "ccache"; + cred_store_kvs[0].value = fullname; + cred_store.count = 1; + cred_store.elements = cred_store_kvs; + major = gss_store_cred_into2(minor_status, cred, GSS_C_INITIATE, + GSS_KRB5_MECHANISM, + GSS_C_STORE_CRED_OVERWRITE, &cred_store, + NULL, NULL, NULL); + free(fullname); + } + return major; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_import_cred(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal keytab_principal, + krb5_keytab keytab, + gss_cred_id_t *cred) +{ + gss_buffer_desc buffer; + OM_uint32 major_status; + krb5_context context; + krb5_error_code ret; + krb5_storage *sp; + krb5_data data; + char *str; + + *cred = GSS_C_NO_CREDENTIAL; + + ret = krb5_init_context(&context); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto out; + } + + if (id) { + ret = krb5_cc_get_full_name(context, id, &str); + if (ret == 0) { + ret = krb5_store_string(sp, str); + free(str); + } + } else + ret = krb5_store_string(sp, ""); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto out; + } + + if (keytab_principal) { + ret = krb5_unparse_name(context, keytab_principal, &str); + if (ret == 0) { + ret = krb5_store_string(sp, str); + free(str); + } + } else + krb5_store_string(sp, ""); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto out; + } + + + if (keytab) { + ret = krb5_kt_get_full_name(context, keytab, &str); + if (ret == 0) { + ret = krb5_store_string(sp, str); + free(str); + } + } else + krb5_store_string(sp, ""); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto out; + } + + ret = krb5_storage_to_data(sp, &data); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto out; + } + + buffer.value = data.data; + buffer.length = data.length; + + major_status = gss_set_cred_option(minor_status, + cred, + GSS_KRB5_IMPORT_CRED_X, + &buffer); + krb5_data_free(&data); +out: + if (sp) + krb5_storage_free(sp); + krb5_free_context(context); + return major_status; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_register_acceptor_identity(const char *identity) +{ + gssapi_mech_interface m; + gss_buffer_desc buffer; + OM_uint32 junk; + + _gss_load_mech(); + + buffer.value = rk_UNCONST(identity); + buffer.length = strlen(identity); + + m = __gss_get_mechanism(GSS_KRB5_MECHANISM); + if (m == NULL || m->gm_set_sec_context_option == NULL) + return GSS_S_FAILURE; + + return m->gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +krb5_gss_register_acceptor_identity(const char *identity) +{ + return gsskrb5_register_acceptor_identity(identity); +} + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_dns_canonicalize(int flag) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + char b = (flag != 0); + + _gss_load_mech(); + + buffer.value = &b; + buffer.length = sizeof(b); + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer); + } + + return (GSS_S_COMPLETE); +} + + + +static krb5_error_code +set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key) +{ + key->type = keyblock->keytype; + key->length = keyblock->keyvalue.length; + key->data = malloc(key->length); + if (key->data == NULL && key->length != 0) + return ENOMEM; + memcpy(key->data, keyblock->keyvalue.data, key->length); + return 0; +} + +static void +free_key(gss_krb5_lucid_key_t *key) +{ + memset(key->data, 0, key->length); + free(key->data); + memset(key, 0, sizeof(*key)); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **rctx) +{ + krb5_context context = NULL; + krb5_error_code ret; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 major_status; + gss_krb5_lucid_context_v1_t *ctx = NULL; + krb5_storage *sp = NULL; + uint32_t num; + + if (context_handle == NULL + || *context_handle == GSS_C_NO_CONTEXT + || version != 1) + { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + major_status = + gss_inquire_sec_context_by_oid (minor_status, + *context_handle, + GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X, + &data_set); + if (major_status) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = krb5_init_context(&context); + if (ret) + goto out; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + ret = ENOMEM; + goto out; + } + + sp = krb5_storage_from_mem(data_set->elements[0].value, + data_set->elements[0].length); + if (sp == NULL) { + ret = ENOMEM; + goto out; + } + + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + if (num != 1) { + ret = EINVAL; + goto out; + } + ctx->version = 1; + /* initiator */ + ret = krb5_ret_uint32(sp, &ctx->initiate); + if (ret) goto out; + /* endtime */ + ret = krb5_ret_uint32(sp, &ctx->endtime); + if (ret) goto out; + /* send_seq */ + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->send_seq = ((uint64_t)num) << 32; + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->send_seq |= num; + /* recv_seq */ + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->recv_seq = ((uint64_t)num) << 32; + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->recv_seq |= num; + /* protocol */ + ret = krb5_ret_uint32(sp, &ctx->protocol); + if (ret) goto out; + if (ctx->protocol == 0) { + krb5_keyblock key; + + /* sign_alg */ + ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg); + if (ret) goto out; + /* seal_alg */ + ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg); + if (ret) goto out; + /* ctx_key */ + ret = krb5_ret_keyblock(sp, &key); + if (ret) goto out; + ret = set_key(&key, &ctx->rfc1964_kd.ctx_key); + krb5_free_keyblock_contents(context, &key); + if (ret) goto out; + } else if (ctx->protocol == 1) { + krb5_keyblock key; + + /* acceptor_subkey */ + ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey); + if (ret) goto out; + /* ctx_key */ + ret = krb5_ret_keyblock(sp, &key); + if (ret) goto out; + ret = set_key(&key, &ctx->cfx_kd.ctx_key); + krb5_free_keyblock_contents(context, &key); + if (ret) goto out; + /* acceptor_subkey */ + if (ctx->cfx_kd.have_acceptor_subkey) { + ret = krb5_ret_keyblock(sp, &key); + if (ret) goto out; + ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey); + krb5_free_keyblock_contents(context, &key); + if (ret) goto out; + } + } else { + ret = EINVAL; + goto out; + } + + *rctx = ctx; + +out: + _gss_secure_release_buffer_set(minor_status, &data_set); + if (sp) + krb5_storage_free(sp); + if (context) + krb5_free_context(context); + + if (ret) { + OM_uint32 junk; + if (ctx) + gss_krb5_free_lucid_sec_context(&junk, ctx); + + *minor_status = ret; + return GSS_S_FAILURE; + } + *minor_status = 0; + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c) +{ + gss_krb5_lucid_context_v1_t *ctx = c; + + if (ctx->version != 1) { + if (minor_status) + *minor_status = 0; + return GSS_S_FAILURE; + } + + if (ctx->protocol == 0) { + free_key(&ctx->rfc1964_kd.ctx_key); + } else if (ctx->protocol == 1) { + free_key(&ctx->cfx_kd.ctx_key); + if (ctx->cfx_kd.have_acceptor_subkey) + free_key(&ctx->cfx_kd.acceptor_subkey); + } + free(ctx); + if (minor_status) + *minor_status = 0; + return GSS_S_COMPLETE; +} + +/* + * + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t cred, + OM_uint32 num_enctypes, + int32_t *enctypes) +{ + krb5_error_code ret; + OM_uint32 maj_status; + gss_buffer_desc buffer; + krb5_storage *sp; + krb5_data data; + size_t i; + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + maj_status = GSS_S_FAILURE; + goto out; + } + + for (i = 0; i < num_enctypes; i++) { + ret = krb5_store_int32(sp, enctypes[i]); + if (ret) { + *minor_status = ret; + maj_status = GSS_S_FAILURE; + goto out; + } + } + + ret = krb5_storage_to_data(sp, &data); + if (ret) { + *minor_status = ret; + maj_status = GSS_S_FAILURE; + goto out; + } + + buffer.value = data.data; + buffer.length = data.length; + + maj_status = gss_set_cred_option(minor_status, + &cred, + GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X, + &buffer); + krb5_data_free(&data); +out: + if (sp) + krb5_storage_free(sp); + return maj_status; +} + +/* + * + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + + _gss_load_mech(); + + if (c) { + buffer.value = c; + buffer.length = sizeof(*c); + } else { + buffer.value = NULL; + buffer.length = 0; + } + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_SEND_TO_KDC_X, &buffer); + } + + return (GSS_S_COMPLETE); +} + +/* + * + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_ccache_name(OM_uint32 *minor_status, + const char *name, + const char **out_name) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER; + OM_uint32 major_status; + struct gsskrb5_ccache_name_args args; + + _gss_load_mech(); + + *minor_status = 0; + + if (out_name) + *out_name = NULL; + + args.name = name; + args.out_name = NULL; + + buffer.value = &args; + buffer.length = sizeof(args); + + major_status = GSS_S_UNAVAILABLE; + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + OM_uint32 mech_major, mech_minor; + + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + + mech_major = m->gm_mech.gm_set_sec_context_option(&mech_minor, + NULL, GSS_KRB5_CCACHE_NAME_X, &buffer); + if (mech_major != GSS_S_UNAVAILABLE) { + major_status = mech_major; + *minor_status = mech_minor; + break; + } + } + + if (out_name) + *out_name = args.out_name; + + return major_status; +} + + +/* + * + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + time_t *authtime) +{ + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 maj_stat; + + if (context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + maj_stat = + gss_inquire_sec_context_by_oid (minor_status, + context_handle, + GSS_KRB5_GET_AUTHTIME_X, + &data_set); + if (maj_stat) + return maj_stat; + + if (data_set == GSS_C_NO_BUFFER_SET) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (data_set->count != 1) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (data_set->elements[0].length != 4) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + { + unsigned char *buf = data_set->elements[0].value; + *authtime = ((unsigned long)buf[3] <<24) | (buf[2] << 16) | + (buf[1] << 8) | (buf[0] << 0); + } + + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +/* + * + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int ad_type, + gss_buffer_t ad_data) +{ + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 maj_stat, tmp; + gss_OID_desc oid_flat; + heim_oid baseoid, oid; + size_t size; + + if (context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + /* All this to append an integer to an oid... */ + + if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length, + &baseoid, NULL) != 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + oid.length = baseoid.length + 1; + oid.components = calloc(oid.length, sizeof(*oid.components)); + if (oid.components == NULL) { + der_free_oid(&baseoid); + + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy(oid.components, baseoid.components, + baseoid.length * sizeof(*baseoid.components)); + + der_free_oid(&baseoid); + + oid.components[oid.length - 1] = ad_type; + + oid_flat.length = (OM_uint32)der_length_oid(&oid); + oid_flat.elements = malloc(oid_flat.length); + if (oid_flat.elements == NULL) { + free(oid.components); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1, + oid_flat.length, &oid, &size) != 0) { + free(oid.components); + _gss_free_oid(&tmp, &oid_flat); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + if (oid_flat.length != size) + abort(); + + free(oid.components); + + /* FINALLY, we have the OID */ + + maj_stat = gss_inquire_sec_context_by_oid (minor_status, + context_handle, + &oid_flat, + &data_set); + + _gss_free_oid(&tmp, &oid_flat); + + if (maj_stat) + return maj_stat; + + if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ad_data->value = malloc(data_set->elements[0].length); + if (ad_data->value == NULL) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ad_data->length = data_set->elements[0].length; + memcpy(ad_data->value, data_set->elements[0].value, ad_data->length); + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +/* + * + */ + +static OM_uint32 +gsskrb5_extract_key(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + const gss_OID oid, + krb5_keyblock **keyblock) +{ + krb5_error_code ret; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 major_status; + krb5_context context = NULL; + krb5_storage *sp = NULL; + + if (context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = krb5_init_context(&context); + if(ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + major_status = + gss_inquire_sec_context_by_oid (minor_status, + context_handle, + oid, + &data_set); + if (major_status) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { + _gss_secure_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + sp = krb5_storage_from_mem(data_set->elements[0].value, + data_set->elements[0].length); + if (sp == NULL) { + ret = ENOMEM; + goto out; + } + + *keyblock = calloc(1, sizeof(**keyblock)); + if (*keyblock == NULL) { + ret = ENOMEM; + goto out; + } + + ret = krb5_ret_keyblock(sp, *keyblock); + +out: + _gss_secure_release_buffer_set(minor_status, &data_set); + if (sp) + krb5_storage_free(sp); + if (ret && keyblock) { + krb5_free_keyblock(context, *keyblock); + *keyblock = NULL; + } + if (context) + krb5_free_context(context); + + *minor_status = ret; + if (ret) + return GSS_S_FAILURE; + + return GSS_S_COMPLETE; +} + +/* + * + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_extract_service_keyblock(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_keyblock **keyblock) +{ + return gsskrb5_extract_key(minor_status, + context_handle, + GSS_KRB5_GET_SERVICE_KEYBLOCK_X, + keyblock); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_keyblock **keyblock) +{ + return gsskrb5_extract_key(minor_status, + context_handle, + GSS_KRB5_GET_INITIATOR_SUBKEY_X, + keyblock); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_get_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_keyblock **keyblock) +{ + return gsskrb5_extract_key(minor_status, + context_handle, + GSS_KRB5_GET_SUBKEY_X, + keyblock); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_default_realm(const char *realm) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + + _gss_load_mech(); + + buffer.value = rk_UNCONST(realm); + buffer.length = strlen(realm); + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_SET_DEFAULT_REALM_X, &buffer); + } + + return (GSS_S_COMPLETE); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_krb5_get_tkt_flags(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + OM_uint32 *tkt_flags) +{ + + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + major_status = + gss_inquire_sec_context_by_oid (minor_status, + context_handle, + GSS_KRB5_GET_TKT_FLAGS_X, + &data_set); + if (major_status) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length < 4) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + { + const u_char *p = data_set->elements[0].value; + *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + } + + gss_release_buffer_set(minor_status, &data_set); + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_set_time_offset(int offset) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + int32_t o = offset; + + _gss_load_mech(); + + buffer.value = &o; + buffer.length = sizeof(o); + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_SET_TIME_OFFSET_X, &buffer); + } + + return (GSS_S_COMPLETE); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_get_time_offset(int *offset) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 maj_stat, junk; + int32_t o; + + _gss_load_mech(); + + buffer.value = &o; + buffer.length = sizeof(o); + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + maj_stat = m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_GET_TIME_OFFSET_X, &buffer); + + if (maj_stat == GSS_S_COMPLETE) { + *offset = o; + return maj_stat; + } + } + + return (GSS_S_UNAVAILABLE); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gsskrb5_plugin_register(struct gsskrb5_krb5_plugin *c) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + + _gss_load_mech(); + + buffer.value = c; + buffer.length = sizeof(*c); + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_PLUGIN_REGISTER_X, &buffer); + } + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c new file mode 100644 index 0000000..372e72d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c @@ -0,0 +1,585 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_mech_switch.c,v 1.2 2006/02/04 09:40:21 dfr Exp $ + */ + +#include "mech_locl.h" +#include <heim_threads.h> + +#ifndef _PATH_GSS_MECH +#define _PATH_GSS_MECH "/etc/gss/mech" +#endif + +struct _gss_mech_switch_list _gss_mechs = { NULL, NULL } ; +gss_OID_set _gss_mech_oids; +static HEIMDAL_MUTEX _gss_mech_mutex = HEIMDAL_MUTEX_INITIALIZER; + +/* + * Convert a string containing an OID in 'dot' form + * (e.g. 1.2.840.113554.1.2.2) to a gss_OID. + */ +static int +_gss_string_to_oid(const char* s, gss_OID *oidp) +{ + int number_count, i, j; + size_t byte_count; + const char *p, *q; + char *res; + gss_OID_desc oid; + + *oidp = GSS_C_NO_OID; + + /* + * First figure out how many numbers in the oid, then + * calculate the compiled oid size. + */ + number_count = 0; + for (p = s; p; p = q) { + q = strchr(p, '.'); + if (q) q = q + 1; + number_count++; + } + + /* + * The first two numbers are in the first byte and each + * subsequent number is encoded in a variable byte sequence. + */ + if (number_count < 2) + return (EINVAL); + + /* + * We do this in two passes. The first pass, we just figure + * out the size. Second time around, we actually encode the + * number. + */ + res = 0; + for (i = 0; i < 2; i++) { + byte_count = 0; + for (p = s, j = 0; p; p = q, j++) { + unsigned int number = 0; + + /* + * Find the end of this number. + */ + q = strchr(p, '.'); + if (q) q = q + 1; + + /* + * Read the number of of the string. Don't + * bother with anything except base ten. + */ + while (*p && *p != '.') { + number = 10 * number + (*p - '0'); + p++; + } + + /* + * Encode the number. The first two numbers + * are packed into the first byte. Subsequent + * numbers are encoded in bytes seven bits at + * a time with the last byte having the high + * bit set. + */ + if (j == 0) { + if (res) + *res = number * 40; + } else if (j == 1) { + if (res) { + *res += number; + res++; + } + byte_count++; + } else if (j >= 2) { + /* + * The number is encoded in seven bit chunks. + */ + unsigned int t; + unsigned int bytes; + + bytes = 0; + for (t = number; t; t >>= 7) + bytes++; + if (bytes == 0) bytes = 1; + while (bytes) { + if (res) { + int bit = 7*(bytes-1); + + *res = (number >> bit) & 0x7f; + if (bytes != 1) + *res |= 0x80; + res++; + } + byte_count++; + bytes--; + } + } + } + if (byte_count == 0) + return EINVAL; + if (!res) { + res = malloc(byte_count); + if (!res) + return (ENOMEM); + oid.length = byte_count; + oid.elements = res; + } + } + + { + OM_uint32 minor_status, tmp; + + if (GSS_ERROR(_gss_intern_oid(&minor_status, &oid, oidp))) { + _gss_free_oid(&tmp, &oid); + return (minor_status); + } + + _gss_free_oid(&tmp, &oid); + } + + return (0); +} + +#define SYM(name) \ +do { \ + m->gm_mech.gm_ ## name = (_gss_##name##_t *)dlsym(so, "gss_" #name); \ + if (!m->gm_mech.gm_ ## name || \ + m->gm_mech.gm_ ##name == gss_ ## name) { \ + _gss_mg_log(1, "can't find symbol gss_" #name "\n"); \ + goto bad; \ + } \ +} while (0) + +#define OPTSYM(name) \ +do { \ + m->gm_mech.gm_ ## name = (_gss_##name##_t *)dlsym(so, "gss_" #name); \ + if (m->gm_mech.gm_ ## name == gss_ ## name) \ + m->gm_mech.gm_ ## name = NULL; \ +} while (0) + +/* mech exports gssspi_XXX, internally referred to as gss_XXX */ +#define OPTSPISYM(name) \ +do { \ + m->gm_mech.gm_ ## name = (_gss_##name##_t *)dlsym(so, "gssspi_" #name); \ +} while (0) + +/* mech exports gssspi_XXX, internally referred to as gssspi_XXX */ +#define OPTSPISPISYM(name) \ +do { \ + m->gm_mech.gm_ ## name = (_gss_##name##_t *)dlsym(so, "gssspi_" #name); \ + if (m->gm_mech.gm_ ## name == gssspi_ ## name) \ + m->gm_mech.gm_ ## name = NULL; \ +} while (0) + +#define COMPATSYM(name) \ +do { \ + m->gm_mech.gm_compat->gmc_ ## name = (_gss_##name##_t *)dlsym(so, "gss_" #name); \ + if (m->gm_mech.gm_compat->gmc_ ## name == gss_ ## name) \ + m->gm_mech.gm_compat->gmc_ ## name = NULL; \ +} while (0) + +#define COMPATSPISYM(name) \ +do { \ + m->gm_mech.gm_compat->gmc_ ## name = (_gss_##name##_t *)dlsym(so, "gssspi_" #name); \ + if (m->gm_mech.gm_compat->gmc_ ## name == gss_ ## name) \ + m->gm_mech.gm_compat->gmc_ ## name = NULL; \ +} while (0) + +/* + * + */ +static int +add_builtin(gssapi_mech_interface mech) +{ + struct _gss_mech_switch *m; + OM_uint32 minor_status; + + /* not registering any mech is ok */ + if (mech == NULL) + return 0; + + m = calloc(1, sizeof(*m)); + if (m == NULL) + return ENOMEM; + m->gm_so = NULL; + m->gm_mech = *mech; + _gss_intern_oid(&minor_status, &mech->gm_mech_oid, &m->gm_mech_oid); + if (minor_status) { + free(m); + return minor_status; + } + + if (gss_add_oid_set_member(&minor_status, &m->gm_mech.gm_mech_oid, + &_gss_mech_oids) != GSS_S_COMPLETE) { + free(m); + return ENOMEM; + } + + /* pick up the oid sets of names */ + + if (m->gm_mech.gm_inquire_names_for_mech) + (*m->gm_mech.gm_inquire_names_for_mech)(&minor_status, + &m->gm_mech.gm_mech_oid, &m->gm_name_types); + + if (m->gm_name_types == NULL && + gss_create_empty_oid_set(&minor_status, + &m->gm_name_types) != GSS_S_COMPLETE) { + free(m); + return ENOMEM; + } + + HEIM_TAILQ_INSERT_TAIL(&_gss_mechs, m, gm_link); + return 0; +} + +static void +init_mech_switch_list(void *p) +{ + struct _gss_mech_switch_list *mechs = p; + + HEIM_TAILQ_INIT(mechs); +} + +/* + * Load the mechanisms file (/etc/gss/mech). + */ +void +_gss_load_mech(void) +{ + OM_uint32 major_status, minor_status; + static heim_base_once_t once = HEIM_BASE_ONCE_INIT; +#ifdef HAVE_DLOPEN + FILE *fp; + char buf[256]; + char *p; + char *name, *oid, *lib, *kobj; + struct _gss_mech_switch *m; + void *so; + gss_OID mech_oid; + int found; + const char *conf = secure_getenv("GSS_MECH_CONFIG"); +#endif + + heim_base_once_f(&once, &_gss_mechs, init_mech_switch_list); + + HEIMDAL_MUTEX_lock(&_gss_mech_mutex); + + if (!HEIM_TAILQ_EMPTY(&_gss_mechs)) { + HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); + return; + } + + major_status = gss_create_empty_oid_set(&minor_status, + &_gss_mech_oids); + if (major_status) { + HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); + return; + } + + if (add_builtin(__gss_krb5_initialize())) + _gss_mg_log(1, "Out of memory while adding builtin Kerberos GSS " + "mechanism to the GSS mechanism switch"); + if (add_builtin(__gss_spnego_initialize())) + _gss_mg_log(1, "Out of memory while adding builtin SPNEGO " + "mechanism to the GSS mechanism switch"); + if (add_builtin(__gss_ntlm_initialize())) + _gss_mg_log(1, "Out of memory while adding builtin NTLM " + "mechanism to the GSS mechanism switch"); + +#ifdef HAVE_DLOPEN + fp = fopen(conf ? conf : _PATH_GSS_MECH, "r"); + if (!fp) + goto out; + rk_cloexec_file(fp); + + while (fgets(buf, sizeof(buf), fp)) { + _gss_mo_init *mi; + + if (*buf == '#') + continue; + p = buf; + name = strsep(&p, "\t\n "); + if (p) while (isspace((unsigned char)*p)) p++; + oid = strsep(&p, "\t\n "); + if (p) while (isspace((unsigned char)*p)) p++; + lib = strsep(&p, "\t\n "); + if (p) while (isspace((unsigned char)*p)) p++; + kobj = strsep(&p, "\t\n "); + if (!name || !oid || !lib || !kobj) + continue; + + if (_gss_string_to_oid(oid, &mech_oid)) + continue; + + /* + * Check for duplicates, already loaded mechs. + */ + found = 0; + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech_oid)) { + found = 1; + break; + } + } + if (found) + continue; + + so = dlopen(lib, RTLD_LAZY | RTLD_LOCAL | RTLD_GROUP); + if (so == NULL) { + _gss_mg_log(1, "dlopen: %s\n", dlerror()); + goto bad; + } + + m = calloc(1, sizeof(*m)); + if (m == NULL) + goto bad; + + m->gm_so = so; + m->gm_mech_oid = mech_oid; + m->gm_mech.gm_name = strdup(name); + m->gm_mech.gm_mech_oid = *mech_oid; + m->gm_mech.gm_flags = 0; + m->gm_mech.gm_compat = calloc(1, sizeof(struct gss_mech_compat_desc_struct)); + if (m->gm_mech.gm_compat == NULL) + goto bad; + + major_status = gss_add_oid_set_member(&minor_status, + &m->gm_mech.gm_mech_oid, &_gss_mech_oids); + if (GSS_ERROR(major_status)) + goto bad; + + SYM(acquire_cred); + SYM(release_cred); + SYM(init_sec_context); + SYM(accept_sec_context); + SYM(process_context_token); + SYM(delete_sec_context); + SYM(context_time); + SYM(get_mic); + SYM(verify_mic); + SYM(wrap); + SYM(unwrap); + OPTSYM(display_status); + OPTSYM(indicate_mechs); + SYM(compare_name); + SYM(display_name); + SYM(import_name); + SYM(export_name); + SYM(release_name); + OPTSYM(inquire_cred); + SYM(inquire_context); + SYM(wrap_size_limit); + OPTSYM(add_cred); + OPTSYM(inquire_cred_by_mech); + SYM(export_sec_context); + SYM(import_sec_context); + OPTSYM(inquire_names_for_mech); + OPTSYM(inquire_mechs_for_name); + SYM(canonicalize_name); + SYM(duplicate_name); + OPTSYM(inquire_cred_by_oid); + OPTSYM(inquire_sec_context_by_oid); + OPTSYM(set_sec_context_option); + OPTSPISYM(set_cred_option); + OPTSYM(pseudo_random); + OPTSYM(wrap_iov); + OPTSYM(unwrap_iov); + OPTSYM(wrap_iov_length); + OPTSYM(store_cred); + OPTSYM(export_cred); + OPTSYM(import_cred); + OPTSYM(acquire_cred_from); + OPTSYM(acquire_cred_impersonate_name); +#if 0 + OPTSYM(iter_creds); + OPTSYM(destroy_cred); + OPTSYM(cred_hold); + OPTSYM(cred_unhold); + OPTSYM(cred_label_get); + OPTSYM(cred_label_set); +#endif + OPTSYM(display_name_ext); + OPTSYM(inquire_name); + OPTSYM(get_name_attribute); + OPTSYM(set_name_attribute); + OPTSYM(delete_name_attribute); + OPTSYM(export_name_composite); + OPTSYM(localname); + OPTSYM(duplicate_cred); + OPTSYM(add_cred_from); + OPTSYM(store_cred_into); + OPTSPISYM(authorize_localname); + OPTSPISPISYM(query_mechanism_info); + OPTSPISPISYM(query_meta_data); + OPTSPISPISYM(exchange_meta_data); + + mi = (_gss_mo_init *)dlsym(so, "gss_mo_init"); + if (mi != NULL) { + major_status = mi(&minor_status, mech_oid, + &m->gm_mech.gm_mo, &m->gm_mech.gm_mo_num); + if (GSS_ERROR(major_status)) + goto bad; + } else { + /* API-as-SPI compatibility */ + COMPATSYM(inquire_saslname_for_mech); + COMPATSYM(inquire_mech_for_saslname); + COMPATSYM(inquire_attrs_for_mech); + COMPATSPISYM(acquire_cred_with_password); + } + + /* pick up the oid sets of names */ + + if (m->gm_mech.gm_inquire_names_for_mech) + (*m->gm_mech.gm_inquire_names_for_mech)(&minor_status, + &m->gm_mech.gm_mech_oid, &m->gm_name_types); + + if (m->gm_name_types == NULL) + gss_create_empty_oid_set(&minor_status, &m->gm_name_types); + + HEIM_TAILQ_INSERT_TAIL(&_gss_mechs, m, gm_link); + continue; + + bad: + if (m != NULL) { + free(m->gm_mech.gm_compat); + /* do not free OID, it has been interned */ + free((char *)m->gm_mech.gm_name); + free(m); + } + if (so != NULL) + dlclose(so); + continue; + } + fclose(fp); + +out: + +#endif + if (add_builtin(__gss_sanon_initialize())) + _gss_mg_log(1, "Out of memory while adding builtin SANON " + "mechanism to the GSS mechanism switch"); + HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); +} + +gssapi_mech_interface +__gss_get_mechanism(gss_const_OID mech) +{ + struct _gss_mech_switch *m; + + _gss_load_mech(); + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech)) + return &m->gm_mech; + } + return NULL; +} + +gss_OID +_gss_mg_support_mechanism(gss_const_OID mech) +{ + struct _gss_mech_switch *m; + + _gss_load_mech(); + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech)) + return m->gm_mech_oid; + } + return NULL; +} + +enum mech_name_match { + MATCH_NONE = 0, + MATCH_COMPLETE, + MATCH_PARTIAL +}; + +static enum mech_name_match +match_mech_name(const char *gm_mech_name, + const char *name, + size_t namelen) +{ + if (gm_mech_name == NULL) + return MATCH_NONE; + else if (strcasecmp(gm_mech_name, name) == 0) + return MATCH_COMPLETE; + else if (strncasecmp(gm_mech_name, name, namelen) == 0) + return MATCH_PARTIAL; + else + return MATCH_NONE; +} + +/* + * Return an OID for a built-in or dynamically loaded mechanism. For + * API compatibility with previous versions, we treat "Kerberos 5" + * as an alias for "krb5". Unique partial matches are supported. + */ +GSSAPI_LIB_FUNCTION gss_OID GSSAPI_CALLCONV +gss_name_to_oid(const char *name) +{ + struct _gss_mech_switch *m, *partial = NULL; + gss_OID oid = GSS_C_NO_OID; + size_t namelen = strlen(name); + + if (isdigit(name[0]) && _gss_string_to_oid(name, &oid) == 0) + return oid; + + _gss_load_mech(); + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + enum mech_name_match match; + + match = match_mech_name(m->gm_mech.gm_name, name, namelen); + if (match == MATCH_NONE && + gss_oid_equal(m->gm_mech_oid, GSS_KRB5_MECHANISM)) + match = match_mech_name("Kerberos 5", name, namelen); + + if (match == MATCH_COMPLETE) + return m->gm_mech_oid; + else if (match == MATCH_PARTIAL) { + if (partial) + return NULL; + else + partial = m; + } + } + + if (partial) + return partial->gm_mech_oid; + + return NULL; +} + +GSSAPI_LIB_FUNCTION const char * GSSAPI_LIB_CALL +gss_oid_to_name(gss_const_OID oid) +{ + struct _gss_mech_switch *m; + + _gss_load_mech(); + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + if (gss_oid_equal(m->gm_mech_oid, oid)) + return m->gm_mech.gm_name; + } + + return NULL; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_mo.c b/third_party/heimdal/lib/gssapi/mech/gss_mo.c new file mode 100644 index 0000000..b6ae282 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_mo.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 PADL Software Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +#include <crypto-headers.h> + +static int +get_option_def(int def, gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) +{ + return def; +} + +int +_gss_mo_get_option_1(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) +{ + return get_option_def(1, mech, mo, value); +} + +int +_gss_mo_get_option_0(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) +{ + return get_option_def(0, mech, mo, value); +} + +int +_gss_mo_get_ctx_as_string(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) +{ + if (value) { + value->value = strdup((char *)mo->ctx); + if (value->value == NULL) + return GSS_S_FAILURE; + value->length = strlen((char *)mo->ctx); + } + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_mo_set(gss_const_OID mech, gss_const_OID option, + int enable, gss_buffer_t value) +{ + gssapi_mech_interface m; + size_t n; + + if ((m = __gss_get_mechanism(mech)) == NULL) + return GSS_S_BAD_MECH; + + for (n = 0; n < m->gm_mo_num; n++) + if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].set) + return m->gm_mo[n].set(mech, &m->gm_mo[n], enable, value); + + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_mo_get(gss_const_OID mech, gss_const_OID option, gss_buffer_t value) +{ + gssapi_mech_interface m; + size_t n; + + _mg_buffer_zero(value); + + if ((m = __gss_get_mechanism(mech)) == NULL) + return GSS_S_BAD_MECH; + + for (n = 0; n < m->gm_mo_num; n++) + if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].get) + return m->gm_mo[n].get(mech, &m->gm_mo[n], value); + + return GSS_S_UNAVAILABLE; +} + +static void +add_all_mo(gssapi_mech_interface m, gss_OID_set *options, OM_uint32 mask) +{ + OM_uint32 minor; + size_t n; + + for (n = 0; n < m->gm_mo_num; n++) + if ((m->gm_mo[n].flags & mask) == mask) + gss_add_oid_set_member(&minor, m->gm_mo[n].option, options); +} + +GSSAPI_LIB_FUNCTION void GSSAPI_LIB_CALL +gss_mo_list(gss_const_OID mech, gss_OID_set *options) +{ + gssapi_mech_interface m; + OM_uint32 major, minor; + + if (options == NULL) + return; + + *options = GSS_C_NO_OID_SET; + + if ((m = __gss_get_mechanism(mech)) == NULL) + return; + + major = gss_create_empty_oid_set(&minor, options); + if (major != GSS_S_COMPLETE) + return; + + add_all_mo(m, options, 0); +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_mo_name(gss_const_OID mech, gss_const_OID option, gss_buffer_t name) +{ + gssapi_mech_interface m; + size_t n; + + if (name == NULL) + return GSS_S_BAD_NAME; + + if ((m = __gss_get_mechanism(mech)) == NULL) + return GSS_S_BAD_MECH; + + for (n = 0; n < m->gm_mo_num; n++) { + if (gss_oid_equal(option, m->gm_mo[n].option)) { + /* + * If there is no name, its because its a GSS_C_MA and + * there is already a table for that. + */ + if (m->gm_mo[n].name) { + name->value = strdup(m->gm_mo[n].name); + if (name->value == NULL) + return GSS_S_BAD_NAME; + name->length = strlen(m->gm_mo[n].name); + return GSS_S_COMPLETE; + } else { + OM_uint32 junk; + return gss_display_mech_attr(&junk, option, + NULL, name, NULL); + } + } + } + return GSS_S_BAD_NAME; +} + +/* + * Helper function to allow NULL name + */ + +static OM_uint32 +mo_value(const gss_const_OID mech, gss_const_OID option, gss_buffer_t name) +{ + if (name == NULL) + return GSS_S_COMPLETE; + + return gss_mo_get(mech, option, name); +} + +/* code derived from draft-ietf-cat-sasl-gssapi-01 */ +static char basis_32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + +static OM_uint32 +make_sasl_name(OM_uint32 *minor, const gss_OID mech, char sasl_name[16]) +{ + EVP_MD_CTX *ctx; + char *p = sasl_name; + u_char hdr[2], hash[20], *h = hash; + + if (mech->length > 127) + return GSS_S_BAD_MECH; + + hdr[0] = 0x06; + hdr[1] = mech->length; + + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); + EVP_DigestUpdate(ctx, hdr, 2); + EVP_DigestUpdate(ctx, mech->elements, mech->length); + EVP_DigestFinal_ex(ctx, hash, NULL); + EVP_MD_CTX_destroy(ctx); + + memcpy(p, "GS2-", 4); + p += 4; + + *p++ = basis_32[(h[0] >> 3)]; + *p++ = basis_32[((h[0] & 7) << 2) | (h[1] >> 6)]; + *p++ = basis_32[(h[1] & 0x3f) >> 1]; + *p++ = basis_32[((h[1] & 1) << 4) | (h[2] >> 4)]; + *p++ = basis_32[((h[2] & 0xf) << 1) | (h[3] >> 7)]; + *p++ = basis_32[(h[3] & 0x7f) >> 2]; + *p++ = basis_32[((h[3] & 3) << 3) | (h[4] >> 5)]; + *p++ = basis_32[(h[4] & 0x1f)]; + *p++ = basis_32[(h[5] >> 3)]; + *p++ = basis_32[((h[5] & 7) << 2) | (h[6] >> 6)]; + *p++ = basis_32[(h[6] & 0x3f) >> 1]; + + *p = '\0'; + + return GSS_S_COMPLETE; +} + +/* + * gss_inquire_saslname_for_mech() wrapper that uses MIT SPI + */ +static OM_uint32 +inquire_saslname_for_mech_compat(OM_uint32 *minor, + const gss_OID desired_mech, + gss_buffer_t sasl_mech_name, + gss_buffer_t mech_name, + gss_buffer_t mech_description) +{ + struct gss_mech_compat_desc_struct *gmc; + gssapi_mech_interface m; + OM_uint32 major; + + m = __gss_get_mechanism(desired_mech); + if (m == NULL) + return GSS_S_BAD_MECH; + + gmc = m->gm_compat; + + if (gmc != NULL && gmc->gmc_inquire_saslname_for_mech != NULL) { + major = gmc->gmc_inquire_saslname_for_mech(minor, + desired_mech, + sasl_mech_name, + mech_name, + mech_description); + } else { + major = GSS_S_UNAVAILABLE; + } + + return major; +} + +/** + * Returns different protocol names and description of the mechanism. + * + * @param minor_status minor status code + * @param desired_mech mech list query + * @param sasl_mech_name SASL GS2 protocol name + * @param mech_name gssapi protocol name + * @param mech_description description of gssapi mech + * + * @return returns GSS_S_COMPLETE or a error code. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_saslname_for_mech(OM_uint32 *minor_status, + const gss_OID desired_mech, + gss_buffer_t sasl_mech_name, + gss_buffer_t mech_name, + gss_buffer_t mech_description) +{ + OM_uint32 major; + + _mg_buffer_zero(sasl_mech_name); + _mg_buffer_zero(mech_name); + _mg_buffer_zero(mech_description); + + if (minor_status) + *minor_status = 0; + + if (desired_mech == NULL) + return GSS_S_BAD_MECH; + + major = mo_value(desired_mech, GSS_C_MA_SASL_MECH_NAME, sasl_mech_name); + if (major == GSS_S_COMPLETE) { + /* Native SPI */ + major = mo_value(desired_mech, GSS_C_MA_MECH_NAME, mech_name); + if (GSS_ERROR(major)) + return major; + + major = mo_value(desired_mech, GSS_C_MA_MECH_DESCRIPTION, mech_description); + if (GSS_ERROR(major)) + return major; + } + + if (GSS_ERROR(major)) { + /* API-as-SPI compatibility */ + major = inquire_saslname_for_mech_compat(minor_status, + desired_mech, + sasl_mech_name, + mech_name, + mech_description); + } + + if (GSS_ERROR(major)) { + /* Algorithmically dervied SASL mechanism name */ + char buf[16]; + gss_buffer_desc tmp = { sizeof(buf) - 1, buf }; + + major = make_sasl_name(minor_status, desired_mech, buf); + if (GSS_ERROR(major)) + return major; + + major = _gss_copy_buffer(minor_status, &tmp, sasl_mech_name); + if (GSS_ERROR(major)) + return major; + } + + return major; +} + +/** + * Find a mech for a sasl name + * + * @param minor_status minor status code + * @param sasl_mech_name + * @param mech_type + * + * @return returns GSS_S_COMPLETE or an error code. + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_mech_for_saslname(OM_uint32 *minor_status, + const gss_buffer_t sasl_mech_name, + gss_OID *mech_type) +{ + struct _gss_mech_switch *m; + gss_buffer_desc name; + OM_uint32 major, junk; + char buf[16]; + + _gss_load_mech(); + + *mech_type = NULL; + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + struct gss_mech_compat_desc_struct *gmc; + + /* Native SPI */ + major = mo_value(m->gm_mech_oid, GSS_C_MA_SASL_MECH_NAME, &name); + if (major == GSS_S_COMPLETE && + name.length == sasl_mech_name->length && + memcmp(name.value, sasl_mech_name->value, name.length) == 0) { + gss_release_buffer(&junk, &name); + *mech_type = m->gm_mech_oid; + return GSS_S_COMPLETE; + } + gss_release_buffer(&junk, &name); + + if (GSS_ERROR(major)) { + /* API-as-SPI compatibility */ + gmc = m->gm_mech.gm_compat; + if (gmc && gmc->gmc_inquire_mech_for_saslname) { + major = gmc->gmc_inquire_mech_for_saslname(minor_status, + sasl_mech_name, + mech_type); + if (major == GSS_S_COMPLETE) + return GSS_S_COMPLETE; + } + } + + if (GSS_ERROR(major)) { + /* Algorithmically dervied SASL mechanism name */ + if (sasl_mech_name->length == 16 && + make_sasl_name(minor_status, m->gm_mech_oid, buf) == GSS_S_COMPLETE && + memcmp(buf, sasl_mech_name->value, 16) == 0) { + *mech_type = m->gm_mech_oid; + return GSS_S_COMPLETE; + } + } + } + + return GSS_S_BAD_MECH; +} + +/* + * Test mechanism against indicated attributes using both Heimdal and + * MIT SPIs. + */ +static int +test_mech_attrs(gssapi_mech_interface mi, + gss_const_OID_set mech_attrs, + gss_const_OID_set against_attrs, + int except) +{ + size_t n, m; + int eq = 0; + + if (against_attrs == GSS_C_NO_OID_SET) + return 1; + + for (n = 0; n < against_attrs->count; n++) { + for (m = 0; m < mi->gm_mo_num; m++) { + eq = gss_oid_equal(mi->gm_mo[m].option, + &against_attrs->elements[n]); + if (eq) + break; + } + if (mech_attrs != GSS_C_NO_OID_SET) { + for (m = 0; m < mech_attrs->count; m++) { + eq = gss_oid_equal(&mech_attrs->elements[m], + &against_attrs->elements[n]); + if (eq) + break; + } + } + if (!eq ^ except) + return 0; + } + + return 1; +} + +/** + * Return set of mechanism that fullfill the criteria + * + * @param minor_status minor status code + * @param desired_mech_attrs + * @param except_mech_attrs + * @param critical_mech_attrs + * @param mechs returned mechs, free with gss_release_oid_set(). + * + * @return returns GSS_S_COMPLETE or an error code. + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_indicate_mechs_by_attrs(OM_uint32 * minor_status, + gss_const_OID_set desired_mech_attrs, + gss_const_OID_set except_mech_attrs, + gss_const_OID_set critical_mech_attrs, + gss_OID_set *mechs) +{ + struct _gss_mech_switch *ms; + gss_OID_set mech_attrs = GSS_C_NO_OID_SET; + gss_OID_set known_mech_attrs = GSS_C_NO_OID_SET; + OM_uint32 major; + + major = gss_create_empty_oid_set(minor_status, mechs); + if (GSS_ERROR(major)) + return major; + + _gss_load_mech(); + + HEIM_TAILQ_FOREACH(ms, &_gss_mechs, gm_link) { + gssapi_mech_interface mi = &ms->gm_mech; + struct gss_mech_compat_desc_struct *gmc = mi->gm_compat; + OM_uint32 tmp; + + if (gmc && gmc->gmc_inquire_attrs_for_mech) { + major = gmc->gmc_inquire_attrs_for_mech(minor_status, + &mi->gm_mech_oid, + &mech_attrs, + &known_mech_attrs); + if (GSS_ERROR(major)) + continue; + } + + /* + * Test mechanism supports all of desired_mech_attrs; + * none of except_mech_attrs; + * and knows of all critical_mech_attrs. + */ + if (test_mech_attrs(mi, mech_attrs, desired_mech_attrs, 0) && + test_mech_attrs(mi, mech_attrs, except_mech_attrs, 1) && + test_mech_attrs(mi, known_mech_attrs, critical_mech_attrs, 0)) { + major = gss_add_oid_set_member(minor_status, &mi->gm_mech_oid, mechs); + } + + gss_release_oid_set(&tmp, &mech_attrs); + gss_release_oid_set(&tmp, &known_mech_attrs); + + if (GSS_ERROR(major)) + break; + } + + return major; +} + +/** + * List support attributes for a mech and/or all mechanisms. + * + * @param minor_status minor status code + * @param mech given together with mech_attr will return the list of + * attributes for mechanism, can optionally be GSS_C_NO_OID. + * @param mech_attr see mech parameter, can optionally be NULL, + * release with gss_release_oid_set(). + * @param known_mech_attrs all attributes for mechanisms supported, + * release with gss_release_oid_set(). + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_attrs_for_mech(OM_uint32 * minor_status, + gss_const_OID mech, + gss_OID_set *mech_attr, + gss_OID_set *known_mech_attrs) +{ + OM_uint32 major, junk; + + if (known_mech_attrs) + *known_mech_attrs = GSS_C_NO_OID_SET; + + if (mech_attr && mech) { + gssapi_mech_interface m; + struct gss_mech_compat_desc_struct *gmc; + + if ((m = __gss_get_mechanism(mech)) == NULL) { + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + gmc = m->gm_compat; + + if (gmc && gmc->gmc_inquire_attrs_for_mech) { + major = gmc->gmc_inquire_attrs_for_mech(minor_status, + mech, + mech_attr, + known_mech_attrs); + } else { + major = gss_create_empty_oid_set(minor_status, mech_attr); + if (major == GSS_S_COMPLETE) + add_all_mo(m, mech_attr, GSS_MO_MA); + } + if (GSS_ERROR(major)) + return major; + } + + if (known_mech_attrs) { + struct _gss_mech_switch *m; + + if (*known_mech_attrs == GSS_C_NO_OID_SET) { + major = gss_create_empty_oid_set(minor_status, known_mech_attrs); + if (GSS_ERROR(major)) { + if (mech_attr) + gss_release_oid_set(&junk, mech_attr); + return major; + } + } + + _gss_load_mech(); + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) + add_all_mo(&m->gm_mech, known_mech_attrs, GSS_MO_MA); + } + + + return GSS_S_COMPLETE; +} + +/** + * Return names and descriptions of mech attributes + * + * @param minor_status minor status code + * @param mech_attr + * @param name + * @param short_desc + * @param long_desc + * + * @return returns GSS_S_COMPLETE or an error code. + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_display_mech_attr(OM_uint32 * minor_status, + gss_const_OID mech_attr, + gss_buffer_t name, + gss_buffer_t short_desc, + gss_buffer_t long_desc) +{ + struct _gss_oid_name_table *ma = NULL; + OM_uint32 major; + size_t n; + + _mg_buffer_zero(name); + _mg_buffer_zero(short_desc); + _mg_buffer_zero(long_desc); + + if (minor_status) + *minor_status = 0; + + for (n = 0; ma == NULL && _gss_ont_ma[n].oid; n++) + if (gss_oid_equal(mech_attr, _gss_ont_ma[n].oid)) + ma = &_gss_ont_ma[n]; + + if (ma == NULL) + return GSS_S_BAD_MECH_ATTR; + + if (name) { + gss_buffer_desc bd; + bd.value = rk_UNCONST(ma->name); + bd.length = strlen(ma->name); + major = _gss_copy_buffer(minor_status, &bd, name); + if (major != GSS_S_COMPLETE) + return major; + } + + if (short_desc) { + gss_buffer_desc bd; + bd.value = rk_UNCONST(ma->short_desc); + bd.length = strlen(ma->short_desc); + major = _gss_copy_buffer(minor_status, &bd, short_desc); + if (major != GSS_S_COMPLETE) + return major; + } + + if (long_desc) { + gss_buffer_desc bd; + bd.value = rk_UNCONST(ma->long_desc); + bd.length = strlen(ma->long_desc); + major = _gss_copy_buffer(minor_status, &bd, long_desc); + if (major != GSS_S_COMPLETE) + return major; + } + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_names.c b/third_party/heimdal/lib/gssapi/mech/gss_names.c new file mode 100644 index 0000000..729e7f2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_names.c @@ -0,0 +1,262 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_names.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +gss_name_t +_gss_mg_get_underlying_mech_name(gss_name_t name, + gss_const_OID mech) +{ + struct _gss_name *n = (struct _gss_name *)name; + struct _gss_mechanism_name *mn; + + HEIM_TAILQ_FOREACH(mn, &n->gn_mn, gmn_link) { + if (gss_oid_equal(mech, mn->gmn_mech_oid)) + return mn->gmn_name; + } + return GSS_C_NO_NAME; +} + +OM_uint32 +_gss_find_mn(OM_uint32 *minor_status, + struct _gss_name *name, + gss_const_OID mech, + struct _gss_mechanism_name ** output_mn) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + struct _gss_mechanism_name *mn; + + *output_mn = NULL; + + /* null names are ok, some mechs might not have names */ + if (name == NULL) + return GSS_S_COMPLETE; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + if (gss_oid_equal(mech, mn->gmn_mech_oid)) + break; + } + + if (!mn) { + /* + * If this name is canonical (i.e. there is only an + * MN but it is from a different mech), give up now. + */ + if (!name->gn_value.value) + return GSS_S_BAD_NAME; + + m = __gss_get_mechanism(mech); + if (!m || !m->gm_import_name) + return (GSS_S_BAD_MECH); + + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) + return GSS_S_FAILURE; + + major_status = m->gm_import_name(minor_status, + &name->gn_value, + name->gn_type, + &mn->gmn_name); + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, *minor_status); + free(mn); + return major_status; + } + + mn->gmn_mech = m; + mn->gmn_mech_oid = &m->gm_mech_oid; + HEIM_TAILQ_INSERT_TAIL(&name->gn_mn, mn, gmn_link); + } + *output_mn = mn; + return 0; +} + + +/* + * Make a name from an MN. + */ +struct _gss_name * +_gss_create_name(gss_name_t new_mn, + struct gssapi_mech_interface_desc *m) +{ + struct _gss_name *name; + struct _gss_mechanism_name *mn; + + name = calloc(1, sizeof(struct _gss_name)); + if (!name) + return (0); + + HEIM_TAILQ_INIT(&name->gn_mn); + + if (new_mn) { + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) { + free(name); + return (0); + } + + mn->gmn_mech = m; + mn->gmn_mech_oid = &m->gm_mech_oid; + mn->gmn_name = new_mn; + HEIM_TAILQ_INSERT_TAIL(&name->gn_mn, mn, gmn_link); + } + + return (name); +} + +/* + * + */ + +void +_gss_mg_release_name(struct _gss_name *name) +{ + OM_uint32 junk; + struct _gss_mechanism_name *mn, *next; + + gss_release_oid(&junk, &name->gn_type); + + HEIM_TAILQ_FOREACH_SAFE(mn, &name->gn_mn, gmn_link, next) { + HEIM_TAILQ_REMOVE(&name->gn_mn, mn, gmn_link); + mn->gmn_mech->gm_release_name(&junk, &mn->gmn_name); + free(mn); + } + gss_release_buffer(&junk, &name->gn_value); + free(name); +} + +void +_gss_mg_check_name(gss_const_name_t name) +{ + if (name == NULL) return; +} + +/* + * + */ + +OM_uint32 +_gss_mech_import_name(OM_uint32 * minor_status, + gss_const_OID mech, + struct _gss_name_type *names, + const gss_buffer_t input_name_buffer, + gss_const_OID input_name_type, + gss_name_t *output_name) +{ + struct _gss_name_type *name; + gss_buffer_t name_buffer = input_name_buffer; + gss_buffer_desc export_name; + + *minor_status = 0; + + if (output_name == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *output_name = GSS_C_NO_NAME; + + /* + * If its a exported name, strip of the mech glue. + */ + + if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) { + unsigned char *p; + uint32_t length; + + if (name_buffer->length < 10 + mech->length) + return GSS_S_BAD_NAME; + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + p = name_buffer->value; + + if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 || + p[3] != mech->length + 2 || + p[4] != 0x06 || + p[5] != mech->length || + memcmp(&p[6], mech->elements, mech->length) != 0) + return GSS_S_BAD_NAME; + + p += 6 + mech->length; + + length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + p += 4; + + if (length > name_buffer->length - 10 - mech->length) + return GSS_S_BAD_NAME; + + /* + * Point this to the mech specific name part, don't modifity + * orignal input_name_buffer. + */ + + export_name.length = length; + export_name.value = p; + + name_buffer = &export_name; + } + + for (name = names; name->gnt_parse != NULL; name++) { + if (gss_oid_equal(input_name_type, name->gnt_name_type) + || (name->gnt_name_type == GSS_C_NO_OID && input_name_type == GSS_C_NO_OID)) + return name->gnt_parse(minor_status, mech, name_buffer, + input_name_type, output_name); + } + + return GSS_S_BAD_NAMETYPE; +} + +OM_uint32 +_gss_mech_inquire_names_for_mech(OM_uint32 * minor_status, + struct _gss_name_type *names, + gss_OID_set *name_types) +{ + struct _gss_name_type *name; + OM_uint32 ret, junk; + + ret = gss_create_empty_oid_set(minor_status, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + for (name = names; name->gnt_parse != NULL; name++) { + if (name->gnt_name_type == GSS_C_NO_OID) + continue; + ret = gss_add_oid_set_member(minor_status, + name->gnt_name_type, + name_types); + if (ret != GSS_S_COMPLETE) + break; + } + + if (ret != GSS_S_COMPLETE) + gss_release_oid_set(&junk, name_types); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_oid.c b/third_party/heimdal/lib/gssapi/mech/gss_oid.c new file mode 100644 index 0000000..10ec22d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_oid.c @@ -0,0 +1,370 @@ +/* Generated file */ +#include "mech_locl.h" + +/* GSS_KRB5_COPY_CCACHE_X - 1.2.752.43.13.1 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_copy_ccache_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x01") }; + +/* GSS_KRB5_GET_TKT_FLAGS_X - 1.2.752.43.13.2 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_tkt_flags_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x02") }; + +/* GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X - 1.2.752.43.13.3 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_extract_authz_data_from_sec_context_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x03") }; + +/* GSS_KRB5_COMPAT_DES3_MIC_X - 1.2.752.43.13.4 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_compat_des3_mic_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x04") }; + +/* GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X - 1.2.752.43.13.5 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_register_acceptor_identity_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x05") }; + +/* GSS_KRB5_EXPORT_LUCID_CONTEXT_X - 1.2.752.43.13.6 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_export_lucid_context_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06") }; + +/* GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X - 1.2.752.43.13.6.1 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_export_lucid_context_v1_x_oid_desc = { 7, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06\x01") }; + +/* GSS_KRB5_SET_DNS_CANONICALIZE_X - 1.2.752.43.13.7 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_dns_canonicalize_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x07") }; + +/* GSS_KRB5_GET_SUBKEY_X - 1.2.752.43.13.8 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_subkey_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x08") }; + +/* GSS_KRB5_GET_INITIATOR_SUBKEY_X - 1.2.752.43.13.9 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_initiator_subkey_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x09") }; + +/* GSS_KRB5_GET_ACCEPTOR_SUBKEY_X - 1.2.752.43.13.10 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_acceptor_subkey_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0a") }; + +/* GSS_KRB5_SEND_TO_KDC_X - 1.2.752.43.13.11 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_send_to_kdc_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0b") }; + +/* GSS_KRB5_GET_AUTHTIME_X - 1.2.752.43.13.12 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_authtime_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0c") }; + +/* GSS_KRB5_GET_SERVICE_KEYBLOCK_X - 1.2.752.43.13.13 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_service_keyblock_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0d") }; + +/* GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X - 1.2.752.43.13.14 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_allowable_enctypes_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0e") }; + +/* GSS_KRB5_SET_DEFAULT_REALM_X - 1.2.752.43.13.15 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_default_realm_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0f") }; + +/* GSS_KRB5_CCACHE_NAME_X - 1.2.752.43.13.16 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_ccache_name_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x10") }; + +/* GSS_KRB5_SET_TIME_OFFSET_X - 1.2.752.43.13.17 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_time_offset_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11") }; + +/* GSS_KRB5_GET_TIME_OFFSET_X - 1.2.752.43.13.18 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_time_offset_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x12") }; + +/* GSS_KRB5_PLUGIN_REGISTER_X - 1.2.752.43.13.19 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_plugin_register_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x13") }; + +/* GSS_NTLM_GET_SESSION_KEY_X - 1.2.752.43.13.20 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_ntlm_get_session_key_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x14") }; + +/* GSS_C_NT_NTLM - 1.2.752.43.13.21 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_ntlm_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x15") }; + +/* GSS_C_NT_DN - 1.2.752.43.13.22 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_dn_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x16") }; + +/* GSS_KRB5_NT_PRINCIPAL_NAME_REFERRAL - 1.2.752.43.13.23 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_nt_principal_name_referral_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x17") }; + +/* GSS_C_NTLM_AVGUEST - 1.2.752.43.13.24 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ntlm_avguest_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x18") }; + +/* GSS_C_NTLM_V1 - 1.2.752.43.13.25 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ntlm_v1_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x19") }; + +/* GSS_C_NTLM_V2 - 1.2.752.43.13.26 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ntlm_v2_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1a") }; + +/* GSS_C_NTLM_SESSION_KEY - 1.2.752.43.13.27 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ntlm_session_key_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1b") }; + +/* GSS_C_NTLM_FORCE_V1 - 1.2.752.43.13.28 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ntlm_force_v1_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1c") }; + +/* GSS_KRB5_CRED_NO_CI_FLAGS_X - 1.2.752.43.13.29 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_cred_no_ci_flags_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1d") }; + +/* GSS_KRB5_IMPORT_CRED_X - 1.2.752.43.13.30 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_import_cred_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1e") }; + +/* GSS_KRB5_IMPORT_RFC4121_CONTEXT_X - 1.2.752.43.13.31 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_import_rfc4121_context_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x1f") }; + +/* GSS_C_MA_SASL_MECH_NAME - 1.2.752.43.13.100 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_sasl_mech_name_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x64") }; + +/* GSS_C_MA_MECH_NAME - 1.2.752.43.13.101 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_name_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x65") }; + +/* GSS_C_MA_MECH_DESCRIPTION - 1.2.752.43.13.102 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_description_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x66") }; + +/* GSS_SASL_DIGEST_MD5_MECHANISM - 1.2.752.43.14.1 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_sasl_digest_md5_mechanism_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x01") }; + +/* GSS_NETLOGON_MECHANISM - 1.2.752.43.14.2 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_netlogon_mechanism_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x02") }; + +/* GSS_NETLOGON_SET_SESSION_KEY_X - 1.2.752.43.14.3 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_netlogon_set_session_key_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x03") }; + +/* GSS_NETLOGON_SET_SIGN_ALGORITHM_X - 1.2.752.43.14.4 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_netlogon_set_sign_algorithm_x_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x04") }; + +/* GSS_NETLOGON_NT_NETBIOS_DNS_NAME - 1.2.752.43.14.5 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_netlogon_nt_netbios_dns_name_oid_desc = { 6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x05") }; + +/* GSS_C_INQ_WIN2K_PAC_X - 1.2.752.43.13.3.128 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_win2k_pac_x_oid_desc = { 8, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x03\x81\x00") }; + +/* GSS_C_INQ_SSPI_SESSION_KEY - 1.2.840.113554.1.2.2.5.5 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_sspi_session_key_oid_desc = { 11, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05") }; + +/* GSS_C_INQ_NEGOEX_KEY - 1.2.840.113554.1.2.2.5.16 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_negoex_key_oid_desc = { 11, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x10") }; + +/* GSS_C_INQ_NEGOEX_VERIFY_KEY - 1.2.840.113554.1.2.2.5.17 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_negoex_verify_key_oid_desc = { 11, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x11") }; + +/* GSS_C_INQ_REQUIRE_MECHLIST_MIC - 1.3.6.1.4.1.7165.655.1.2 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_require_mechlist_mic_oid_desc = { 11, rk_UNCONST("\x2b\x06\x01\x04\x01\xb7\x7d\x85\x0f\x01\x02") }; + +/* GSS_KRB5_MECHANISM - 1.2.840.113554.1.2.2 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_mechanism_oid_desc = { 9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; + +/* GSS_NTLM_MECHANISM - 1.3.6.1.4.1.311.2.2.10 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_ntlm_mechanism_oid_desc = { 10, rk_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a") }; + +/* GSS_SPNEGO_MECHANISM - 1.3.6.1.5.5.2 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_spnego_mechanism_oid_desc = { 6, rk_UNCONST("\x2b\x06\x01\x05\x05\x02") }; + +/* GSS_C_INQ_PEER_HAS_BUGGY_SPNEGO - 1.3.6.1.4.1.5322.19.6 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_peer_has_buggy_spnego_oid_desc = { 9, rk_UNCONST("\x2b\x06\x01\x04\x01\xa9\x4a\x13\x06") }; + +/* GSS_C_NTLM_RESET_CRYPTO - 1.3.6.1.4.1.7165.655.1.3 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ntlm_reset_crypto_oid_desc = { 11, rk_UNCONST("\x2b\x06\x01\x04\x01\xb7\x7d\x85\x0f\x01\x03") }; + +/* GSS_NEGOEX_MECHANISM - 1.3.6.1.4.1.311.2.2.30 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_negoex_mechanism_oid_desc = { 10, rk_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x1e") }; + +/* GSS_SANON_X25519_MECHANISM - 1.3.6.1.4.1.5322.26.1.110 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_sanon_x25519_mechanism_oid_desc = { 10, rk_UNCONST("\x2b\x06\x01\x04\x01\xa9\x4a\x1a\x01\x6e") }; + +/* GSS_C_MA_MECH_CONCRETE - 1.3.6.1.5.5.13.1 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_concrete_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x01") }; + +/* GSS_C_MA_MECH_PSEUDO - 1.3.6.1.5.5.13.2 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_pseudo_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x02") }; + +/* GSS_C_MA_MECH_COMPOSITE - 1.3.6.1.5.5.13.3 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_composite_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x03") }; + +/* GSS_C_MA_MECH_NEGO - 1.3.6.1.5.5.13.4 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_nego_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x04") }; + +/* GSS_C_MA_MECH_GLUE - 1.3.6.1.5.5.13.5 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_glue_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x05") }; + +/* GSS_C_MA_NOT_MECH - 1.3.6.1.5.5.13.6 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_not_mech_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x06") }; + +/* GSS_C_MA_DEPRECATED - 1.3.6.1.5.5.13.7 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_deprecated_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x07") }; + +/* GSS_C_MA_NOT_DFLT_MECH - 1.3.6.1.5.5.13.8 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_not_dflt_mech_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x08") }; + +/* GSS_C_MA_ITOK_FRAMED - 1.3.6.1.5.5.13.9 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_itok_framed_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x09") }; + +/* GSS_C_MA_AUTH_INIT - 1.3.6.1.5.5.13.10 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_auth_init_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x0a") }; + +/* GSS_C_MA_AUTH_TARG - 1.3.6.1.5.5.13.11 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_auth_targ_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x0b") }; + +/* GSS_C_MA_AUTH_INIT_INIT - 1.3.6.1.5.5.13.12 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_auth_init_init_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x0c") }; + +/* GSS_C_MA_AUTH_TARG_INIT - 1.3.6.1.5.5.13.13 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_auth_targ_init_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x0d") }; + +/* GSS_C_MA_AUTH_INIT_ANON - 1.3.6.1.5.5.13.14 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_auth_init_anon_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x0e") }; + +/* GSS_C_MA_AUTH_TARG_ANON - 1.3.6.1.5.5.13.15 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_auth_targ_anon_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x0f") }; + +/* GSS_C_MA_DELEG_CRED - 1.3.6.1.5.5.13.16 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_deleg_cred_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x10") }; + +/* GSS_C_MA_INTEG_PROT - 1.3.6.1.5.5.13.17 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_integ_prot_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x11") }; + +/* GSS_C_MA_CONF_PROT - 1.3.6.1.5.5.13.18 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_conf_prot_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x12") }; + +/* GSS_C_MA_MIC - 1.3.6.1.5.5.13.19 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mic_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x13") }; + +/* GSS_C_MA_WRAP - 1.3.6.1.5.5.13.20 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_wrap_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x14") }; + +/* GSS_C_MA_PROT_READY - 1.3.6.1.5.5.13.21 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_prot_ready_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x15") }; + +/* GSS_C_MA_REPLAY_DET - 1.3.6.1.5.5.13.22 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_replay_det_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x16") }; + +/* GSS_C_MA_OOS_DET - 1.3.6.1.5.5.13.23 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_oos_det_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x17") }; + +/* GSS_C_MA_CBINDINGS - 1.3.6.1.5.5.13.24 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_cbindings_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x18") }; + +/* GSS_C_MA_PFS - 1.3.6.1.5.5.13.25 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_pfs_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x19") }; + +/* GSS_C_MA_COMPRESS - 1.3.6.1.5.5.13.26 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_compress_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x1a") }; + +/* GSS_C_MA_CTX_TRANS - 1.3.6.1.5.5.13.27 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_ctx_trans_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x1b") }; + +/* GSS_C_MA_NEGOEX_AND_SPNEGO - 1.2.840.113554.1.2.2.5.18 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_negoex_and_spnego_oid_desc = { 11, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x12") }; + +struct _gss_oid_name_table _gss_ont_ma[] = { + { GSS_C_MA_AUTH_INIT, "GSS_C_MA_AUTH_INIT", "auth-init-princ", "" }, + { GSS_C_MA_AUTH_INIT_ANON, "GSS_C_MA_AUTH_INIT_ANON", "auth-init-princ-anon", "" }, + { GSS_C_MA_AUTH_INIT_INIT, "GSS_C_MA_AUTH_INIT_INIT", "auth-init-princ-initial", "" }, + { GSS_C_MA_AUTH_TARG, "GSS_C_MA_AUTH_TARG", "auth-targ-princ", "" }, + { GSS_C_MA_AUTH_TARG_ANON, "GSS_C_MA_AUTH_TARG_ANON", "auth-targ-princ-anon", "" }, + { GSS_C_MA_AUTH_TARG_INIT, "GSS_C_MA_AUTH_TARG_INIT", "auth-targ-princ-initial", "" }, + { GSS_C_MA_CBINDINGS, "GSS_C_MA_CBINDINGS", "channel-bindings", "" }, + { GSS_C_MA_COMPRESS, "GSS_C_MA_COMPRESS", "compress", "" }, + { GSS_C_MA_CONF_PROT, "GSS_C_MA_CONF_PROT", "conf-prot", "" }, + { GSS_C_MA_CTX_TRANS, "GSS_C_MA_CTX_TRANS", "context-transfer", "" }, + { GSS_C_MA_DELEG_CRED, "GSS_C_MA_DELEG_CRED", "deleg-cred", "" }, + { GSS_C_MA_DEPRECATED, "GSS_C_MA_DEPRECATED", "mech-deprecated", "" }, + { GSS_C_MA_INTEG_PROT, "GSS_C_MA_INTEG_PROT", "integ-prot", "" }, + { GSS_C_MA_ITOK_FRAMED, "GSS_C_MA_ITOK_FRAMED", "initial-is-framed", "" }, + { GSS_C_MA_MECH_COMPOSITE, "GSS_C_MA_MECH_COMPOSITE", "composite-mech", "" }, + { GSS_C_MA_MECH_CONCRETE, "GSS_C_MA_MECH_CONCRETE", "concrete-mech", "Indicates that a mech is neither a pseudo-mechanism nor a composite mechanism" }, + { GSS_C_MA_MECH_DESCRIPTION, "GSS_C_MA_MECH_DESCRIPTION", "Mech description", "The long description of the mechanism" }, + { GSS_C_MA_MECH_GLUE, "GSS_C_MA_MECH_GLUE", "mech-glue", "" }, + { GSS_C_MA_MECH_NAME, "GSS_C_MA_MECH_NAME", "GSS mech name", "The name of the GSS-API mechanism" }, + { GSS_C_MA_MECH_NEGO, "GSS_C_MA_MECH_NEGO", "mech-negotiation-mech", "" }, + { GSS_C_MA_MECH_PSEUDO, "GSS_C_MA_MECH_PSEUDO", "pseudo-mech", "" }, + { GSS_C_MA_MIC, "GSS_C_MA_MIC", "mic", "" }, + { GSS_C_MA_NEGOEX_AND_SPNEGO, "GSS_C_MA_NEGOEX_AND_SPNEGO", "negoex-and-spnego", "Indicates that a mechanism supports both NegoEx and SPNEGO" }, + { GSS_C_MA_NOT_DFLT_MECH, "GSS_C_MA_NOT_DFLT_MECH", "mech-not-default", "" }, + { GSS_C_MA_NOT_MECH, "GSS_C_MA_NOT_MECH", "not-mech", "" }, + { GSS_C_MA_OOS_DET, "GSS_C_MA_OOS_DET", "oos-detection", "" }, + { GSS_C_MA_PFS, "GSS_C_MA_PFS", "pfs", "" }, + { GSS_C_MA_PROT_READY, "GSS_C_MA_PROT_READY", "prot-ready", "" }, + { GSS_C_MA_REPLAY_DET, "GSS_C_MA_REPLAY_DET", "replay-detection", "" }, + { GSS_C_MA_SASL_MECH_NAME, "GSS_C_MA_SASL_MECH_NAME", "SASL mechanism name", "The name of the SASL mechanism" }, + { GSS_C_MA_WRAP, "GSS_C_MA_WRAP", "wrap", "" }, + { NULL, NULL, NULL, NULL } +}; + +struct _gss_oid_name_table _gss_ont_mech[] = { + { GSS_KRB5_MECHANISM, "GSS_KRB5_MECHANISM", "Kerberos 5", "Heimdal Kerberos 5 mechanism" }, + { GSS_NTLM_MECHANISM, "GSS_NTLM_MECHANISM", "NTLM", "Heimdal NTLM mechanism" }, + { GSS_SANON_X25519_MECHANISM, "GSS_SANON_X25519_MECHANISM", "SAnon-X25519", "Heimdal Simple Anonymous (X25519) mechanism" }, + { GSS_SPNEGO_MECHANISM, "GSS_SPNEGO_MECHANISM", "SPNEGO", "Heimdal SPNEGO mechanism" }, + { NULL, NULL, NULL, NULL } +}; + +gss_OID _gss_ot_internal[] = { + &__gss_krb5_copy_ccache_x_oid_desc, + &__gss_krb5_get_tkt_flags_x_oid_desc, + &__gss_krb5_extract_authz_data_from_sec_context_x_oid_desc, + &__gss_krb5_compat_des3_mic_x_oid_desc, + &__gss_krb5_register_acceptor_identity_x_oid_desc, + &__gss_krb5_export_lucid_context_x_oid_desc, + &__gss_krb5_export_lucid_context_v1_x_oid_desc, + &__gss_krb5_set_dns_canonicalize_x_oid_desc, + &__gss_krb5_get_subkey_x_oid_desc, + &__gss_krb5_get_initiator_subkey_x_oid_desc, + &__gss_krb5_get_acceptor_subkey_x_oid_desc, + &__gss_krb5_send_to_kdc_x_oid_desc, + &__gss_krb5_get_authtime_x_oid_desc, + &__gss_krb5_get_service_keyblock_x_oid_desc, + &__gss_krb5_set_allowable_enctypes_x_oid_desc, + &__gss_krb5_set_default_realm_x_oid_desc, + &__gss_krb5_ccache_name_x_oid_desc, + &__gss_krb5_set_time_offset_x_oid_desc, + &__gss_krb5_get_time_offset_x_oid_desc, + &__gss_krb5_plugin_register_x_oid_desc, + &__gss_ntlm_get_session_key_x_oid_desc, + &__gss_c_nt_ntlm_oid_desc, + &__gss_c_nt_dn_oid_desc, + &__gss_krb5_nt_principal_name_referral_oid_desc, + &__gss_c_ntlm_avguest_oid_desc, + &__gss_c_ntlm_v1_oid_desc, + &__gss_c_ntlm_v2_oid_desc, + &__gss_c_ntlm_session_key_oid_desc, + &__gss_c_ntlm_force_v1_oid_desc, + &__gss_krb5_cred_no_ci_flags_x_oid_desc, + &__gss_krb5_import_cred_x_oid_desc, + &__gss_krb5_import_rfc4121_context_x_oid_desc, + &__gss_c_ma_sasl_mech_name_oid_desc, + &__gss_c_ma_mech_name_oid_desc, + &__gss_c_ma_mech_description_oid_desc, + &__gss_sasl_digest_md5_mechanism_oid_desc, + &__gss_netlogon_mechanism_oid_desc, + &__gss_netlogon_set_session_key_x_oid_desc, + &__gss_netlogon_set_sign_algorithm_x_oid_desc, + &__gss_netlogon_nt_netbios_dns_name_oid_desc, + &__gss_c_inq_win2k_pac_x_oid_desc, + &__gss_c_inq_sspi_session_key_oid_desc, + &__gss_c_inq_negoex_key_oid_desc, + &__gss_c_inq_negoex_verify_key_oid_desc, + &__gss_c_inq_require_mechlist_mic_oid_desc, + &__gss_krb5_mechanism_oid_desc, + &__gss_ntlm_mechanism_oid_desc, + &__gss_spnego_mechanism_oid_desc, + &__gss_c_inq_peer_has_buggy_spnego_oid_desc, + &__gss_c_ntlm_reset_crypto_oid_desc, + &__gss_negoex_mechanism_oid_desc, + &__gss_sanon_x25519_mechanism_oid_desc, + &__gss_c_ma_mech_concrete_oid_desc, + &__gss_c_ma_mech_pseudo_oid_desc, + &__gss_c_ma_mech_composite_oid_desc, + &__gss_c_ma_mech_nego_oid_desc, + &__gss_c_ma_mech_glue_oid_desc, + &__gss_c_ma_not_mech_oid_desc, + &__gss_c_ma_deprecated_oid_desc, + &__gss_c_ma_not_dflt_mech_oid_desc, + &__gss_c_ma_itok_framed_oid_desc, + &__gss_c_ma_auth_init_oid_desc, + &__gss_c_ma_auth_targ_oid_desc, + &__gss_c_ma_auth_init_init_oid_desc, + &__gss_c_ma_auth_targ_init_oid_desc, + &__gss_c_ma_auth_init_anon_oid_desc, + &__gss_c_ma_auth_targ_anon_oid_desc, + &__gss_c_ma_deleg_cred_oid_desc, + &__gss_c_ma_integ_prot_oid_desc, + &__gss_c_ma_conf_prot_oid_desc, + &__gss_c_ma_mic_oid_desc, + &__gss_c_ma_wrap_oid_desc, + &__gss_c_ma_prot_ready_oid_desc, + &__gss_c_ma_replay_det_oid_desc, + &__gss_c_ma_oos_det_oid_desc, + &__gss_c_ma_cbindings_oid_desc, + &__gss_c_ma_pfs_oid_desc, + &__gss_c_ma_compress_oid_desc, + &__gss_c_ma_ctx_trans_oid_desc, + &__gss_c_ma_negoex_and_spnego_oid_desc, +}; + +size_t _gss_ot_internal_count = sizeof(_gss_ot_internal) / sizeof(_gss_ot_internal[0]); diff --git a/third_party/heimdal/lib/gssapi/mech/gss_oid_equal.c b/third_party/heimdal/lib/gssapi/mech/gss_oid_equal.c new file mode 100644 index 0000000..b125ede --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_oid_equal.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +/** + * Compare two GSS-API OIDs with each other. + * + * GSS_C_NO_OID matches nothing, not even it-self. + * + * @param a first oid to compare + * @param b second oid to compare + * + * @return non-zero when both oid are the same OID, zero when they are + * not the same. + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL +gss_oid_equal(gss_const_OID a, gss_const_OID b) +{ + if (a == b && a != GSS_C_NO_OID) + return 1; + if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length) + return 0; + return memcmp(a->elements, b->elements, a->length) == 0; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_oid_to_str.c b/third_party/heimdal/lib/gssapi/mech/gss_oid_to_str.c new file mode 100644 index 0000000..d8e188d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_oid_to_str.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str) +{ + int ret; + size_t size; + heim_oid o; + char *p; + + _mg_buffer_zero(oid_str); + + if (oid == GSS_C_NULL_OID) + return GSS_S_FAILURE; + + ret = der_get_oid (oid->elements, oid->length, &o, &size); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = der_print_heim_oid(&o, ' ', &p); + der_free_oid(&o); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + oid_str->value = p; + oid_str->length = strlen(p); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c b/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c new file mode 100644 index 0000000..5046fae --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +static OM_uint32 +mech_localname(OM_uint32 *minor_status, + struct _gss_mechanism_name *mn, + gss_buffer_t localname) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + + *minor_status = 0; + + if (mn->gmn_mech->gm_localname == NULL) + return GSS_S_UNAVAILABLE; + + major_status = mn->gmn_mech->gm_localname(minor_status, + mn->gmn_name, + mn->gmn_mech_oid, + localname); + if (GSS_ERROR(major_status)) + _gss_mg_error(mn->gmn_mech, *minor_status); + + return major_status; +} + +static OM_uint32 +attr_localname(OM_uint32 *minor_status, + struct _gss_mechanism_name *mn, + gss_buffer_t localname) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + OM_uint32 tmpMinor; + gss_buffer_desc value = GSS_C_EMPTY_BUFFER; + gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER; + int authenticated = 0, complete = 0; + int more = -1; + + *minor_status = 0; + + localname->length = 0; + localname->value = NULL; + + if (mn->gmn_mech->gm_get_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + major_status = mn->gmn_mech->gm_get_name_attribute(minor_status, + mn->gmn_name, + GSS_C_ATTR_LOCAL_LOGIN_USER, + &authenticated, + &complete, + &value, + &display_value, + &more); + if (GSS_ERROR(major_status)) { + _gss_mg_error(mn->gmn_mech, *minor_status); + return major_status; + } + + if (authenticated) { + *localname = value; + } else { + major_status = GSS_S_UNAVAILABLE; + gss_release_buffer(&tmpMinor, &value); + } + + gss_release_buffer(&tmpMinor, &display_value); + + return major_status; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_localname(OM_uint32 *minor_status, + gss_const_name_t pname, + const gss_OID mech_type, + gss_buffer_t localname) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_name *name = (struct _gss_name *) pname; + struct _gss_mechanism_name *mn = NULL; + + *minor_status = 0; + + if (mech_type != GSS_C_NO_OID) { + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (GSS_ERROR(major_status)) + return major_status; + + major_status = mech_localname(minor_status, mn, localname); + if (major_status != GSS_S_COMPLETE) + major_status = attr_localname(minor_status, mn, localname); + } else { + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + major_status = mech_localname(minor_status, mn, localname); + if (major_status != GSS_S_COMPLETE) + major_status = attr_localname(minor_status, mn, localname); + if (major_status != GSS_S_UNAVAILABLE) + break; + } + } + + if (major_status != GSS_S_COMPLETE && mn != NULL) + _gss_mg_error(mn->gmn_mech, *minor_status); + + return major_status; +} + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_pname_to_uid(OM_uint32 *minor_status, + gss_const_name_t pname, + const gss_OID mech_type, + uid_t *uidp) +{ +#ifdef NO_LOCALNAME + return GSS_S_UNAVAILABLE; +#else + OM_uint32 major, tmpMinor; + gss_buffer_desc localname = GSS_C_EMPTY_BUFFER; + char *szLocalname; +#ifdef POSIX_GETPWNAM_R + char pwbuf[2048]; + struct passwd pw, *pwd; +#else + struct passwd *pwd; +#endif + + major = gss_localname(minor_status, pname, mech_type, &localname); + if (GSS_ERROR(major)) + return major; + if (localname.length == 0) { + *minor_status = KRB5_NO_LOCALNAME; + return GSS_S_FAILURE; + } + + szLocalname = malloc(localname.length + 1); + if (szLocalname == NULL) { + gss_release_buffer(&tmpMinor, &localname); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy(szLocalname, localname.value, localname.length); + szLocalname[localname.length] = '\0'; + +#ifdef POSIX_GETPWNAM_R + if (getpwnam_r(szLocalname, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) + pwd = NULL; +#else + pwd = getpwnam(szLocalname); +#endif + + gss_release_buffer(&tmpMinor, &localname); + free(szLocalname); + + *minor_status = 0; + + if (pwd != NULL) { + *uidp = pwd->pw_uid; + major = GSS_S_COMPLETE; + } else { + major = GSS_S_UNAVAILABLE; + } + + return major; +#endif +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_process_context_token.c b/third_party/heimdal/lib/gssapi/mech/gss_process_context_token.c new file mode 100644 index 0000000..d10eb47 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_process_context_token.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_process_context_token.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_process_context_token(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t token_buffer) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_process_context_token(minor_status, ctx->gc_ctx, + token_buffer)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_pseudo_random.c b/third_party/heimdal/lib/gssapi/mech/gss_pseudo_random.c new file mode 100644 index 0000000..1b7eb7e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_pseudo_random.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + struct _gss_context *ctx = (struct _gss_context *) context; + gssapi_mech_interface m; + OM_uint32 major_status; + + _mg_buffer_zero(prf_out); + *minor_status = 0; + + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + m = ctx->gc_mech; + + if (m->gm_pseudo_random == NULL) + return GSS_S_UNAVAILABLE; + + major_status = (*m->gm_pseudo_random)(minor_status, ctx->gc_ctx, + prf_key, prf_in, desired_output_len, + prf_out); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, *minor_status); + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_release_buffer.c b/third_party/heimdal/lib/gssapi/mech/gss_release_buffer.c new file mode 100644 index 0000000..c3dd457 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_release_buffer.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_buffer.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer) +{ + + *minor_status = 0; + if (buffer->value) + free(buffer->value); + _mg_buffer_zero(buffer); + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_release_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_release_cred.c new file mode 100644 index 0000000..3a85de5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_release_cred.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +/** + * Release a credentials + * + * Its ok to release the GSS_C_NO_CREDENTIAL/NULL credential, it will + * return a GSS_S_COMPLETE error code. On return cred_handle is set ot + * GSS_C_NO_CREDENTIAL. + * + * Example: + * + * @code + * gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + * major = gss_release_cred(&minor, &cred); + * @endcode + * + * @param minor_status minor status return code, mech specific + * @param cred_handle a pointer to the credential too release + * + * @return an gssapi error code + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) +{ + struct _gss_cred *cred = (struct _gss_cred *) *cred_handle; + + if (cred == NULL) + return (GSS_S_COMPLETE); + + _gss_mg_release_cred(cred); + + *minor_status = 0; + *cred_handle = GSS_C_NO_CREDENTIAL; + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_release_name.c b/third_party/heimdal/lib/gssapi/mech/gss_release_name.c new file mode 100644 index 0000000..db1793e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_release_name.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +/** + * Free a name + * + * import_name can point to NULL or be NULL, or a pointer to a + * gss_name_t structure. If it was a pointer to gss_name_t, the + * pointer will be set to NULL on success and failure. + * + * @param minor_status minor status code + * @param input_name name to free + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_name(OM_uint32 *minor_status, + gss_name_t *input_name) +{ + struct _gss_name *name; + + *minor_status = 0; + + if (input_name == NULL || *input_name == NULL) + return GSS_S_COMPLETE; + + name = (struct _gss_name *) *input_name; + _gss_mg_release_name(name); + + *input_name = GSS_C_NO_NAME; + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_release_oid.c b/third_party/heimdal/lib/gssapi/mech/gss_release_oid.c new file mode 100644 index 0000000..4f674b0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_release_oid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_oid(OM_uint32 *minor_status, gss_OID *oid) +{ + *oid = GSS_C_NO_OID; + + if (minor_status != NULL) + *minor_status = 0; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_release_oid_set.c b/third_party/heimdal/lib/gssapi/mech/gss_release_oid_set.c new file mode 100644 index 0000000..183ddf8 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_release_oid_set.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_oid_set.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_release_oid_set(OM_uint32 *minor_status, + gss_OID_set *set) +{ + + *minor_status = 0; + if (set && *set) { + if ((*set)->elements) + free((*set)->elements); + free(*set); + *set = GSS_C_NO_OID_SET; + } + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_rfc4121.c b/third_party/heimdal/lib/gssapi/mech/gss_rfc4121.c new file mode 100644 index 0000000..97a0833 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_rfc4121.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "mech_locl.h" + +/* + * An internal API (for now) to return a mechglue context handle given + * a session key that can provide RFC 4121 compatible message protection + * and PRF services. Used by SAnon. The implementation of those services + * is currently provided by the krb5 GSS mechanism but that is opaque to + * the caller (minor status codes notwithstanding). + */ +OM_uint32 +_gss_mg_import_rfc4121_context(OM_uint32 *minor, + uint8_t initiator_flag, + OM_uint32 gss_flags, + int32_t rfc3961_enctype, + gss_const_buffer_t session_key, + gss_ctx_id_t *rfc4121_context_handle) +{ + OM_uint32 major = GSS_S_FAILURE, tmpMinor; + krb5_storage *sp; + krb5_error_code ret; + krb5_data d; + gss_buffer_desc rfc4121_args = GSS_C_EMPTY_BUFFER; + + krb5_data_zero(&d); + + *minor = 0; + *rfc4121_context_handle = GSS_C_NO_CONTEXT; + + sp = krb5_storage_emem(); + if (sp == NULL) { + ret = ENOMEM; + goto out; + } + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST); + + /* + * The arguments GSS_KRB5_IMPORT_RFC4121_CONTEXT_X are the serialized + * form of initiator_flag || flags || keytype || session_key. The session + * key length is inferred from the keytype. + */ + ret = krb5_store_uint8(sp, initiator_flag); + if (ret != 0) + goto out; + + ret = krb5_store_uint32(sp, gss_flags); + if (ret != 0) + goto out; + + ret = krb5_store_int32(sp, rfc3961_enctype); + if (ret != 0) + goto out; + + if (krb5_storage_write(sp, session_key->value, session_key->length) + != session_key->length) { + ret = ENOMEM; + goto out; + } + + ret = krb5_storage_to_data(sp, &d); + if (ret != 0) + goto out; + + rfc4121_args.length = d.length; + rfc4121_args.value = d.data; + + major = gss_set_sec_context_option(minor, rfc4121_context_handle, + GSS_KRB5_IMPORT_RFC4121_CONTEXT_X, + &rfc4121_args); + +out: + _gss_secure_release_buffer(&tmpMinor, &rfc4121_args); + krb5_storage_free(sp); + + if (major == GSS_S_FAILURE && *minor == 0) + *minor = ret; + + return major; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_seal.c b/third_party/heimdal/lib/gssapi/mech/gss_seal.c new file mode 100644 index 0000000..26c65da --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_seal.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_seal.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_seal(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + + return (gss_wrap(minor_status, + context_handle, conf_req_flag, qop_req, + input_message_buffer, conf_state, + output_message_buffer)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_set_cred_option.c b/third_party/heimdal/lib/gssapi/mech/gss_set_cred_option.c new file mode 100644 index 0000000..39b49e3 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_set_cred_option.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_set_cred_option (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID object, + const gss_buffer_t value) +{ + struct _gss_cred *cred = (struct _gss_cred *) *cred_handle; + OM_uint32 major_status = GSS_S_COMPLETE; + struct _gss_mechanism_cred *mc; + int one_ok = 0; + + *minor_status = 0; + + _gss_load_mech(); + + if (cred == NULL) { + struct _gss_mech_switch *m; + + cred = _gss_mg_alloc_cred(); + if (cred == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + + if (m->gm_mech.gm_set_cred_option == NULL) + continue; + + mc = malloc(sizeof(*mc)); + if (mc == NULL) { + *cred_handle = (gss_cred_id_t)cred; + gss_release_cred(minor_status, cred_handle); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + mc->gmc_mech = &m->gm_mech; + mc->gmc_mech_oid = m->gm_mech_oid; + mc->gmc_cred = GSS_C_NO_CREDENTIAL; + + major_status = m->gm_mech.gm_set_cred_option( + minor_status, &mc->gmc_cred, object, value); + + if (major_status) { + free(mc); + continue; + } + one_ok = 1; + HEIM_TAILQ_INSERT_TAIL(&cred->gc_mc, mc, gmc_link); + } + *cred_handle = (gss_cred_id_t)cred; + if (!one_ok) { + OM_uint32 junk; + gss_release_cred(&junk, cred_handle); + } + } else { + gssapi_mech_interface m; + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + m = mc->gmc_mech; + + if (m == NULL) + return GSS_S_BAD_MECH; + + if (m->gm_set_cred_option == NULL) + continue; + + major_status = m->gm_set_cred_option(minor_status, + &mc->gmc_cred, object, value); + if (major_status == GSS_S_COMPLETE) + one_ok = 1; + else + _gss_mg_error(m, *minor_status); + + } + } + if (one_ok) { + *minor_status = 0; + return GSS_S_COMPLETE; + } + return major_status; +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_set_name_attribute.c b/third_party/heimdal/lib/gssapi/mech/gss_set_name_attribute.c new file mode 100644 index 0000000..4e963f3 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_set_name_attribute.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_set_name_attribute(OM_uint32 *minor_status, + gss_name_t input_name, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (!m->gm_set_name_attribute) + continue; + + major_status = m->gm_set_name_attribute(minor_status, + mn->gmn_name, + complete, + attr, + value); + if (GSS_ERROR(major_status)) + _gss_mg_error(m, *minor_status); + else + break; + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_set_neg_mechs.c b/third_party/heimdal/lib/gssapi/mech/gss_set_neg_mechs.c new file mode 100644 index 0000000..7c527b2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_set_neg_mechs.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_set_neg_mechs(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID_set mechs) +{ + struct _gss_cred *cred = (struct _gss_cred *)cred_handle; + OM_uint32 major_status, junk; + gss_OID_set tmp_mechs; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (cred_handle == GSS_C_NO_CREDENTIAL || mechs == GSS_C_NO_OID_SET) + return GSS_S_CALL_INACCESSIBLE_READ; + + major_status = gss_duplicate_oid_set(minor_status, mechs, &tmp_mechs); + if (major_status != GSS_S_COMPLETE) + return major_status; + + gss_release_oid_set(&junk, &cred->gc_neg_mechs); + cred->gc_neg_mechs = tmp_mechs; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c b/third_party/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c new file mode 100644 index 0000000..5b92ac4 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2004, 2020, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID object, + const gss_buffer_t value) +{ + struct _gss_context *ctx; + OM_uint32 major_status; + gssapi_mech_interface mi; + int allocated_ctx; + + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + _gss_load_mech(); + + ctx = (struct _gss_context *) *context_handle; + if (ctx == NULL) { + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + allocated_ctx = 1; + } else { + allocated_ctx = 0; + } + + major_status = GSS_S_BAD_MECH; + + if (allocated_ctx) { + struct _gss_mech_switch *m; + + HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + mi = &m->gm_mech; + + if (mi->gm_set_sec_context_option == NULL) + continue; + major_status = mi->gm_set_sec_context_option(minor_status, + &ctx->gc_ctx, object, value); + if (major_status == GSS_S_COMPLETE) { + ctx->gc_mech = mi; + break; + } else { + _gss_mg_error(mi, *minor_status); + } + } + } else { + mi = ctx->gc_mech; + if (mi->gm_set_sec_context_option != NULL) { + major_status = mi->gm_set_sec_context_option(minor_status, + &ctx->gc_ctx, object, value); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(mi, *minor_status); + } + } + + if (allocated_ctx) { + if (major_status == GSS_S_COMPLETE) + *context_handle = (gss_ctx_id_t)ctx; + else + free(ctx); + } + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_sign.c b/third_party/heimdal/lib/gssapi/mech/gss_sign.c new file mode 100644 index 0000000..4ef99c1 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_sign.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_sign.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_sign(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int qop_req, + gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + + return gss_get_mic(minor_status, + context_handle, qop_req, message_buffer, message_token); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_store_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_store_cred.c new file mode 100644 index 0000000..7a9344a --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_store_cred.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +/* See RFC5588 */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_store_cred(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + return gss_store_cred_into(minor_status, + input_cred_handle, + cred_usage, + desired_mech, + overwrite_cred, + default_cred, + GSS_C_NO_CRED_STORE, + elements_stored, + cred_usage_stored); +} + diff --git a/third_party/heimdal/lib/gssapi/mech/gss_store_cred_into.c b/third_party/heimdal/lib/gssapi/mech/gss_store_cred_into.c new file mode 100644 index 0000000..1c739b0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_store_cred_into.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +static OM_uint32 +store_mech_cred(OM_uint32 *minor_status, + gssapi_mech_interface m, + const struct _gss_mechanism_cred *mc, + gss_cred_usage_t input_usage, + OM_uint32 store_cred_flags, + gss_const_key_value_set_t cred_store, + gss_cred_usage_t *usage_stored, + gss_buffer_set_t *env) +{ + OM_uint32 major_status; + OM_uint32 overwrite_cred = + !!(store_cred_flags & GSS_C_STORE_CRED_OVERWRITE); + OM_uint32 default_cred = !!(store_cred_flags & GSS_C_STORE_CRED_DEFAULT); + + if (m->gm_store_cred_into2) + major_status = m->gm_store_cred_into2(minor_status, mc->gmc_cred, + input_usage, &m->gm_mech_oid, + store_cred_flags, cred_store, + NULL, usage_stored, + env); + else if (m->gm_store_cred_into) + major_status = m->gm_store_cred_into(minor_status, mc->gmc_cred, + input_usage, &m->gm_mech_oid, + overwrite_cred, default_cred, + cred_store, NULL, usage_stored); + else if (cred_store == GSS_C_NO_CRED_STORE && m->gm_store_cred) + major_status = m->gm_store_cred(minor_status, mc->gmc_cred, + input_usage, &m->gm_mech_oid, + overwrite_cred, default_cred, + NULL, usage_stored); + else + major_status = GSS_S_UNAVAILABLE; + + return major_status; +} + +/* + * See RFC5588 for gss_store_cred(). This function is a variant that takes a + * const key/value hashmap-like thing that specifies a credential store in a + * mechanism- and implementation-specific way, though Heimdal and MIT agree on + * at least the following keys for the Kerberos mechanism: ccache, keytab, and + * client_keytab. A set of environment variables may be output as well + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_store_cred_into2(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_usage_t input_usage, + const gss_OID desired_mech, + OM_uint32 store_cred_flags, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored, + gss_buffer_set_t *env) +{ + struct _gss_cred *cred = (struct _gss_cred *)input_cred_handle; + struct _gss_mechanism_cred *mc; + OM_uint32 major_status; + OM_uint32 minor; + size_t successes; + + if (env != NULL) + *env = NULL; + + if (input_cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + + if (cred_usage_stored) + *cred_usage_stored = 0; + + if (elements_stored) { + *elements_stored = GSS_C_NO_OID_SET; + + major_status = gss_create_empty_oid_set(minor_status, + elements_stored); + if (major_status != GSS_S_COMPLETE) + return major_status; + } + + major_status = GSS_S_NO_CRED; + successes = 0; + + HEIM_TAILQ_FOREACH(mc, &cred->gc_mc, gmc_link) { + gssapi_mech_interface m = mc->gmc_mech; + + if (m == NULL || (m->gm_flags & GM_USE_MG_CRED) != 0) + continue; + + if (desired_mech != GSS_C_NO_OID && + !gss_oid_equal(&m->gm_mech_oid, desired_mech)) + continue; + + major_status = store_mech_cred(minor_status, m, mc, input_usage, + store_cred_flags, cred_store, + cred_usage_stored, env); + if (major_status == GSS_S_COMPLETE) { + if (elements_stored && desired_mech != GSS_C_NO_OID) + gss_add_oid_set_member(&minor, desired_mech, elements_stored); + successes++; + } else if (desired_mech != GSS_C_NO_OID) { + _gss_mg_error(m, *minor_status); + gss_release_oid_set(&minor, elements_stored); + return major_status; + } + } + + if (successes > 0) { + *minor_status = 0; + major_status = GSS_S_COMPLETE; + } + + heim_assert(successes || major_status != GSS_S_COMPLETE, + "cred storage failed, but no error raised"); + + return major_status; +} + +/* + * See RFC5588 for gss_store_cred(). This function is a variant that takes a + * const key/value hashmap-like thing that specifies a credential store in a + * mechanism- and implementation-specific way, though Heimdal and MIT agree on + * at least the following keys for the Kerberos mechanism: ccache, keytab, and + * client_keytab. + */ +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_store_cred_into(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_usage_t input_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + OM_uint32 store_cred_flags = + (overwrite_cred ? GSS_C_STORE_CRED_OVERWRITE : 0) | + (default_cred ? GSS_C_STORE_CRED_DEFAULT : 0); + return gss_store_cred_into2(minor_status, input_cred_handle, input_usage, + desired_mech, store_cred_flags, cred_store, + elements_stored, cred_usage_stored, NULL); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c b/third_party/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c new file mode 100644 index 0000000..715d34b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_test_oid_set_member.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_test_oid_set_member(OM_uint32 *minor_status, + const gss_OID member, + const gss_OID_set set, + int *present) +{ + size_t i; + + *present = 0; + for (i = 0; i < set->count; i++) + if (gss_oid_equal(member, &set->elements[i])) + *present = 1; + + *minor_status = 0; + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_unseal.c b/third_party/heimdal/lib/gssapi/mech/gss_unseal.c new file mode 100644 index 0000000..0add03d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_unseal.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_unseal.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_unseal(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + int *qop_state) +{ + + return (gss_unwrap(minor_status, + context_handle, input_message_buffer, + output_message_buffer, conf_state, (gss_qop_t *)qop_state)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_unwrap.c b/third_party/heimdal/lib/gssapi/mech/gss_unwrap.c new file mode 100644 index 0000000..dd6363b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_unwrap.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_unwrap.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_unwrap(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + if (conf_state) + *conf_state = 0; + if (qop_state) + *qop_state = 0; + + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + m = ctx->gc_mech; + + return (m->gm_unwrap(minor_status, ctx->gc_ctx, + input_message_buffer, output_message_buffer, + conf_state, qop_state)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_utils.c b/third_party/heimdal/lib/gssapi/mech/gss_utils.c new file mode 100644 index 0000000..bb7e619 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_utils.c @@ -0,0 +1,324 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_utils.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +static OM_uint32 +_gss_copy_oid(OM_uint32 *minor_status, + gss_const_OID from_oid, + gss_OID to_oid) +{ + size_t len = from_oid->length; + + *minor_status = 0; + to_oid->elements = malloc(len); + if (!to_oid->elements) { + to_oid->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + to_oid->length = (OM_uint32)len; + memcpy(to_oid->elements, from_oid->elements, len); + return (GSS_S_COMPLETE); +} + +OM_uint32 +_gss_free_oid(OM_uint32 *minor_status, gss_OID oid) +{ + *minor_status = 0; + if (oid->elements) { + free(oid->elements); + oid->elements = NULL; + oid->length = 0; + } + return (GSS_S_COMPLETE); +} + +struct _gss_interned_oid { + HEIM_SLIST_ATOMIC_ENTRY(_gss_interned_oid) gio_link; + gss_OID_desc gio_oid; +}; + +static HEIM_SLIST_ATOMIC_HEAD(_gss_interned_oid_list, _gss_interned_oid) interned_oids = +HEIM_SLIST_HEAD_INITIALIZER(interned_oids); + +extern gss_OID _gss_ot_internal[]; +extern size_t _gss_ot_internal_count; + +static OM_uint32 +intern_oid_static(OM_uint32 *minor_status, + gss_const_OID from_oid, + gss_OID *to_oid) +{ + size_t i; + + /* statically allocated OIDs */ + for (i = 0; i < _gss_ot_internal_count; i++) { + if (gss_oid_equal(_gss_ot_internal[i], from_oid)) { + *minor_status = 0; + *to_oid = _gss_ot_internal[i]; + return GSS_S_COMPLETE; + } + } + + return GSS_S_CONTINUE_NEEDED; +} + +OM_uint32 +_gss_intern_oid(OM_uint32 *minor_status, + gss_const_OID from_oid, + gss_OID *to_oid) +{ + OM_uint32 major_status; + struct _gss_interned_oid *iop; + + major_status = intern_oid_static(minor_status, from_oid, to_oid); + if (major_status != GSS_S_CONTINUE_NEEDED) + return major_status; + + HEIM_SLIST_ATOMIC_FOREACH(iop, &interned_oids, gio_link) { + if (gss_oid_equal(&iop->gio_oid, from_oid)) { + *minor_status = 0; + *to_oid = &iop->gio_oid; + return GSS_S_COMPLETE; + } + } + + iop = malloc(sizeof(*iop)); + if (iop == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + major_status = _gss_copy_oid(minor_status, from_oid, &iop->gio_oid); + if (GSS_ERROR(major_status)) { + free(iop); + return major_status; + } + + HEIM_SLIST_ATOMIC_INSERT_HEAD(&interned_oids, iop, gio_link); + + *minor_status = 0; + *to_oid = &iop->gio_oid; + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gss_copy_buffer(OM_uint32 *minor_status, + const gss_buffer_t from_buf, gss_buffer_t to_buf) +{ + size_t len = from_buf->length; + + *minor_status = 0; + to_buf->value = malloc(len); + if (!to_buf->value) { + *minor_status = ENOMEM; + to_buf->length = 0; + return GSS_S_FAILURE; + } + to_buf->length = len; + memcpy(to_buf->value, from_buf->value, len); + return (GSS_S_COMPLETE); +} + +OM_uint32 +_gss_secure_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer) +{ + if (buffer->value) + memset_s(buffer->value, buffer->length, 0, buffer->length); + + return gss_release_buffer(minor_status, buffer); +} + +OM_uint32 +_gss_secure_release_buffer_set(OM_uint32 *minor_status, + gss_buffer_set_t *buffer_set) +{ + size_t i; + OM_uint32 minor; + + *minor_status = 0; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) + return GSS_S_COMPLETE; + + for (i = 0; i < (*buffer_set)->count; i++) + _gss_secure_release_buffer(&minor, &((*buffer_set)->elements[i])); + + (*buffer_set)->count = 0; + + return gss_release_buffer_set(minor_status, buffer_set); +} + +void +_gss_mg_encode_le_uint32(uint32_t n, uint8_t *p) +{ + p[0] = (n >> 0 ) & 0xFF; + p[1] = (n >> 8 ) & 0xFF; + p[2] = (n >> 16) & 0xFF; + p[3] = (n >> 24) & 0xFF; +} + +void +_gss_mg_decode_le_uint32(const void *ptr, uint32_t *n) +{ + const uint8_t *p = ptr; + *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +void +_gss_mg_encode_be_uint32(uint32_t n, uint8_t *p) +{ + p[0] = (n >> 24) & 0xFF; + p[1] = (n >> 16) & 0xFF; + p[2] = (n >> 8 ) & 0xFF; + p[3] = (n >> 0 ) & 0xFF; +} + +void +_gss_mg_decode_be_uint32(const void *ptr, uint32_t *n) +{ + const uint8_t *p = ptr; + *n = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); +} + +void +_gss_mg_encode_le_uint16(uint16_t n, uint8_t *p) +{ + p[0] = (n >> 0 ) & 0xFF; + p[1] = (n >> 8 ) & 0xFF; +} + +void +_gss_mg_decode_le_uint16(const void *ptr, uint16_t *n) +{ + const uint8_t *p = ptr; + *n = (p[0] << 0) | (p[1] << 8); +} + +void +_gss_mg_encode_be_uint16(uint16_t n, uint8_t *p) +{ + p[0] = (n >> 8) & 0xFF; + p[1] = (n >> 0) & 0xFF; +} + +void +_gss_mg_decode_be_uint16(const void *ptr, uint16_t *n) +{ + const uint8_t *p = ptr; + *n = (p[0] << 24) | (p[1] << 16); +} + +OM_uint32 +_gss_mg_ret_oid(OM_uint32 *minor, + krb5_storage *sp, + gss_OID *oidp) +{ + krb5_data data; + gss_OID_desc oid; + OM_uint32 major; + + *minor = 0; + *oidp = GSS_C_NO_OID; + + *minor = krb5_ret_data(sp, &data); + if (*minor) + return GSS_S_FAILURE; + + if (data.length) { + oid.length = data.length; + oid.elements = data.data; + + major = _gss_intern_oid(minor, &oid, oidp); + } else + major = GSS_S_COMPLETE; + + krb5_data_free(&data); + + return major; +} + +OM_uint32 +_gss_mg_store_oid(OM_uint32 *minor, + krb5_storage *sp, + gss_const_OID oid) +{ + krb5_data data; + + if (oid) { + data.length = oid->length; + data.data = oid->elements; + } else + krb5_data_zero(&data); + + *minor = krb5_store_data(sp, data); + + return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE; +} + +OM_uint32 +_gss_mg_ret_buffer(OM_uint32 *minor, + krb5_storage *sp, + gss_buffer_t buffer) +{ + krb5_data data; + + _mg_buffer_zero(buffer); + + *minor = krb5_ret_data(sp, &data); + if (*minor == 0) { + if (data.length) { + buffer->length = data.length; + buffer->value = data.data; + } else + krb5_data_free(&data); + } + + return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE; +} + +OM_uint32 +_gss_mg_store_buffer(OM_uint32 *minor, + krb5_storage *sp, + gss_const_buffer_t buffer) +{ + krb5_data data; + + if (buffer) { + data.length = buffer->length; + data.data = buffer->value; + } else + krb5_data_zero(&data); + + *minor = krb5_store_data(sp, data); + + return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_verify.c b/third_party/heimdal/lib/gssapi/mech/gss_verify.c new file mode 100644 index 0000000..dd53ddb --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_verify.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_verify.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_verify(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t message_buffer, + gss_buffer_t token_buffer, + int *qop_state) +{ + + return (gss_verify_mic(minor_status, + context_handle, message_buffer, token_buffer, + (gss_qop_t *)qop_state)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_verify_mic.c b/third_party/heimdal/lib/gssapi/mech/gss_verify_mic.c new file mode 100644 index 0000000..ae3b52f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_verify_mic.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_verify_mic.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_verify_mic(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + if (qop_state) + *qop_state = 0; + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + m = ctx->gc_mech; + + return (m->gm_verify_mic(minor_status, ctx->gc_ctx, + message_buffer, token_buffer, qop_state)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_wrap.c b/third_party/heimdal/lib/gssapi/mech/gss_wrap.c new file mode 100644 index 0000000..82378d3 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_wrap.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_wrap.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +/** + * Wrap a message using either confidentiality (encryption + + * signature) or sealing (signature). + * + * @param minor_status minor status code. + * @param context_handle context handle. + * @param conf_req_flag if non zero, confidentiality is requestd. + * @param qop_req type of protection needed, in most cases it GSS_C_QOP_DEFAULT should be passed in. + * @param input_message_buffer messages to wrap + * @param conf_state returns non zero if confidentiality was honoured. + * @param output_message_buffer the resulting buffer, release with gss_release_buffer(). + * + * @ingroup gssapi + */ + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + if (conf_state) + *conf_state = 0; + _mg_buffer_zero(output_message_buffer); + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + m = ctx->gc_mech; + + return (m->gm_wrap(minor_status, ctx->gc_ctx, + conf_req_flag, qop_req, input_message_buffer, + conf_state, output_message_buffer)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c b/third_party/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c new file mode 100644 index 0000000..3bcd9ec --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_wrap_size_limit.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_size_limit(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m; + + *max_input_size = 0; + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + m = ctx->gc_mech; + + return (m->gm_wrap_size_limit(minor_status, ctx->gc_ctx, + conf_req_flag, qop_req, req_output_size, max_input_size)); +} diff --git a/third_party/heimdal/lib/gssapi/mech/gssapi.asn1 b/third_party/heimdal/lib/gssapi/mech/gssapi.asn1 new file mode 100644 index 0000000..96ca6bd --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gssapi.asn1 @@ -0,0 +1,12 @@ +-- $Id$ + +GSS-API DEFINITIONS ::= BEGIN + +IMPORTS HEIM_ANY_SET FROM heim; + +GSSAPIContextToken ::= [APPLICATION 0] IMPLICIT SEQUENCE { + thisMech OBJECT IDENTIFIER, + innerContextToken HEIM_ANY_SET +} + +END diff --git a/third_party/heimdal/lib/gssapi/mech/gssspi_exchange_meta_data.c b/third_party/heimdal/lib/gssapi/mech/gssspi_exchange_meta_data.c new file mode 100644 index 0000000..fa98cbd --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gssspi_exchange_meta_data.c @@ -0,0 +1,115 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * Portions Copyright (c) 2019 AuriStor, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gssspi_exchange_meta_data( + OM_uint32 *minor_status, + gss_const_OID input_mech_type, + gss_cred_id_t input_cred_handle, + gss_ctx_id_t *context_handle, + gss_const_name_t target_name, + OM_uint32 req_flags, + gss_const_buffer_t meta_data) +{ + OM_uint32 major_status, junk; + gssapi_mech_interface m; + struct _gss_name *name = (struct _gss_name *) target_name; + struct _gss_mechanism_name *mn; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + gss_cred_id_t cred_handle; + int allocated_ctx; + gss_const_OID mech_type = input_mech_type; + + *minor_status = 0; + + if (mech_type == GSS_C_NO_OID) + return GSS_S_BAD_MECH; + + if (ctx == NULL) { + ctx = calloc(1, sizeof(struct _gss_context)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + m = ctx->gc_mech = __gss_get_mechanism(mech_type); + if (m == NULL) { + free(ctx); + return GSS_S_BAD_MECH; + } + allocated_ctx = 1; + } else { + m = ctx->gc_mech; + mech_type = &m->gm_mech_oid; + allocated_ctx = 0; + } + + if (m->gm_exchange_meta_data == NULL) { + major_status = GSS_S_BAD_MECH; + goto cleanup; + } + + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (major_status != GSS_S_COMPLETE) + goto cleanup; + + if (m->gm_flags & GM_USE_MG_CRED) + cred_handle = input_cred_handle; + else + cred_handle = _gss_mg_find_mech_cred(input_cred_handle, mech_type); + + if (input_cred_handle != GSS_C_NO_CREDENTIAL && + cred_handle == NULL) { + major_status = GSS_S_NO_CRED; + goto cleanup; + } + + /* note: mechanism is not obligated to allocate a context on success */ + major_status = m->gm_exchange_meta_data(minor_status, + mech_type, + cred_handle, + &ctx->gc_ctx, + mn ? mn->gmn_name : GSS_C_NO_NAME, + req_flags, + meta_data); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, *minor_status); + +cleanup: + if (allocated_ctx && major_status != GSS_S_COMPLETE) + gss_delete_sec_context(&junk, (gss_ctx_id_t *)&ctx, GSS_C_NO_BUFFER); + + *context_handle = (gss_ctx_id_t) ctx; + + _gss_mg_log(10, "gss-emd: return %d/%d", (int)major_status, (int)*minor_status); + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gssspi_query_mechanism_info.c b/third_party/heimdal/lib/gssapi/mech/gssspi_query_mechanism_info.c new file mode 100644 index 0000000..82fe9d9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gssspi_query_mechanism_info.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2019 AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gssspi_query_mechanism_info( + OM_uint32 *minor_status, + gss_const_OID mech_type, + unsigned char auth_scheme[16]) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + + *minor_status = 0; + + if (mech_type == GSS_C_NO_OID) + return GSS_S_BAD_MECH; + + m = __gss_get_mechanism(mech_type); + if (m == NULL || m->gm_query_mechanism_info == NULL) + return GSS_S_BAD_MECH; + + major_status = m->gm_query_mechanism_info(minor_status, + mech_type, + auth_scheme); + + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, *minor_status); + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/gssspi_query_meta_data.c b/third_party/heimdal/lib/gssapi/mech/gssspi_query_meta_data.c new file mode 100644 index 0000000..490bbc9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/gssspi_query_meta_data.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * Portions Copyright (c) 2019 AuriStor, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gssspi_query_meta_data( + OM_uint32 *minor_status, + gss_const_OID input_mech_type, + gss_cred_id_t input_cred_handle, + gss_ctx_id_t *context_handle, + gss_const_name_t target_name, + OM_uint32 req_flags, + gss_buffer_t meta_data) +{ + OM_uint32 major_status, junk; + gssapi_mech_interface m; + struct _gss_name *name = (struct _gss_name *) target_name; + struct _gss_mechanism_name *mn; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + gss_cred_id_t cred_handle; + int allocated_ctx; + gss_const_OID mech_type = input_mech_type; + + *minor_status = 0; + + _mg_buffer_zero(meta_data); + + if (mech_type == GSS_C_NO_OID) + return GSS_S_BAD_MECH; + + if (ctx == NULL) { + ctx = calloc(1, sizeof(struct _gss_context)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + m = ctx->gc_mech = __gss_get_mechanism(mech_type); + if (m == NULL) { + free(ctx); + return GSS_S_BAD_MECH; + } + allocated_ctx = 1; + } else { + m = ctx->gc_mech; + mech_type = &m->gm_mech_oid; + allocated_ctx = 0; + } + + if (m->gm_query_meta_data == NULL) { + major_status = GSS_S_BAD_MECH; + goto cleanup; + } + + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (major_status != GSS_S_COMPLETE) + goto cleanup; + + if (m->gm_flags & GM_USE_MG_CRED) + cred_handle = input_cred_handle; + else + cred_handle = _gss_mg_find_mech_cred(input_cred_handle, mech_type); + + if (input_cred_handle != GSS_C_NO_CREDENTIAL && + cred_handle == NULL) { + major_status = GSS_S_NO_CRED; + goto cleanup; + } + + /* note: mechanism is not obligated to allocate a context on success */ + major_status = m->gm_query_meta_data(minor_status, + mech_type, + cred_handle, + &ctx->gc_ctx, + mn ? mn->gmn_name : GSS_C_NO_NAME, + req_flags, + meta_data); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, *minor_status); + +cleanup: + if (allocated_ctx && major_status != GSS_S_COMPLETE) + gss_delete_sec_context(&junk, (gss_ctx_id_t *)&ctx, GSS_C_NO_BUFFER); + + *context_handle = (gss_ctx_id_t) ctx; + + _gss_mg_log(10, "gss-qmd: return %d/%d", (int)major_status, (int)*minor_status); + + return major_status; +} diff --git a/third_party/heimdal/lib/gssapi/mech/mech.5 b/third_party/heimdal/lib/gssapi/mech/mech.5 new file mode 100644 index 0000000..56e916e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/mech.5 @@ -0,0 +1,94 @@ +.\" Copyright (c) 2005 Doug Rabson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libgssapi/mech.5,v 1.1 2005/12/29 14:40:20 dfr Exp $ +.Dd November 14, 2005 +.Dt MECH 5 +.Os +.Sh NAME +.Nm mech , +.Nm qop +.Nd "GSS-API Mechanism and QOP files" +.Sh SYNOPSIS +.Pa "/etc/gss/mech" +.Pa "/etc/gss/qop" +.Sh DESCRIPTION +The +.Pa "/etc/gss/mech" +file contains a list of installed GSS-API security mechanisms. +Each line of the file either contains a comment if the first character +is '#' or it contains five fields with the following meanings: +.Bl -tag +.It Name +The name of this GSS-API mechanism. +.It Object identifier +The OID for this mechanism. +.It Library +A shared library containing the implementation of this mechanism. +.It Kernel module (optional) +A kernel module containing the implementation of this mechanism (not +yet supported in FreeBSD). +.It Library options (optional) +Optionsal parameters interpreted by the mechanism. Library options +must be enclosed in brackets ([ ]) to differentiate them from the +optional kernel module entry. +.El +.Pp +The +.Pa "/etc/gss/qop" +file contains a list of Quality of Protection values for use with +GSS-API. +Each line of the file either contains a comment if the first character +is '#' or it contains three fields with the following meanings: +.Bl -tag +.It QOP string +The name of this Quality of Protection algorithm. +.It QOP value +The numeric value used to select this algorithm for use with GSS-API +functions such as +.Xr gss_get_mic 3 . +.It Mechanism name +The GSS-API mechanism name that corresponds to this algorithm. +.El +.Sh EXAMPLES +This is a typical entry from +.Pa "/etc/gss/mech" : +.Bd -literal +kerberosv5 1.2.840.113554.1.2.2 /usr/lib/libgssapi_krb5.so.8 - +.Ed +.Pp +This is a typical entry from +.Pa "/etc/gss/qop" : +.Bd -literal +GSS_KRB5_CONF_C_QOP_DES 0x0100 kerberosv5 +.Ed +.Sh HISTORY +The +.Nm +manual page example first appeared in +.Fx 7.0 . +.Sh AUTHORS +This +manual page was written by +.An Doug Rabson Aq Mt dfr@FreeBSD.org . diff --git a/third_party/heimdal/lib/gssapi/mech/mech_locl.h b/third_party/heimdal/lib/gssapi/mech/mech_locl.h new file mode 100644 index 0000000..d451b87 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/mech_locl.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#include <config.h> + +#include <roken.h> + +#include <krb5-types.h> + +#include <ctype.h> + +#include <heimbase.h> + +#include <gssapi_asn1.h> +#include <der.h> + +#include <gssapi.h> +#include <gssapi_mech.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> + +#include <heimqueue.h> + +#include "context.h" +#include "cred.h" +#include "mech_switch.h" +#include "name.h" +#include "utils.h" +#include "compat.h" + +#define _mg_buffer_zero(buffer) \ + do { \ + if (buffer) { \ + (buffer)->value = NULL; \ + (buffer)->length = 0; \ + } \ + } while(0) + +#define _mg_oid_set_zero(oid_set) \ + do { \ + if (oid_set) { \ + (oid_set)->elements = NULL; \ + (oid_set)->count = 0; \ + } \ + } while(0) diff --git a/third_party/heimdal/lib/gssapi/mech/mech_switch.h b/third_party/heimdal/lib/gssapi/mech/mech_switch.h new file mode 100644 index 0000000..abc89ae --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/mech_switch.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/mech_switch.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id$ + */ + +#include <gssapi_mech.h> + +struct _gss_mech_switch { + HEIM_TAILQ_ENTRY(_gss_mech_switch) gm_link; + gss_OID gm_mech_oid; + gss_OID_set gm_name_types; + void *gm_so; + gssapi_mech_interface_desc gm_mech; +}; +HEIM_TAILQ_HEAD(_gss_mech_switch_list, _gss_mech_switch); +extern struct _gss_mech_switch_list _gss_mechs; +extern gss_OID_set _gss_mech_oids; + +void _gss_load_mech(void); diff --git a/third_party/heimdal/lib/gssapi/mech/name.h b/third_party/heimdal/lib/gssapi/mech/name.h new file mode 100644 index 0000000..4a03486 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/name.h @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/name.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id$ + */ + +struct _gss_mechanism_name { + HEIM_TAILQ_ENTRY(_gss_mechanism_name) gmn_link; + gssapi_mech_interface gmn_mech; /* mechanism ops for MN */ + gss_OID gmn_mech_oid; /* mechanism oid for MN */ + gss_name_t gmn_name; /* underlying MN */ +}; +HEIM_TAILQ_HEAD(_gss_mechanism_name_list, _gss_mechanism_name); + +struct _gss_name { + gss_OID gn_type; /* type of name */ + gss_buffer_desc gn_value; /* value (as imported) */ + struct _gss_mechanism_name_list gn_mn; /* list of MNs */ +}; + +OM_uint32 + _gss_find_mn(OM_uint32 *, struct _gss_name *, gss_const_OID, + struct _gss_mechanism_name **); +struct _gss_name * + _gss_create_name(gss_name_t new_mn, gssapi_mech_interface m); +void _gss_mg_release_name(struct _gss_name *); + + +void _gss_mg_check_name(gss_const_name_t name); + +gss_name_t + _gss_mg_get_underlying_mech_name(gss_name_t name, gss_const_OID mech); + +OM_uint32 +_gss_mech_import_name(OM_uint32 * minor_status, + gss_const_OID mech, + struct _gss_name_type *names, + const gss_buffer_t input_name_buffer, + gss_const_OID input_name_type, + gss_name_t *output_name); + +OM_uint32 +gss_mg_export_name(OM_uint32 *minor_status, + const gss_const_OID mech, + const void *name, + size_t length, + gss_buffer_t exported_name); + +OM_uint32 +_gss_mech_inquire_names_for_mech(OM_uint32 * minor_status, + struct _gss_name_type *names, + gss_OID_set *name_types); + + diff --git a/third_party/heimdal/lib/gssapi/mech/utils.h b/third_party/heimdal/lib/gssapi/mech/utils.h new file mode 100644 index 0000000..208a59c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/mech/utils.h @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/utils.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id$ + */ + +OM_uint32 _gss_free_oid(OM_uint32 *, gss_OID); +OM_uint32 _gss_intern_oid(OM_uint32 *, gss_const_OID, gss_OID *); +OM_uint32 _gss_copy_buffer(OM_uint32 *minor_status, + const gss_buffer_t from_buf, gss_buffer_t to_buf); +OM_uint32 _gss_secure_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer); +OM_uint32 _gss_secure_release_buffer_set(OM_uint32 *minor_status, + gss_buffer_set_t *buffer_set); + +void _gss_mg_encode_le_uint32(uint32_t n, uint8_t *p); +void _gss_mg_decode_le_uint32(const void *ptr, uint32_t *n); +void _gss_mg_encode_be_uint32(uint32_t n, uint8_t *p); +void _gss_mg_decode_be_uint32(const void *ptr, uint32_t *n); + +void _gss_mg_encode_le_uint16(uint16_t n, uint8_t *p); +void _gss_mg_decode_le_uint16(const void *ptr, uint16_t *n); +void _gss_mg_encode_be_uint16(uint16_t n, uint8_t *p); +void _gss_mg_decode_be_uint16(const void *ptr, uint16_t *n); + +OM_uint32 +_gss_mg_import_rfc4121_context(OM_uint32 *minor, + uint8_t initiator_flag, + OM_uint32 gss_flags, + int32_t rfc3961_enctype, + gss_const_buffer_t session_key, + gss_ctx_id_t *rfc4121_context_handle); + +#include <krb5.h> + +/* + * Note: functions below support zero-length OIDs and buffers and will + * return NULL values. Callers should handle accordingly. + */ + +OM_uint32 +_gss_mg_ret_oid(OM_uint32 *minor, + krb5_storage *sp, + gss_OID *oidp); + +OM_uint32 +_gss_mg_store_oid(OM_uint32 *minor, + krb5_storage *sp, + gss_const_OID oid); + +OM_uint32 +_gss_mg_ret_buffer(OM_uint32 *minor, + krb5_storage *sp, + gss_buffer_t buffer); + +OM_uint32 +_gss_mg_store_buffer(OM_uint32 *minor, + krb5_storage *sp, + gss_const_buffer_t buffer); diff --git a/third_party/heimdal/lib/gssapi/netlogon/accept_sec_context.c b/third_party/heimdal/lib/gssapi/netlogon/accept_sec_context.c new file mode 100644 index 0000000..06ddfd5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/accept_sec_context.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +/* + * Not implemented: this is needed only by domain controllers. + */ + +OM_uint32 +_netlogon_accept_sec_context +(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle + ) +{ + + output_token->value = NULL; + output_token->length = 0; + + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_FAILURE; + + if (input_token_buffer == GSS_C_NO_BUFFER) + return GSS_S_FAILURE; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (mech_type) + *mech_type = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } else { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/acquire_cred.c b/third_party/heimdal/lib/gssapi/netlogon/acquire_cred.c new file mode 100644 index 0000000..d790d08 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/acquire_cred.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" +#include <gssapi_spi.h> + +OM_uint32 +_netlogon_acquire_cred(OM_uint32 * min_stat, + gss_const_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec) +{ + OM_uint32 ret; + gssnetlogon_cred cred; + + /* only initiator support so far */ + if (cred_usage != GSS_C_INITIATE) + return GSS_S_FAILURE; + + if (desired_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + cred = (gssnetlogon_cred)calloc(1, sizeof(*cred)); + if (cred == NULL) { + *min_stat = ENOMEM; + return GSS_S_FAILURE; + } + cred->SignatureAlgorithm = NL_SIGN_ALG_HMAC_MD5; + cred->SealAlgorithm = NL_SEAL_ALG_RC4; + + ret = _netlogon_duplicate_name(min_stat, desired_name, + (gss_name_t *)&cred->Name); + if (GSS_ERROR(ret)) { + free(cred); + return ret; + } + + *output_cred_handle = (gss_cred_id_t)cred; + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NO_OID_SET; + if (time_rec != NULL) + *time_rec = GSS_C_INDEFINITE; + + return GSS_S_COMPLETE; +} + +OM_uint32 +_netlogon_acquire_cred_ex(gss_status_id_t status, + gss_const_name_t desired_name, + OM_uint32 flags, + OM_uint32 time_req, + gss_cred_usage_t cred_usage, + gss_auth_identity_t identity, + void *ctx, + void (*complete)(void *, OM_uint32, gss_status_id_t, gss_cred_id_t, OM_uint32)) +{ + return GSS_S_UNAVAILABLE; +} + +/* + * value contains 16 byte session key + */ +static OM_uint32 +_netlogon_set_session_key(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + gssnetlogon_cred cred; + + if (*cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + cred = (gssnetlogon_cred)*cred_handle; + + if (value->length != sizeof(cred->SessionKey)) { + *minor_status = ERANGE; + return GSS_S_FAILURE; + } + + memcpy(cred->SessionKey, value->value, value->length); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +/* + * value contains 16 bit little endian encoded seal algorithm + */ +static OM_uint32 +_netlogon_set_sign_algorithm(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + gssnetlogon_cred cred; + uint16_t alg; + const uint8_t *p; + + if (*cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + cred = (gssnetlogon_cred)*cred_handle; + + if (value->length != 2) { + *minor_status = ERANGE; + return GSS_S_FAILURE; + } + + p = (const uint8_t *)value->value; + alg = (p[0] << 0) | (p[1] << 8); + + if (alg != NL_SIGN_ALG_HMAC_MD5 && alg != NL_SIGN_ALG_SHA256) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + cred->SignatureAlgorithm = alg; + if (alg == NL_SIGN_ALG_SHA256) + cred->SealAlgorithm = NL_SEAL_ALG_AES128; + else + cred->SealAlgorithm = NL_SEAL_ALG_RC4; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_netlogon_set_cred_option + (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + if (value == GSS_C_NO_BUFFER) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_object, GSS_NETLOGON_SET_SESSION_KEY_X)) + return _netlogon_set_session_key(minor_status, cred_handle, value); + else if (gss_oid_equal(desired_object, GSS_NETLOGON_SET_SIGN_ALGORITHM_X)) + return _netlogon_set_sign_algorithm(minor_status, cred_handle, value); + + *minor_status = EINVAL; + return GSS_S_FAILURE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/add_cred.c b/third_party/heimdal/lib/gssapi/netlogon/add_cred.c new file mode 100644 index 0000000..0222303 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/add_cred.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_add_cred ( + OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 ret; + int equal; + const gssnetlogon_cred src = (const gssnetlogon_cred)input_cred_handle; + gssnetlogon_cred dst; + + if (desired_name != GSS_C_NO_NAME) { + if (input_cred_handle != GSS_C_NO_CREDENTIAL) { + ret = _netlogon_compare_name(minor_status, desired_name, + (gss_name_t)src->Name, &equal); + if (GSS_ERROR(ret)) + return ret; + + if (!equal) + return GSS_S_BAD_NAME; + } + } + + ret = _netlogon_acquire_cred(minor_status, + input_cred_handle ? (gss_name_t)src->Name : desired_name, + initiator_time_req, GSS_C_NO_OID_SET, cred_usage, + output_cred_handle, actual_mechs, initiator_time_rec); + if (GSS_ERROR(ret)) + return ret; + + dst = (gssnetlogon_cred)*output_cred_handle; + + if (src != NULL) { + dst->SignatureAlgorithm = src->SignatureAlgorithm; + dst->SealAlgorithm = src->SealAlgorithm; + + memcpy(dst->SessionKey, src->SessionKey, sizeof(src->SessionKey)); + } + + if (acceptor_time_rec != NULL) + *acceptor_time_rec = 0; + + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/canonicalize_name.c b/third_party/heimdal/lib/gssapi/netlogon/canonicalize_name.c new file mode 100644 index 0000000..1e8087a --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/canonicalize_name.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_canonicalize_name ( + OM_uint32 * minor_status, + gss_const_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ) +{ + return _netlogon_duplicate_name(minor_status, input_name, output_name); +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/compare_name.c b/third_party/heimdal/lib/gssapi/netlogon/compare_name.c new file mode 100644 index 0000000..986c3b0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/compare_name.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_compare_name + (OM_uint32 * minor_status, + gss_const_name_t name1, + gss_const_name_t name2, + int * name_equal + ) +{ + const gssnetlogon_name n1 = (const gssnetlogon_name)name1; + const gssnetlogon_name n2 = (const gssnetlogon_name)name2; + + *name_equal = 0; + + if (n1->NetbiosName.value != NULL && n2->NetbiosName.value != NULL) + *name_equal = (strcasecmp((char *)n1->NetbiosName.value, + (char *)n2->NetbiosName.value) == 0); + + if (n1->DnsName.value != NULL && n2->DnsName.value != NULL) + *name_equal = (strcasecmp((char *)n1->DnsName.value, + (char *)n2->DnsName.value) == 0); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/context_time.c b/third_party/heimdal/lib/gssapi/netlogon/context_time.c new file mode 100644 index 0000000..c7bf9eb --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/context_time.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_context_time + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + OM_uint32 * time_rec + ) +{ + if (time_rec != NULL) + *time_rec = GSS_C_INDEFINITE; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/crypto.c b/third_party/heimdal/lib/gssapi/netlogon/crypto.c new file mode 100644 index 0000000..0fc8f01 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/crypto.c @@ -0,0 +1,733 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +static uint8_t zeros[4]; + +static void +_netlogon_encode_sequence_number(uint64_t SequenceNumber, uint8_t *p, + int initiatorFlag) +{ + uint32_t LowPart, HighPart; + + LowPart = (SequenceNumber >> 0 ) & 0xFFFFFFFF; + HighPart = (SequenceNumber >> 32) & 0xFFFFFFFF; + + _gss_mg_encode_be_uint32(LowPart, &p[0]); + _gss_mg_encode_be_uint32(HighPart, &p[4]); + + if (initiatorFlag) + p[4] |= 0x80; +} + +static int +_netlogon_decode_sequence_number(void *ptr, uint64_t *n, + int initiatorFlag) +{ + uint8_t *p = ptr; + uint32_t LowPart, HighPart; + int gotInitiatorFlag; + + gotInitiatorFlag = (p[4] & 0x80) != 0; + if (gotInitiatorFlag != initiatorFlag) + return -1; + + p[4] &= 0x7F; /* clear initiator bit */ + + _gss_mg_decode_be_uint32(&p[0], &LowPart); + _gss_mg_decode_be_uint32(&p[4], &HighPart); + + *n = (LowPart << 0) | ((uint64_t)HighPart << 32); + + return 0; +} + +static inline size_t +_netlogon_checksum_length(NL_AUTH_SIGNATURE *sig) +{ +#if 0 + return (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) ? 32 : 8; +#else + /* Owing to a bug in Windows it always uses the old value */ + return 8; +#endif +} + +static inline size_t +_netlogon_signature_length(uint16_t alg, int conf_req_flag) +{ + return NL_AUTH_SIGNATURE_COMMON_LENGTH + + (alg == NL_SIGN_ALG_SHA256 ? 32 : 8) + + (conf_req_flag ? 8 : 0); +} + +static inline uint8_t * +_netlogon_confounder(NL_AUTH_SIGNATURE *sig) +{ + size_t cksumlen = _netlogon_checksum_length(sig); + + return &sig->Checksum[cksumlen]; +} + +static int +_netlogon_encode_NL_AUTH_SIGNATURE(NL_AUTH_SIGNATURE *sig, + uint8_t *p, size_t len) +{ + *p++ = (sig->SignatureAlgorithm >> 0) & 0xFF; + *p++ = (sig->SignatureAlgorithm >> 8) & 0xFF; + *p++ = (sig->SealAlgorithm >> 0) & 0xFF; + *p++ = (sig->SealAlgorithm >> 8) & 0xFF; + *p++ = (sig->Pad >> 0) & 0xFF; + *p++ = (sig->Pad >> 8) & 0xFF; + *p++ = (sig->Flags >> 0) & 0xFF; + *p++ = (sig->Flags >> 8) & 0xFF; + + if (len > NL_AUTH_SIGNATURE_HEADER_LENGTH) { + memcpy(p, sig->SequenceNumber, 8); + p += 8; + } + + if (len > NL_AUTH_SIGNATURE_COMMON_LENGTH) { + size_t cksumlen = _netlogon_checksum_length(sig); + + memcpy(p, sig->Checksum, cksumlen); + p += cksumlen; + + /* Confounder, if present, is immediately after checksum */ + if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { + memcpy(p, &sig->Checksum[cksumlen], 8); + } + } + + return 0; +} + +static int +_netlogon_decode_NL_AUTH_SIGNATURE(const uint8_t *ptr, + size_t len, + NL_AUTH_SIGNATURE *sig) +{ + const uint8_t *p = ptr; + size_t cksumlen; + + if (len < NL_AUTH_SIGNATURE_COMMON_LENGTH) + return KRB5_BAD_MSIZE; + + sig->SignatureAlgorithm = (p[0] << 0) | (p[1] << 8); + sig->SealAlgorithm = (p[2] << 0) | (p[3] << 8); + sig->Pad = (p[4] << 0) | (p[5] << 8); + sig->Flags = (p[6] << 0) | (p[7] << 8); + p += 8; + + memcpy(sig->SequenceNumber, p, 8); + p += 8; + + /* Validate signature algorithm is known and matches enctype */ + switch (sig->SignatureAlgorithm) { + case NL_SIGN_ALG_HMAC_MD5: + cksumlen = NL_AUTH_SIGNATURE_LENGTH; + break; + case NL_SIGN_ALG_SHA256: + cksumlen = NL_AUTH_SHA2_SIGNATURE_LENGTH; + break; + default: + return EINVAL; + break; + } + + if (sig->SealAlgorithm == NL_SEAL_ALG_NONE) + cksumlen -= 8; /* confounder is optional if no sealing */ + + if (len < cksumlen) + return KRB5_BAD_MSIZE; + + /* Copy variable length checksum */ + cksumlen = _netlogon_checksum_length(sig); + memcpy(sig->Checksum, p, cksumlen); + p += cksumlen; + + /* Copy confounder in past checksum */ + if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) + memcpy(&sig->Checksum[cksumlen], p, 8); + + return 0; +} + +static void +_netlogon_derive_rc4_hmac_key(uint8_t key[16], + uint8_t *salt, + size_t saltLength, + EVP_CIPHER_CTX *rc4Key, + int enc) +{ + uint8_t tmpData[MD5_DIGEST_LENGTH]; + uint8_t derivedKey[MD5_DIGEST_LENGTH]; + unsigned int len = MD5_DIGEST_LENGTH; + + HMAC(EVP_md5(), key, 16, zeros, sizeof(zeros), tmpData, &len); + HMAC(EVP_md5(), tmpData, MD5_DIGEST_LENGTH, + salt, saltLength, derivedKey, &len); + + assert(len == MD5_DIGEST_LENGTH); + + EVP_CipherInit_ex(rc4Key, EVP_rc4(), NULL, derivedKey, NULL, enc); + + memset(derivedKey, 0, sizeof(derivedKey)); +} + +static void +_netlogon_derive_rc4_seal_key(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + EVP_CIPHER_CTX *sealkey, + int enc) +{ + uint8_t xorKey[16]; + int i; + + for (i = 0; i < sizeof(xorKey); i++) { + xorKey[i] = ctx->SessionKey[i] ^ 0xF0; + } + + _netlogon_derive_rc4_hmac_key(xorKey, + sig->SequenceNumber, sizeof(sig->SequenceNumber), sealkey, enc); + + memset(xorKey, 0, sizeof(xorKey)); +} + +static void +_netlogon_derive_rc4_seq_key(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + EVP_CIPHER_CTX *seqkey, + int enc) +{ + _netlogon_derive_rc4_hmac_key(ctx->SessionKey, + sig->Checksum, sizeof(sig->Checksum), seqkey, enc); +} + +static void +_netlogon_derive_aes_seal_key(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + EVP_CIPHER_CTX *sealkey, + int enc) +{ + uint8_t encryptionKey[16]; + uint8_t ivec[16]; + int i; + + for (i = 0; i < sizeof(encryptionKey); i++) { + encryptionKey[i] = ctx->SessionKey[i] ^ 0xF0; + } + + memcpy(&ivec[0], sig->SequenceNumber, 8); + memcpy(&ivec[8], sig->SequenceNumber, 8); + + EVP_CipherInit_ex(sealkey, EVP_aes_128_cfb8(), + NULL, encryptionKey, ivec, enc); + + memset(encryptionKey, 0, sizeof(encryptionKey)); +} + +static void +_netlogon_derive_aes_seq_key(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + EVP_CIPHER_CTX *seqkey, + int enc) +{ + uint8_t ivec[16]; + + memcpy(&ivec[0], sig->Checksum, 8); + memcpy(&ivec[8], sig->Checksum, 8); + + EVP_CipherInit_ex(seqkey, EVP_aes_128_cfb8(), + NULL, ctx->SessionKey, ivec, enc); +} + +static void +_netlogon_seal(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + gss_iov_buffer_desc *iov, + int iov_count, + int enc) +{ + EVP_CIPHER_CTX sealkey; + int i; + uint8_t *confounder = _netlogon_confounder(sig); + + EVP_CIPHER_CTX_init(&sealkey); + + if (sig->SealAlgorithm == NL_SEAL_ALG_AES128) + _netlogon_derive_aes_seal_key(ctx, sig, &sealkey, enc); + else + _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc); + + EVP_Cipher(&sealkey, confounder, confounder, 8); + + /* + * For RC4, Windows resets the cipherstate after encrypting + * the confounder, thus defeating the purpose of the confounder + */ + if (sig->SealAlgorithm == NL_SEAL_ALG_RC4) { + EVP_CipherFinal_ex(&sealkey, NULL, &i); + _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc); + } + + for (i = 0; i < iov_count; i++) { + gss_iov_buffer_t iovp = &iov[i]; + + switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + EVP_Cipher(&sealkey, iovp->buffer.value, iovp->buffer.value, + iovp->buffer.length); + break; + default: + break; + } + } + + EVP_CipherFinal_ex(&sealkey, NULL, &i); + EVP_CIPHER_CTX_cleanup(&sealkey); +} + +static void +_netlogon_seq(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + int enc) +{ + EVP_CIPHER_CTX seqkey; + + EVP_CIPHER_CTX_init(&seqkey); + + if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) + _netlogon_derive_aes_seq_key(ctx, sig, &seqkey, enc); + else + _netlogon_derive_rc4_seq_key(ctx, sig, &seqkey, enc); + + EVP_Cipher(&seqkey, sig->SequenceNumber, sig->SequenceNumber, 8); + + EVP_CIPHER_CTX_cleanup(&seqkey); +} + +static void +_netlogon_digest_md5(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + gss_iov_buffer_desc *iov, + int iov_count, + uint8_t *md) +{ + EVP_MD_CTX *md5; + uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH]; + uint8_t digest[MD5_DIGEST_LENGTH]; + unsigned int md_len = MD5_DIGEST_LENGTH; + int i; + + _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header)); + + md5 = EVP_MD_CTX_create(); + EVP_DigestInit_ex(md5, EVP_md5(), NULL); + EVP_DigestUpdate(md5, zeros, sizeof(zeros)); + EVP_DigestUpdate(md5, header, sizeof(header)); + + if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { + EVP_DigestUpdate(md5, sig->Confounder, sizeof(sig->Confounder)); + } + + for (i = 0; i < iov_count; i++) { + gss_iov_buffer_t iovp = &iov[i]; + + switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + EVP_DigestUpdate(md5, iovp->buffer.value, iovp->buffer.length); + break; + default: + break; + } + } + + EVP_DigestFinal_ex(md5, digest, NULL); + EVP_MD_CTX_destroy(md5); + + HMAC(EVP_md5(), ctx->SessionKey, sizeof(ctx->SessionKey), + digest, sizeof(digest), digest, &md_len); + memcpy(md, digest, 8); +} + +static void +_netlogon_digest_sha256(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + gss_iov_buffer_desc *iov, + int iov_count, + uint8_t *md) +{ + HMAC_CTX hmac; + uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH]; + uint8_t digest[SHA256_DIGEST_LENGTH]; + unsigned int md_len = SHA256_DIGEST_LENGTH; + int i; + + /* Encode first 8 bytes of signature into header */ + _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header)); + + HMAC_CTX_init(&hmac); + HMAC_Init_ex(&hmac, ctx->SessionKey, sizeof(ctx->SessionKey), + EVP_sha256(), NULL); + HMAC_Update(&hmac, header, sizeof(header)); + + if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { + /* + * If the checksum length bug is ever fixed, then be sure to + * update this code to point to &sig->Checksum[32] as that is + * where the confounder is supposed to be. + */ + HMAC_Update(&hmac, sig->Confounder, 8); + } + + for (i = 0; i < iov_count; i++) { + gss_iov_buffer_t iovp = &iov[i]; + + switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + HMAC_Update(&hmac, iovp->buffer.value, iovp->buffer.length); + break; + default: + break; + } + } + + HMAC_Final(&hmac, digest, &md_len); + HMAC_CTX_cleanup(&hmac); + memcpy(md, digest, 8); +} + +static void +_netlogon_digest(gssnetlogon_ctx ctx, + NL_AUTH_SIGNATURE *sig, + gss_iov_buffer_desc *iov, + int iov_count, + uint8_t *md) +{ + if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) + _netlogon_digest_sha256(ctx, sig, iov, iov_count, md); + else + _netlogon_digest_md5(ctx, sig, iov, iov_count, md); +} + +OM_uint32 +_netlogon_wrap_iov(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + gss_iov_buffer_t header; + NL_AUTH_SIGNATURE_U sigbuf = { { 0 } }; + NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf); + gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; + size_t size; + uint8_t *seqdata; + + if (ctx->State != NL_AUTH_ESTABLISHED) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + size = _netlogon_signature_length(ctx->SignatureAlgorithm, conf_req_flag); + + if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + ret = _gss_mg_allocate_buffer(minor_status, header, size); + if (GSS_ERROR(ret)) + return ret; + } else if (header->buffer.length < size) { + *minor_status = KRB5_BAD_MSIZE; + return GSS_S_FAILURE; + } else { + header->buffer.length = size; + } + + memset(header->buffer.value, 0, header->buffer.length); + + sig->SignatureAlgorithm = ctx->SignatureAlgorithm; + sig->SealAlgorithm = conf_req_flag ? ctx->SealAlgorithm : NL_SEAL_ALG_NONE; + + if (conf_req_flag) + krb5_generate_random_block(_netlogon_confounder(sig), 8); + + sig->Pad = 0xFFFF; /* [MS-NRPC] 3.3.4.2.1.3 */ + sig->Flags = 0; /* [MS-NRPC] 3.3.4.2.1.4 */ + HEIMDAL_MUTEX_lock(&ctx->Mutex); + _netlogon_encode_sequence_number(ctx->SequenceNumber, sig->SequenceNumber, + ctx->LocallyInitiated); + ctx->SequenceNumber++; + HEIMDAL_MUTEX_unlock(&ctx->Mutex); + + /* [MS-NRPC] 3.3.4.2.1.7: sign header, optional confounder and data */ + _netlogon_digest(ctx, sig, iov, iov_count, sig->Checksum); + + /* [MS-NRPC] 3.3.4.2.1.8: optionally encrypt confounder and data */ + if (conf_req_flag) + _netlogon_seal(ctx, sig, iov, iov_count, 1); + + /* [MS-NRPC] 3.3.4.2.1.9: encrypt sequence number */ + _netlogon_seq(ctx, sig, 1); + + _netlogon_encode_NL_AUTH_SIGNATURE(sig, header->buffer.value, + header->buffer.length); + + if (conf_state != NULL) + *conf_state = conf_req_flag; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_netlogon_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + gss_iov_buffer_t header; + NL_AUTH_SIGNATURE_U sigbuf; + NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf); + gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; + uint8_t checksum[SHA256_DIGEST_LENGTH]; + uint64_t SequenceNumber; + + if (ctx->State != NL_AUTH_ESTABLISHED) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = _netlogon_decode_NL_AUTH_SIGNATURE(header->buffer.value, + header->buffer.length, + sig); + if (ret != 0) { + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* [MS-NRPC] 3.3.4.2.2.1: verify signature algorithm selection */ + if (sig->SignatureAlgorithm != ctx->SignatureAlgorithm) + return GSS_S_BAD_SIG; + + /* [MS-NRPC] 3.3.4.2.2.2: verify encryption algorithm selection */ + if (sig->SealAlgorithm != NL_SEAL_ALG_NONE && + sig->SealAlgorithm != ctx->SealAlgorithm) + return GSS_S_DEFECTIVE_TOKEN; + + /* [MS-NRPC] 3.3.4.2.2.3: verify Pad bytes */ + if (sig->Pad != 0xFFFF) + return GSS_S_DEFECTIVE_TOKEN; + + /* [MS-NRPC] 3.3.4.2.2.5: decrypt sequence number */ + _netlogon_seq(ctx, sig, 0); + + /* [MS-NRPC] 3.3.4.2.2.6: decode sequence number */ + if (_netlogon_decode_sequence_number(sig->SequenceNumber, &SequenceNumber, + !ctx->LocallyInitiated) != 0) + return GSS_S_UNSEQ_TOKEN; + + /* [MS-NRPC] 3.3.4.2.2.9: decrypt confounder and data */ + if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) + _netlogon_seal(ctx, sig, iov, iov_count, 0); + + /* [MS-NRPC] 3.3.4.2.2.10: verify signature */ + _netlogon_digest(ctx, sig, iov, iov_count, checksum); + if (memcmp(sig->Checksum, checksum, _netlogon_checksum_length(sig)) != 0) + return GSS_S_BAD_SIG; + + HEIMDAL_MUTEX_lock(&ctx->Mutex); + if (SequenceNumber != ctx->SequenceNumber) { + /* [MS-NRPC] 3.3.4.2.2.7: check sequence number */ + ret = GSS_S_UNSEQ_TOKEN; + } else { + /* [MS-NRPC] 3.3.4.2.2.8: increment sequence number */ + ctx->SequenceNumber++; + ret = GSS_S_COMPLETE; + } + HEIMDAL_MUTEX_unlock(&ctx->Mutex); + + if (conf_state != NULL) + *conf_state = (sig->SealAlgorithm != NL_SEAL_ALG_NONE); + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + *minor_status = 0; + return ret; +} + +OM_uint32 +_netlogon_wrap_iov_length(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + gss_iov_buffer_t iovp; + gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; + size_t len; + + iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (iovp == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + len = NL_AUTH_SIGNATURE_COMMON_LENGTH; + if (ctx->SignatureAlgorithm == NL_SIGN_ALG_SHA256) + len += 32; /* SHA2 checksum size */ + else + len += 8; /* HMAC checksum size */ + if (conf_req_flag) + len += 8; /* counfounder */ + + iovp->buffer.length = len; + + iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (iovp != NULL) + iovp->buffer.length = 0; + + iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + if (iovp != NULL) + iovp->buffer.length = 0; + + if (conf_state != NULL) + *conf_state = conf_req_flag; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _netlogon_get_mic + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + gss_iov_buffer_desc iov[2]; + OM_uint32 ret; + + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[0].buffer = *message_buffer; + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[1].buffer.length = 0; + iov[1].buffer.value = NULL; + + ret = _netlogon_wrap_iov(minor_status, context_handle, 0, + qop_req, NULL, iov, 2); + if (ret == GSS_S_COMPLETE) + *message_token = iov[1].buffer; + + return ret; +} + +OM_uint32 +_netlogon_verify_mic + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + gss_iov_buffer_desc iov[2]; + + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[0].buffer = *message_buffer; + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[1].buffer = *token_buffer; + + return _netlogon_unwrap_iov(minor_status, context_handle, + NULL, qop_state, iov, 2); +} + +OM_uint32 +_netlogon_wrap_size_limit ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size + ) +{ + gss_iov_buffer_desc iov[1]; + OM_uint32 ret; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[0].buffer.length = 0; + + ret = _netlogon_wrap_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, NULL, + iov, sizeof(iov)/sizeof(iov[0])); + if (GSS_ERROR(ret)) + return ret; + + if (req_output_size < iov[0].buffer.length) + *max_input_size = 0; + else + *max_input_size = req_output_size - iov[0].buffer.length; + + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/delete_sec_context.c b/third_party/heimdal/lib/gssapi/netlogon/delete_sec_context.c new file mode 100644 index 0000000..8710416 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/delete_sec_context.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 +_netlogon_delete_sec_context(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token) +{ + if (context_handle != NULL && *context_handle != GSS_C_NO_CONTEXT) { + gssnetlogon_ctx ctx = (gssnetlogon_ctx)*context_handle; + + *context_handle = GSS_C_NO_CONTEXT; + + _netlogon_release_name(minor_status, (gss_name_t *)&ctx->SourceName); + _netlogon_release_name(minor_status, (gss_name_t *)&ctx->TargetName); + HEIMDAL_MUTEX_destroy(&ctx->Mutex); + memset(ctx, 0, sizeof(*ctx)); + free(ctx); + } + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/display_name.c b/third_party/heimdal/lib/gssapi/netlogon/display_name.c new file mode 100644 index 0000000..7b0e223 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/display_name.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_display_name + (OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + const gssnetlogon_name name = (const gssnetlogon_name)input_name; + gss_buffer_t namebuf; + + if (output_name_type != NULL) + *output_name_type = GSS_C_NO_OID; + + if (output_name_buffer != NULL) { + namebuf = name->DnsName.length ? &name->DnsName : &name->NetbiosName; + + output_name_buffer->value = malloc(namebuf->length + 1); + if (output_name_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(output_name_buffer->value, namebuf->value, namebuf->length); + ((char *)output_name_buffer->value)[namebuf->length] = '\0'; + output_name_buffer->length = namebuf->length; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/display_status.c b/third_party/heimdal/lib/gssapi/netlogon/display_status.c new file mode 100644 index 0000000..68946e5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/display_status.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_display_status + (OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + if (minor_status) + *minor_status = 0; + if (status_string) { + status_string->length = 0; + status_string->value = NULL; + } + if (message_context) + *message_context = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/duplicate_cred.c b/third_party/heimdal/lib/gssapi/netlogon/duplicate_cred.c new file mode 100644 index 0000000..0271fb2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/duplicate_cred.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 +_netlogon_duplicate_cred(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_id_t *output_cred_handle) +{ + gssnetlogon_const_cred src = (gssnetlogon_const_cred)input_cred_handle; + gssnetlogon_cred dst; + + dst = calloc(1, sizeof(*dst)); + if (dst == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *dst = *src; + return _netlogon_duplicate_name(minor_status, (gss_name_t)&src->Name, &dst->Name) +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/duplicate_name.c b/third_party/heimdal/lib/gssapi/netlogon/duplicate_name.c new file mode 100644 index 0000000..1365e76 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/duplicate_name.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_duplicate_name ( + OM_uint32 * minor_status, + gss_const_name_t src_name, + gss_name_t * dest_name + ) +{ + const gssnetlogon_name src = (const gssnetlogon_name)src_name; + gssnetlogon_name dst = NULL; + + dst = calloc(1, sizeof(*dst)); + if (dst == NULL) + goto fail; + + dst->NetbiosName.value = malloc(src->NetbiosName.length + 1); + if (dst->NetbiosName.value == NULL) + goto fail; + memcpy(dst->NetbiosName.value, src->NetbiosName.value, + src->NetbiosName.length); + dst->NetbiosName.length = src->NetbiosName.length; + ((char *)dst->NetbiosName.value)[dst->NetbiosName.length] = '\0'; + + if (src->DnsName.length != 0) { + dst->DnsName.value = malloc(src->DnsName.length + 1); + if (dst->DnsName.value == NULL) + goto fail; + memcpy(dst->DnsName.value, src->DnsName.value, src->DnsName.length); + dst->DnsName.length = src->DnsName.length; + ((char *)dst->DnsName.value)[dst->DnsName.length] = '\0'; + } + + *minor_status = 0; + *dest_name = (gss_name_t)dst; + return GSS_S_COMPLETE; + +fail: + _netlogon_release_name(minor_status, (gss_name_t *)&dst); + *minor_status = ENOMEM; + return GSS_S_FAILURE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/export_name.c b/third_party/heimdal/lib/gssapi/netlogon/export_name.c new file mode 100644 index 0000000..9984f8b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/export_name.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_export_name + (OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_buffer_t exported_name + ) +{ + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/export_sec_context.c b/third_party/heimdal/lib/gssapi/netlogon/export_sec_context.c new file mode 100644 index 0000000..7e410aa --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/export_sec_context.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 +_netlogon_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ) +{ + if (interprocess_token != GSS_C_NO_BUFFER) { + interprocess_token->length = 0; + interprocess_token->value = NULL; + } + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/external.c b/third_party/heimdal/lib/gssapi/netlogon/external.c new file mode 100644 index 0000000..14f471e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/external.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2010-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +static gssapi_mech_interface_desc netlogon_mech = { + GMI_VERSION, + "netlogon", + {6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x02") }, + 0, + _netlogon_acquire_cred, + _netlogon_release_cred, + _netlogon_init_sec_context, + _netlogon_accept_sec_context, + _netlogon_process_context_token, + _netlogon_delete_sec_context, + _netlogon_context_time, + _netlogon_get_mic, + _netlogon_verify_mic, + NULL, + NULL, + _netlogon_display_status, + NULL, + _netlogon_compare_name, + _netlogon_display_name, + _netlogon_import_name, + _netlogon_export_name, + _netlogon_release_name, + _netlogon_inquire_cred, + _netlogon_inquire_context, + _netlogon_wrap_size_limit, + _netlogon_add_cred, + _netlogon_inquire_cred_by_mech, + _netlogon_export_sec_context, + _netlogon_import_sec_context, + _netlogon_inquire_names_for_mech, + _netlogon_inquire_mechs_for_name, + _netlogon_canonicalize_name, + _netlogon_duplicate_name, + NULL, + NULL, + NULL, + _netlogon_set_cred_option, + NULL, + _netlogon_wrap_iov, + _netlogon_unwrap_iov, + _netlogon_wrap_iov_length, + NULL, /* gm_store_cred */ + NULL, /* gm_export_cred */ + NULL, /* gm_import_cred */ + NULL, /* gm_acquire_cred_from */ + NULL, /* gm_acquire_cred_impersonate_name */ + NULL, /* gm_iter_creds */ + NULL, /* gm_destroy_cred */ + NULL, /* gm_cred_hold */ + NULL, /* gm_cred_unhold */ + NULL, /* gm_cred_label_get */ + NULL, /* gm_cred_label_set */ + NULL, /* gm_mo */ + 0, /* gm_mo_num */ + NULL, /* gm_localname */ + NULL, /* gm_authorize_localname */ + NULL, /* gm_display_name_ext */ + NULL, /* gm_inquire_name */ + NULL, /* gm_get_name_attribute */ + NULL, /* gm_set_name_attribute */ + NULL, /* gm_delete_name_attribute */ + NULL, /* gm_export_name_composite */ + NULL, /* gm_duplicate_cred */ + NULL, /* gm_add_cred_from */ + NULL, /* gm_store_cred_into */ + NULL /* gm_compat */ +}; + +gssapi_mech_interface +__gss_netlogon_initialize(void) +{ + return &netlogon_mech; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/import_name.c b/third_party/heimdal/lib/gssapi/netlogon/import_name.c new file mode 100644 index 0000000..aa9191f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/import_name.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" +#include <ctype.h> + +OM_uint32 _netlogon_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + gssnetlogon_name name; + const char *netbiosName; + const char *dnsName = NULL; + size_t len, i; + + if (!gss_oid_equal(input_name_type, GSS_NETLOGON_NT_NETBIOS_DNS_NAME)) { + return GSS_S_BAD_NAME; + } + + /* encoding is NetBIOS name \0 DNS name \0 */ + + netbiosName = input_name_buffer->value; + len = strlen(netbiosName); + if (len < input_name_buffer->length) + dnsName = netbiosName + len + 1; + + name = (gssnetlogon_name)calloc(1, sizeof(*name)); + if (name == NULL) + goto cleanup; + + name->NetbiosName.value = malloc(len + 1); + if (name->NetbiosName.value == NULL) + goto cleanup; + memcpy(name->NetbiosName.value, netbiosName, len + 1); + name->NetbiosName.length = len; + + /* normalise name to uppercase XXX UTF-8 OK? */ + for (i = 0; i < len; i++) { + ((char *)name->NetbiosName.value)[i] = + toupper(((char *)name->NetbiosName.value)[i]); + } + + if (dnsName != NULL && dnsName[0] != '\0') { + name->DnsName.value = strdup(dnsName); + if (name->DnsName.value == NULL) + goto cleanup; + name->DnsName.length = strlen(dnsName); + } + + *output_name = (gss_name_t)name; + *minor_status = 0; + return GSS_S_COMPLETE; + +cleanup: + _netlogon_release_name(minor_status, (gss_name_t *)&name); + *minor_status = ENOMEM; + return GSS_S_FAILURE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/import_sec_context.c b/third_party/heimdal/lib/gssapi/netlogon/import_sec_context.c new file mode 100644 index 0000000..0415b39 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/import_sec_context.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 +_netlogon_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t * context_handle + ) +{ + *minor_status = 0; + if (context_handle != NULL) + *context_handle = GSS_C_NO_CONTEXT; + + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/indicate_mechs.c b/third_party/heimdal/lib/gssapi/netlogon/indicate_mechs.c new file mode 100644 index 0000000..9192e42 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/indicate_mechs.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_indicate_mechs +(OM_uint32 * minor_status, + gss_OID_set * mech_set + ) +{ + *minor_status = 0; + if (mech_set != NULL) + *mech_set = GSS_C_NO_OID_SET; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/init_sec_context.c b/third_party/heimdal/lib/gssapi/netlogon/init_sec_context.c new file mode 100644 index 0000000..906f457 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/init_sec_context.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" +#include <nameser.h> + +static OM_uint32 +_netlogon_encode_dns_string(OM_uint32 *minor_status, + const gss_buffer_t str, + gss_buffer_t buffer) +{ + int ret; + + memset(buffer->value, 0, buffer->length); + + ret = ns_name_compress((const char *)str->value, + (uint8_t *)buffer->value, buffer->length, + NULL, NULL); + if (ret < 0) { + *minor_status = errno; + return GSS_S_FAILURE; + } + + buffer->length = ret; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +_netlogon_make_initial_auth_message(OM_uint32 *minor_status, + gssnetlogon_ctx ctx, + gss_buffer_t output_token) +{ + uint32_t flags = 0; +#define MAX_NL_NAMES 5 + gss_buffer_desc names[MAX_NL_NAMES]; + uint8_t comp_names[3][MAXHOSTNAMELEN * 2]; + size_t n = 0, i = 0, len; + OM_uint32 ret; + uint8_t *p; + + if (ctx->TargetName->NetbiosName.length) { + flags |= NL_FLAG_NETBIOS_DOMAIN_NAME; + names[n] = ctx->TargetName->NetbiosName; /* OEM encoding */ + names[n].length++; + n++; + } + if (ctx->SourceName->NetbiosName.length) { + flags |= NL_FLAG_NETBIOS_COMPUTER_NAME; + names[n] = ctx->SourceName->NetbiosName; /* OEM encoding */ + names[n].length++; + n++; + } + if (ctx->TargetName->DnsName.length) { + flags |= NL_FLAG_DNS_DOMAIN_NAME; + names[n].value = comp_names[i++]; + names[n].length = MAXHOSTNAMELEN * 2; + ret = _netlogon_encode_dns_string(minor_status, + &ctx->TargetName->DnsName, + &names[n]); + if (GSS_ERROR(ret)) + return ret; + n++; + } + if (ctx->SourceName->DnsName.length) { + flags |= NL_FLAG_DNS_HOST_NAME; + names[n].value = comp_names[i++]; + names[n].length = MAXHOSTNAMELEN * 2; + ret = _netlogon_encode_dns_string(minor_status, + &ctx->SourceName->DnsName, + &names[n]); + if (GSS_ERROR(ret)) + return ret; + n++; + } + if (ctx->SourceName->NetbiosName.length) { + flags |= NL_FLAG_UTF8_COMPUTER_NAME; + names[n].value = comp_names[i++]; + names[n].length = MAXHOSTNAMELEN * 2; + ret = _netlogon_encode_dns_string(minor_status, + &ctx->SourceName->NetbiosName, + &names[n]); + if (GSS_ERROR(ret)) + return ret; + n++; + } + + for (i = 0, len = NL_AUTH_MESSAGE_LENGTH; i < n; i++) { + len += names[i].length; + } + + output_token->value = malloc(len); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = (uint8_t *)output_token->value; + _gss_mg_encode_le_uint32(NL_NEGOTIATE_REQUEST_MESSAGE, p); + _gss_mg_encode_le_uint32(flags, p + 4); + p += 8; + + for (i = 0; i < n; i++) { + assert(names[i].length != 0); + assert(((char *)names[i].value)[names[i].length - 1] == '\0'); + memcpy(p, names[i].value, names[i].length); + p += names[i].length; + } + + output_token->length = len; + assert(p == (uint8_t *)output_token->value + len); + + *minor_status = 0; + return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +_netlogon_read_initial_auth_message(OM_uint32 *minor_status, + gssnetlogon_ctx ctx, + const gss_buffer_t input_token) +{ + NL_AUTH_MESSAGE msg; + const uint8_t *p = (const uint8_t *)input_token->value; + + if (ctx->State != NL_AUTH_NEGOTIATE) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (input_token->length < NL_AUTH_MESSAGE_LENGTH) + return GSS_S_DEFECTIVE_TOKEN; + + _gss_mg_decode_le_uint32(&p[0], &msg.MessageType); + _gss_mg_decode_le_uint32(&p[4], &msg.Flags); + + if (msg.MessageType != NL_NEGOTIATE_RESPONSE_MESSAGE || + msg.Flags != 0) + return GSS_S_DEFECTIVE_TOKEN; + + ctx->State = NL_AUTH_ESTABLISHED; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +_netlogon_alloc_context(OM_uint32 *minor_status, + gssnetlogon_ctx *pContext) +{ + gssnetlogon_ctx ctx; + + ctx = (gssnetlogon_ctx)calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ctx->State = NL_AUTH_NEGOTIATE; + ctx->LocallyInitiated = 1; + ctx->MessageBlockSize = 1; + + HEIMDAL_MUTEX_init(&ctx->Mutex); + + *pContext = ctx; + + return GSS_S_COMPLETE; +} + +OM_uint32 +_netlogon_init_sec_context(OM_uint32 * minor_status, + gss_const_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + gss_const_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + const gssnetlogon_cred cred = (const gssnetlogon_cred)initiator_cred_handle; + gssnetlogon_ctx ctx = (gssnetlogon_ctx)*context_handle; + const gssnetlogon_name target = (const gssnetlogon_name)target_name; + OM_uint32 ret; + + *minor_status = 0; + + output_token->value = NULL; + output_token->length = 0; + + /* Validate arguments */ + if (cred == NULL) + return GSS_S_NO_CRED; + else if (target == NULL) + return GSS_S_BAD_NAME; + + if (ctx == NULL) { + if (input_token->length != 0) + return GSS_S_DEFECTIVE_TOKEN; + + ret = _netlogon_alloc_context(minor_status, &ctx); + if (GSS_ERROR(ret)) + goto cleanup; + + HEIMDAL_MUTEX_lock(&ctx->Mutex); + *context_handle = (gss_ctx_id_t)ctx; + + ctx->GssFlags = req_flags & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | + GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | + GSS_C_INTEG_FLAG | GSS_C_DCE_STYLE); + ctx->SignatureAlgorithm = cred->SignatureAlgorithm; + ctx->SealAlgorithm = cred->SealAlgorithm; + + ret = _netlogon_duplicate_name(minor_status, (gss_name_t)cred->Name, + (gss_name_t *)&ctx->SourceName); + if (GSS_ERROR(ret)) + goto cleanup; + + ret = _netlogon_duplicate_name(minor_status, (gss_name_t)target, + (gss_name_t *)&ctx->TargetName); + if (GSS_ERROR(ret)) + goto cleanup; + + memcpy(ctx->SessionKey, cred->SessionKey, sizeof(cred->SessionKey)); + + ret = _netlogon_make_initial_auth_message(minor_status, ctx, + output_token); + if (GSS_ERROR(ret)) + goto cleanup; + } else { + HEIMDAL_MUTEX_lock(&ctx->Mutex); + ret = _netlogon_read_initial_auth_message(minor_status, ctx, + input_token); + } + + if (ret_flags != NULL) + *ret_flags = ctx->GssFlags; + if (time_rec != NULL) + *time_rec = GSS_C_INDEFINITE; + if (actual_mech_type != NULL) + *actual_mech_type = GSS_NETLOGON_MECHANISM; + +cleanup: + HEIMDAL_MUTEX_unlock(&ctx->Mutex); + + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + OM_uint32 tmp; + _netlogon_delete_sec_context(&tmp, context_handle, NULL); + } + + return ret; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/inquire_context.c b/third_party/heimdal/lib/gssapi/netlogon/inquire_context.c new file mode 100644 index 0000000..24995c2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/inquire_context.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_inquire_context ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + const gssnetlogon_ctx ctx = (const gssnetlogon_ctx)context_handle; + OM_uint32 ret; + + if (src_name != NULL) { + ret = _netlogon_duplicate_name(minor_status, (gss_name_t)ctx->SourceName, + (gss_name_t *)src_name); + if (GSS_ERROR(ret)) + return ret; + } + if (targ_name != NULL) { + ret = _netlogon_duplicate_name(minor_status, (gss_name_t)ctx->TargetName, + (gss_name_t *)targ_name); + if (GSS_ERROR(ret)) + return ret; + } + if (mech_type != NULL) + *mech_type = GSS_NETLOGON_MECHANISM; + if (ctx_flags != NULL) + *ctx_flags = ctx->GssFlags; + if (locally_initiated != NULL) + *locally_initiated = ctx->LocallyInitiated; + if (open_context != NULL) + *open_context = (ctx->State == NL_AUTH_ESTABLISHED); + + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/inquire_cred.c b/third_party/heimdal/lib/gssapi/netlogon/inquire_cred.c new file mode 100644 index 0000000..6c7ca34 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/inquire_cred.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_inquire_cred + (OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + gss_name_t * name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ) +{ + OM_uint32 ret; + const gssnetlogon_cred cred = (const gssnetlogon_cred)cred_handle; + + *minor_status = 0; + + if (cred == NULL) + return GSS_S_NO_CRED; + + if (name != NULL) { + ret = _netlogon_duplicate_name(minor_status, + (gss_const_name_t)cred->Name, name); + if (GSS_ERROR(ret)) + return ret; + } + if (lifetime != NULL) + *lifetime = GSS_C_INDEFINITE; + if (cred_usage != NULL) + *cred_usage = GSS_C_INITIATE; + if (mechanisms != NULL) + *mechanisms = GSS_C_NO_OID_SET; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/inquire_cred_by_mech.c b/third_party/heimdal/lib/gssapi/netlogon/inquire_cred_by_mech.c new file mode 100644 index 0000000..f36310f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/inquire_cred_by_mech.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_inquire_cred_by_mech ( + OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ) +{ + OM_uint32 ret; + const gssnetlogon_cred cred = (const gssnetlogon_cred)cred_handle; + + if (name != NULL) { + ret = _netlogon_duplicate_name(minor_status, + (gss_const_name_t)cred->Name, name); + if (GSS_ERROR(ret)) + return ret; + } + if (initiator_lifetime != NULL) + *initiator_lifetime = GSS_C_INDEFINITE; + if (acceptor_lifetime != NULL) + *acceptor_lifetime = GSS_C_INDEFINITE; + if (cred_usage != NULL) + *cred_usage = GSS_C_INITIATE; + *minor_status = 0; + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/inquire_mechs_for_name.c b/third_party/heimdal/lib/gssapi/netlogon/inquire_mechs_for_name.c new file mode 100644 index 0000000..dbf385c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/inquire_mechs_for_name.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_inquire_mechs_for_name ( + OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_OID_set * mech_types + ) +{ + if (mech_types != NULL) + *mech_types = GSS_C_NO_OID_SET; + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/inquire_names_for_mech.c b/third_party/heimdal/lib/gssapi/netlogon/inquire_names_for_mech.c new file mode 100644 index 0000000..9802e53 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/inquire_names_for_mech.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + OM_uint32 ret, tmp; + + ret = gss_create_empty_oid_set(minor_status, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_add_oid_set_member(minor_status, GSS_NETLOGON_NT_NETBIOS_DNS_NAME, name_types); + if (ret != GSS_S_COMPLETE) { + gss_release_oid_set(&tmp, name_types); + return ret; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/iter_cred.c b/third_party/heimdal/lib/gssapi/netlogon/iter_cred.c new file mode 100644 index 0000000..93a8d59 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/iter_cred.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" +#include <gssapi_spi.h> + +void +_netlogon_iter_creds_f(OM_uint32 flags, + void *userctx , + void (*cred_iter)(void *, gss_OID, gss_cred_id_t)) +{ +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/netlogon.h b/third_party/heimdal/lib/gssapi/netlogon/netlogon.h new file mode 100644 index 0000000..68573e2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/netlogon.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2010-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NETLOGON_NETLOGON_H +#define NETLOGON_NETLOGON_H + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <errno.h> + +#include <gssapi.h> +#include <gssapi_mech.h> +#include <gssapi_netlogon.h> + +#include <krb5.h> + +#include <roken.h> +#include <heim_threads.h> + +#define HC_DEPRECATED_CRYPTO +#include "crypto-headers.h" + +/* + * + */ + +typedef struct { +#define NL_NEGOTIATE_REQUEST_MESSAGE 0x00000000 +#define NL_NEGOTIATE_RESPONSE_MESSAGE 0x00000001 + uint32_t MessageType; +#define NL_FLAG_NETBIOS_DOMAIN_NAME 0x00000001 +#define NL_FLAG_NETBIOS_COMPUTER_NAME 0x00000002 +#define NL_FLAG_DNS_DOMAIN_NAME 0x00000004 +#define NL_FLAG_DNS_HOST_NAME 0x00000008 /* not used */ +#define NL_FLAG_UTF8_COMPUTER_NAME 0x00000010 + uint32_t Flags; + char *Buffer[0]; +} NL_AUTH_MESSAGE; + +#define NL_AUTH_MESSAGE_LENGTH 8 + +/* SignatureAlgorithm */ +#define NL_SIGN_ALG_HMAC_MD5 0x0077 +#define NL_SIGN_ALG_SHA256 0x0013 + +/* SealAlgorithm */ +#define NL_SEAL_ALG_RC4 0x007A +#define NL_SEAL_ALG_AES128 0x001A +#define NL_SEAL_ALG_NONE 0xFFFF + +typedef struct { + uint16_t SignatureAlgorithm; + uint16_t SealAlgorithm; + uint16_t Pad; + uint16_t Flags; + uint8_t SequenceNumber[8]; + uint8_t Checksum[8]; + uint8_t Confounder[8]; +} NL_AUTH_SIGNATURE; + +#define NL_AUTH_SIGNATURE_HEADER_LENGTH 8 +#define NL_AUTH_SIGNATURE_COMMON_LENGTH 16 +#define NL_AUTH_SIGNATURE_LENGTH 32 + +typedef struct { + uint16_t SignatureAlgorithm; + uint16_t SealAlgorithm; + uint16_t Pad; + uint16_t Flags; + uint8_t SequenceNumber[8]; + uint8_t Checksum[32]; + uint8_t Confounder[8]; +} NL_AUTH_SHA2_SIGNATURE; + +#define NL_AUTH_SHA2_SIGNATURE_LENGTH 56 + +typedef union { + NL_AUTH_SIGNATURE Signature; + NL_AUTH_SHA2_SIGNATURE SHA2Signature; +} NL_AUTH_SIGNATURE_U; + +#define NL_AUTH_SIGNATURE_P(_u) (&(_u)->Signature) + +typedef struct gssnetlogon_name { + gss_buffer_desc NetbiosName; + gss_buffer_desc DnsName; +} *gssnetlogon_name; +typedef const struct gssnetlogon_name *gssnetlogon_const_name; + +typedef struct gssnetlogon_cred { + gssnetlogon_name *Name; + uint16_t SignatureAlgorithm; + uint16_t SealAlgorithm; + uint8_t SessionKey[16]; +} *gssnetlogon_cred; +typedef const struct gssnetlogon_cred *gssnetlogon_const_cred; + +typedef struct gssnetlogon_ctx { + HEIMDAL_MUTEX Mutex; + enum { NL_AUTH_NEGOTIATE, NL_AUTH_ESTABLISHED } State; + OM_uint32 GssFlags; + uint8_t LocallyInitiated; + uint32_t MessageBlockSize; + uint16_t SignatureAlgorithm; + uint16_t SealAlgorithm; + uint64_t SequenceNumber; + gssnetlogon_name SourceName; + gssnetlogon_name TargetName; + uint8_t SessionKey[16]; +} *gssnetlogon_ctx; + +#include <netlogon-private.h> + +#endif /* NETLOGON_NETLOGON_H */ diff --git a/third_party/heimdal/lib/gssapi/netlogon/process_context_token.c b/third_party/heimdal/lib/gssapi/netlogon/process_context_token.c new file mode 100644 index 0000000..0f83613 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/process_context_token.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_process_context_token ( + OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/netlogon/regen.sh b/third_party/heimdal/lib/gssapi/netlogon/regen.sh new file mode 100644 index 0000000..b034dbf --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/regen.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +perl ../../../cf/make-proto.pl -q -P comment -p netlogon-private.h *.c diff --git a/third_party/heimdal/lib/gssapi/netlogon/release_cred.c b/third_party/heimdal/lib/gssapi/netlogon/release_cred.c new file mode 100644 index 0000000..7db71b6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/release_cred.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_release_cred + (OM_uint32 * minor_status, + gss_cred_id_t * cred_handle + ) +{ + gssnetlogon_cred cred = (gssnetlogon_cred)*cred_handle; + + if (cred != NULL) { + _netlogon_release_name(minor_status, (gss_name_t *)&cred->Name); + memset(cred, 0, sizeof(*cred)); + free(cred); + *cred_handle = GSS_C_NO_CREDENTIAL; + } + + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/netlogon/release_name.c b/third_party/heimdal/lib/gssapi/netlogon/release_name.c new file mode 100644 index 0000000..27ca018 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/netlogon/release_name.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "netlogon.h" + +OM_uint32 _netlogon_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ) +{ + gssnetlogon_name name = (gssnetlogon_name)*input_name; + + if (name != NULL) { + gss_release_buffer(minor_status, &name->NetbiosName); + gss_release_buffer(minor_status, &name->DnsName); + free(name); + *input_name = GSS_C_NO_NAME; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c new file mode 100644 index 0000000..6a3e889 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +/* + * + */ + +OM_uint32 +_gss_ntlm_allocate_ctx(OM_uint32 *minor_status, ntlm_ctx *ctx) +{ + OM_uint32 maj_stat; + struct ntlm_server_interface *ns_interface = NULL; + +#ifdef DIGEST + ns_interface = &ntlmsspi_kdc_digest; +#endif + if (ns_interface == NULL) + return GSS_S_FAILURE; + + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + (*ctx)->server = ns_interface; + + maj_stat = (*(*ctx)->server->nsi_init)(minor_status, &(*ctx)->ictx); + if (maj_stat == GSS_S_COMPLETE) + return GSS_S_COMPLETE; + + if (*ctx) + free(*ctx); + (*ctx) = NULL; + + return maj_stat; +} + +/* + * + */ + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_accept_sec_context +(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle + ) +{ + krb5_error_code ret; + struct ntlm_buf data; + OM_uint32 junk; + ntlm_ctx ctx; + + output_token->value = NULL; + output_token->length = 0; + + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_FAILURE; + + if (input_token_buffer == GSS_C_NO_BUFFER) + return GSS_S_FAILURE; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (mech_type) + *mech_type = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + if (*context_handle == GSS_C_NO_CONTEXT) { + struct ntlm_type1 type1; + OM_uint32 major_status; + OM_uint32 retflags; + struct ntlm_buf out; + + major_status = _gss_ntlm_allocate_ctx(minor_status, &ctx); + if (major_status) + return major_status; + *context_handle = (gss_ctx_id_t)ctx; + + /* check if the mechs is allowed by remote service */ + major_status = (*ctx->server->nsi_probe)(minor_status, ctx->ictx, NULL); + if (major_status) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + return major_status; + } + + data.data = input_token_buffer->value; + data.length = input_token_buffer->length; + + ret = heim_ntlm_decode_type1(&data, &type1); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if ((type1.flags & NTLM_NEG_UNICODE) == 0) { + heim_ntlm_free_type1(&type1); + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (type1.flags & NTLM_NEG_SIGN) + ctx->gssflags |= GSS_C_CONF_FLAG; + if (type1.flags & NTLM_NEG_SIGN) + ctx->gssflags |= GSS_C_INTEG_FLAG; + + major_status = (*ctx->server->nsi_type2)(minor_status, + ctx->ictx, + type1.flags, + type1.hostname, + type1.domain, + &retflags, + &out); + heim_ntlm_free_type1(&type1); + if (major_status != GSS_S_COMPLETE) { + OM_uint32 gunk; + _gss_ntlm_delete_sec_context(&gunk, context_handle, NULL); + return major_status; + } + + output_token->value = malloc(out.length); + if (output_token->value == NULL && out.length != 0) { + OM_uint32 gunk; + heim_ntlm_free_buf(&out); + _gss_ntlm_delete_sec_context(&gunk, context_handle, NULL); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(output_token->value, out.data, out.length); + output_token->length = out.length; + heim_ntlm_free_buf(&out); + + ctx->flags = retflags; + + return GSS_S_CONTINUE_NEEDED; + } else { + OM_uint32 maj_stat; + struct ntlm_type3 type3; + struct ntlm_buf session; + + ctx = (ntlm_ctx)*context_handle; + + data.data = input_token_buffer->value; + data.length = input_token_buffer->length; + + ret = heim_ntlm_decode_type3(&data, 1, &type3); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + maj_stat = (*ctx->server->nsi_type3)(minor_status, + ctx->ictx, + &type3, + &session); + if (maj_stat) { + heim_ntlm_free_type3(&type3); + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + return maj_stat; + } + + if (src_name) { + ntlm_name n = calloc(1, sizeof(*n)); + if (n) { + n->user = strdup(type3.username); + n->domain = strdup(type3.targetname); + } + if (n == NULL || n->user == NULL || n->domain == NULL) { + gss_name_t tempn = (gss_name_t)n; + _gss_ntlm_release_name(&junk, &tempn); + heim_ntlm_free_type3(&type3); + _gss_ntlm_delete_sec_context(minor_status, + context_handle, NULL); + return maj_stat; + } + *src_name = (gss_name_t)n; + } + + heim_ntlm_free_type3(&type3); + + ret = krb5_data_copy(&ctx->sessionkey, + session.data, session.length); + if (ret) { + if (src_name) + _gss_ntlm_release_name(&junk, src_name); + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = ret; + return GSS_S_FAILURE; + } + + _gss_ntlm_set_keys(ctx); + + if (mech_type) + *mech_type = GSS_NTLM_MECHANISM; + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + + ctx->status |= STATUS_OPEN; + + if (ret_flags) + *ret_flags = ctx->gssflags; + + return GSS_S_COMPLETE; + } +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/acquire_cred.c b/third_party/heimdal/lib/gssapi/ntlm/acquire_cred.c new file mode 100644 index 0000000..a6b151f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/acquire_cred.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_acquire_cred_from(OM_uint32 *min_stat, + gss_const_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + ntlm_name name = (ntlm_name) desired_name; + OM_uint32 maj_stat; + ntlm_ctx ctx; + + *min_stat = 0; + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + + if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_ACCEPT) { + int ret; + + maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + ret = (*ctx->server->nsi_probe)(min_stat, ctx->ictx, NULL); + { + gss_ctx_id_t context = (gss_ctx_id_t)ctx; + OM_uint32 junk; + _gss_ntlm_delete_sec_context(&junk, &context, NULL); + } + if (ret) { + *min_stat = ret; + return GSS_S_NO_CRED; + } + } + if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_INITIATE) { + ntlm_cred cred; + + *min_stat = _gss_ntlm_get_user_cred(name, &cred); + if (*min_stat) + return GSS_S_NO_CRED; + cred->usage = cred_usage; + + *output_cred_handle = (gss_cred_id_t)cred; + } + + return (GSS_S_COMPLETE); +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/add_cred.c b/third_party/heimdal/lib/gssapi/ntlm/add_cred.c new file mode 100644 index 0000000..1517232 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/add_cred.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV _gss_ntlm_add_cred ( + OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + if (minor_status) + *minor_status = 0; + if (output_cred_handle) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + if (initiator_time_rec) + *initiator_time_rec = 0; + if (acceptor_time_rec) + *acceptor_time_rec = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/canonicalize_name.c b/third_party/heimdal/lib/gssapi/ntlm/canonicalize_name.c new file mode 100644 index 0000000..3409b3b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/canonicalize_name.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_canonicalize_name ( + OM_uint32 * minor_status, + gss_const_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ) +{ + return gss_duplicate_name (minor_status, input_name, output_name); +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/compare_name.c b/third_party/heimdal/lib/gssapi/ntlm/compare_name.c new file mode 100644 index 0000000..d185ab9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/compare_name.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV _gss_ntlm_compare_name + (OM_uint32 * minor_status, + gss_const_name_t name1, + gss_const_name_t name2, + int * name_equal + ) +{ + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/context_time.c b/third_party/heimdal/lib/gssapi/ntlm/context_time.c new file mode 100644 index 0000000..589ee2a --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/context_time.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV _gss_ntlm_context_time + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + OM_uint32 * time_rec + ) +{ + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/creds.c b/third_party/heimdal/lib/gssapi/ntlm/creds.c new file mode 100644 index 0000000..5794015 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/creds.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_inquire_cred + (OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + gss_name_t * name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ) +{ + OM_uint32 ret, junk; + + *minor_status = 0; + + if (cred_handle == NULL) + return GSS_S_NO_CRED; + + if (name) { + ntlm_name n = calloc(1, sizeof(*n)); + ntlm_cred c = (ntlm_cred)cred_handle; + if (n) { + n->user = strdup(c->username); + n->domain = strdup(c->domain); + } + if (n == NULL || n->user == NULL || n->domain == NULL) { + if (n) { + free(n->user); + free(n->domain); + free(n); + } + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + *name = (gss_name_t)n; + } + if (lifetime) + *lifetime = GSS_C_INDEFINITE; + if (cred_usage) + *cred_usage = 0; + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; + if (mechanisms) { + ret = gss_create_empty_oid_set(minor_status, mechanisms); + if (ret) + goto out; + ret = gss_add_oid_set_member(minor_status, + GSS_NTLM_MECHANISM, + mechanisms); + if (ret) + goto out; + } + + return GSS_S_COMPLETE; +out: + gss_release_oid_set(&junk, mechanisms); + return ret; +} + +#ifdef HAVE_KCM +static OM_uint32 +_gss_ntlm_destroy_kcm_cred(gss_cred_id_t *cred_handle) +{ + krb5_storage *request, *response; + krb5_data response_data; + krb5_context context; + krb5_error_code ret; + ntlm_cred cred; + + cred = (ntlm_cred)*cred_handle; + + ret = krb5_init_context(&context); + if (ret) + return ret; + + ret = krb5_kcm_storage_request(context, KCM_OP_DEL_NTLM_CRED, &request); + if (ret) + goto out; + + ret = krb5_store_stringz(request, cred->username); + if (ret) + goto out; + + ret = krb5_store_stringz(request, cred->domain); + if (ret) + goto out; + + ret = krb5_kcm_call(context, request, &response, &response_data); + if (ret) + goto out; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + out: + krb5_free_context(context); + + return ret; +} +#endif /* HAVE_KCM */ + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_destroy_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle) +{ +#ifdef HAVE_KCM + krb5_error_code ret; +#endif + + if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_COMPLETE; + +#ifdef HAVE_KCM + ret = _gss_ntlm_destroy_kcm_cred(cred_handle); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } +#endif + + return _gss_ntlm_release_cred(minor_status, cred_handle); +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/crypto.c b/third_party/heimdal/lib/gssapi/ntlm/crypto.c new file mode 100644 index 0000000..efa71d9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/crypto.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2006-2016 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" +struct hx509_certs_data; +struct krb5_pk_identity; +struct krb5_pk_cert; +struct ContentInfo; +struct AlgorithmIdentifier; +struct _krb5_krb_auth_data; +struct krb5_dh_moduli; +struct _krb5_key_data; +struct _krb5_encryption_type; +struct _krb5_key_type; +#include "krb5_locl.h" + +/* + * + */ + +static void +encode_le_uint32(uint32_t n, unsigned char *p) +{ + p[0] = (n >> 0) & 0xFF; + p[1] = (n >> 8) & 0xFF; + p[2] = (n >> 16) & 0xFF; + p[3] = (n >> 24) & 0xFF; +} + + +static void +decode_le_uint32(const void *ptr, uint32_t *n) +{ + const unsigned char *p = ptr; + *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +/* + * + */ + +const char a2i_signmagic[] = + "session key to server-to-client signing key magic constant"; +const char a2i_sealmagic[] = + "session key to server-to-client sealing key magic constant"; +const char i2a_signmagic[] = + "session key to client-to-server signing key magic constant"; +const char i2a_sealmagic[] = + "session key to client-to-server sealing key magic constant"; + + +void +_gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, + unsigned char *data, size_t len) +{ + unsigned char out[16]; + EVP_MD_CTX *ctx; + const char *signmagic; + const char *sealmagic; + + if (acceptor) { + signmagic = a2i_signmagic; + sealmagic = a2i_sealmagic; + } else { + signmagic = i2a_signmagic; + sealmagic = i2a_sealmagic; + } + + key->seq = 0; + + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, EVP_md5(), NULL); + EVP_DigestUpdate(ctx, data, len); + EVP_DigestUpdate(ctx, signmagic, strlen(signmagic) + 1); + EVP_DigestFinal_ex(ctx, key->signkey, NULL); + + EVP_DigestInit_ex(ctx, EVP_md5(), NULL); + EVP_DigestUpdate(ctx, data, len); + EVP_DigestUpdate(ctx, sealmagic, strlen(sealmagic) + 1); + EVP_DigestFinal_ex(ctx, out, NULL); + EVP_MD_CTX_destroy(ctx); + + RC4_set_key(&key->sealkey, 16, out); + if (sealsign) + key->signsealkey = &key->sealkey; +} + +/* + * Set (or reset) keys + */ + +void +_gss_ntlm_set_keys(ntlm_ctx ctx) +{ + int acceptor; + + if (ctx->sessionkey.length == 0) + return; + + acceptor = !(ctx->status & STATUS_CLIENT); + + ctx->status |= STATUS_SESSIONKEY; + + if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { + _gss_ntlm_set_key(&ctx->u.v2.send, acceptor, + (ctx->flags & NTLM_NEG_KEYEX), + ctx->sessionkey.data, + ctx->sessionkey.length); + _gss_ntlm_set_key(&ctx->u.v2.recv, !acceptor, + (ctx->flags & NTLM_NEG_KEYEX), + ctx->sessionkey.data, + ctx->sessionkey.length); + } else { + ctx->u.v1.crypto_send.seq = 0; + RC4_set_key(&ctx->u.v1.crypto_send.key, + ctx->sessionkey.length, + ctx->sessionkey.data); + ctx->u.v1.crypto_recv.seq = 0; + RC4_set_key(&ctx->u.v1.crypto_recv.key, + ctx->sessionkey.length, + ctx->sessionkey.data); + } +} + +/* + * + */ + +static OM_uint32 +v1_sign_message(gss_buffer_t in, + RC4_KEY *signkey, + uint32_t seq, + unsigned char out[16]) +{ + unsigned char sigature[12]; + uint32_t crc; + + _krb5_crc_init_table(); + crc = _krb5_crc_update(in->value, in->length, 0); + + encode_le_uint32(0, &sigature[0]); + encode_le_uint32(crc, &sigature[4]); + encode_le_uint32(seq, &sigature[8]); + + encode_le_uint32(1, out); /* version */ + RC4(signkey, sizeof(sigature), sigature, out + 4); + + if (RAND_bytes(out + 4, 4) != 1) + return GSS_S_UNAVAILABLE; + + return 0; +} + + +static OM_uint32 +v2_sign_message(gss_buffer_t in, + unsigned char signkey[16], + RC4_KEY *sealkey, + uint32_t seq, + unsigned char out[16]) +{ + unsigned char hmac[16]; + unsigned int hmaclen; + HMAC_CTX c; + + HMAC_CTX_init(&c); + if (HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL) == 0) { + HMAC_CTX_cleanup(&c); + return GSS_S_FAILURE; + } + + encode_le_uint32(seq, hmac); + HMAC_Update(&c, hmac, 4); + HMAC_Update(&c, in->value, in->length); + HMAC_Final(&c, hmac, &hmaclen); + HMAC_CTX_cleanup(&c); + + encode_le_uint32(1, &out[0]); + if (sealkey) + RC4(sealkey, 8, hmac, &out[4]); + else + memcpy(&out[4], hmac, 8); + + memset(&out[12], 0, 4); + + return GSS_S_COMPLETE; +} + +static OM_uint32 +v2_verify_message(gss_buffer_t in, + unsigned char signkey[16], + RC4_KEY *sealkey, + uint32_t seq, + const unsigned char checksum[16]) +{ + OM_uint32 ret; + unsigned char out[16]; + + ret = v2_sign_message(in, signkey, sealkey, seq, out); + if (ret) + return ret; + + if (memcmp(checksum, out, 16) != 0) + return GSS_S_BAD_MIC; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +v2_seal_message(const gss_buffer_t in, + unsigned char signkey[16], + uint32_t seq, + RC4_KEY *sealkey, + gss_buffer_t out) +{ + unsigned char *p; + OM_uint32 ret; + + if (in->length + 16 < in->length) + return EINVAL; + + p = malloc(in->length + 16); + if (p == NULL) + return ENOMEM; + + RC4(sealkey, in->length, in->value, p); + + ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); + if (ret) { + free(p); + return ret; + } + + out->value = p; + out->length = in->length + 16; + + return 0; +} + +static OM_uint32 +v2_unseal_message(gss_buffer_t in, + unsigned char signkey[16], + uint32_t seq, + RC4_KEY *sealkey, + gss_buffer_t out) +{ + OM_uint32 ret; + + if (in->length < 16) + return GSS_S_BAD_MIC; + + out->length = in->length - 16; + out->value = malloc(out->length); + if (out->value == NULL) + return GSS_S_BAD_MIC; + + RC4(sealkey, out->length, in->value, out->value); + + ret = v2_verify_message(out, signkey, sealkey, seq, + ((const unsigned char *)in->value) + out->length); + if (ret) { + OM_uint32 junk; + gss_release_buffer(&junk, out); + } + return ret; +} + +/* + * + */ + +#define CTX_FLAGS_ISSET(_ctx,_flags) \ + (((_ctx)->flags & (_flags)) == (_flags)) + +/* + * + */ + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_get_mic + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + ntlm_ctx ctx = (ntlm_ctx)context_handle; + OM_uint32 junk; + + *minor_status = 0; + + message_token->value = malloc(16); + message_token->length = 16; + if (message_token->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { + OM_uint32 ret; + + if ((ctx->status & STATUS_SESSIONKEY) == 0) { + gss_release_buffer(&junk, message_token); + return GSS_S_UNAVAILABLE; + } + + ret = v2_sign_message(message_buffer, + ctx->u.v2.send.signkey, + ctx->u.v2.send.signsealkey, + ctx->u.v2.send.seq++, + message_token->value); + if (ret) + gss_release_buffer(&junk, message_token); + return ret; + + } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { + OM_uint32 ret; + + if ((ctx->status & STATUS_SESSIONKEY) == 0) { + gss_release_buffer(&junk, message_token); + return GSS_S_UNAVAILABLE; + } + + ret = v1_sign_message(message_buffer, + &ctx->u.v1.crypto_send.key, + ctx->u.v1.crypto_send.seq++, + message_token->value); + if (ret) + gss_release_buffer(&junk, message_token); + return ret; + + } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { + unsigned char *sigature; + + sigature = message_token->value; + + encode_le_uint32(1, &sigature[0]); /* version */ + encode_le_uint32(0, &sigature[4]); + encode_le_uint32(0, &sigature[8]); + encode_le_uint32(0, &sigature[12]); + + return GSS_S_COMPLETE; + } + gss_release_buffer(&junk, message_token); + + return GSS_S_UNAVAILABLE; +} + +/* + * + */ + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_verify_mic + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + ntlm_ctx ctx = (ntlm_ctx)context_handle; + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + *minor_status = 0; + + if (token_buffer->length != 16) + return GSS_S_BAD_MIC; + + if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { + OM_uint32 ret; + + if ((ctx->status & STATUS_SESSIONKEY) == 0) + return GSS_S_UNAVAILABLE; + + ret = v2_verify_message(message_buffer, + ctx->u.v2.recv.signkey, + ctx->u.v2.recv.signsealkey, + ctx->u.v2.recv.seq++, + token_buffer->value); + if (ret) + return ret; + + return GSS_S_COMPLETE; + } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { + + unsigned char sigature[12]; + uint32_t crc, num; + + if ((ctx->status & STATUS_SESSIONKEY) == 0) + return GSS_S_UNAVAILABLE; + + decode_le_uint32(token_buffer->value, &num); + if (num != 1) + return GSS_S_BAD_MIC; + + RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), + ((unsigned char *)token_buffer->value) + 4, sigature); + + _krb5_crc_init_table(); + crc = _krb5_crc_update(message_buffer->value, + message_buffer->length, 0); + /* skip first 4 bytes in the encrypted checksum */ + decode_le_uint32(&sigature[4], &num); + if (num != crc) + return GSS_S_BAD_MIC; + decode_le_uint32(&sigature[8], &num); + if (ctx->u.v1.crypto_recv.seq != num) + return GSS_S_BAD_MIC; + ctx->u.v1.crypto_recv.seq++; + + return GSS_S_COMPLETE; + } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { + uint32_t num; + unsigned char *p; + + p = (unsigned char*)(token_buffer->value); + + decode_le_uint32(&p[0], &num); /* version */ + if (num != 1) return GSS_S_BAD_MIC; + decode_le_uint32(&p[4], &num); + if (num != 0) return GSS_S_BAD_MIC; + decode_le_uint32(&p[8], &num); + if (num != 0) return GSS_S_BAD_MIC; + decode_le_uint32(&p[12], &num); + if (num != 0) return GSS_S_BAD_MIC; + + return GSS_S_COMPLETE; + } + + return GSS_S_UNAVAILABLE; +} + +/* + * + */ + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_wrap_size_limit ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ) +{ + ntlm_ctx ctx = (ntlm_ctx)context_handle; + + *minor_status = 0; + + if(ctx->flags & NTLM_NEG_SEAL) { + + if (req_output_size < 16) + *max_input_size = 0; + else + *max_input_size = req_output_size - 16; + + return GSS_S_COMPLETE; + } + + return GSS_S_UNAVAILABLE; +} + +/* + * + */ + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_wrap +(OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + ntlm_ctx ctx = (ntlm_ctx)context_handle; + OM_uint32 ret; + + *minor_status = 0; + if (conf_state) + *conf_state = 0; + if (output_message_buffer == GSS_C_NO_BUFFER) + return GSS_S_FAILURE; + + + if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { + + return v2_seal_message(input_message_buffer, + ctx->u.v2.send.signkey, + ctx->u.v2.send.seq++, + &ctx->u.v2.send.sealkey, + output_message_buffer); + + } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { + gss_buffer_desc trailer; + OM_uint32 junk; + + output_message_buffer->length = input_message_buffer->length + 16; + output_message_buffer->value = malloc(output_message_buffer->length); + if (output_message_buffer->value == NULL) { + output_message_buffer->length = 0; + return GSS_S_FAILURE; + } + + + RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, + input_message_buffer->value, output_message_buffer->value); + + ret = _gss_ntlm_get_mic(minor_status, context_handle, + 0, input_message_buffer, + &trailer); + if (ret) { + gss_release_buffer(&junk, output_message_buffer); + return ret; + } + if (trailer.length != 16) { + gss_release_buffer(&junk, output_message_buffer); + gss_release_buffer(&junk, &trailer); + return GSS_S_FAILURE; + } + memcpy(((unsigned char *)output_message_buffer->value) + + input_message_buffer->length, + trailer.value, trailer.length); + gss_release_buffer(&junk, &trailer); + + return GSS_S_COMPLETE; + } + + return GSS_S_UNAVAILABLE; +} + +/* + * + */ + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_unwrap + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + ntlm_ctx ctx = (ntlm_ctx)context_handle; + OM_uint32 ret; + + *minor_status = 0; + output_message_buffer->value = NULL; + output_message_buffer->length = 0; + + if (conf_state) + *conf_state = 0; + if (qop_state) + *qop_state = 0; + + if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { + + return v2_unseal_message(input_message_buffer, + ctx->u.v2.recv.signkey, + ctx->u.v2.recv.seq++, + &ctx->u.v2.recv.sealkey, + output_message_buffer); + + } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { + + gss_buffer_desc trailer; + OM_uint32 junk; + + if (input_message_buffer->length < 16) + return GSS_S_BAD_MIC; + + output_message_buffer->length = input_message_buffer->length - 16; + output_message_buffer->value = malloc(output_message_buffer->length); + if (output_message_buffer->value == NULL) { + output_message_buffer->length = 0; + return GSS_S_FAILURE; + } + + RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, + input_message_buffer->value, output_message_buffer->value); + + trailer.value = ((unsigned char *)input_message_buffer->value) + + output_message_buffer->length; + trailer.length = 16; + + ret = _gss_ntlm_verify_mic(minor_status, context_handle, + output_message_buffer, + &trailer, NULL); + if (ret) { + gss_release_buffer(&junk, output_message_buffer); + return ret; + } + + return GSS_S_COMPLETE; + } + + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c new file mode 100644 index 0000000..57587a0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV _gss_ntlm_delete_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token + ) +{ + OM_uint32 min; + + if (context_handle) { + ntlm_ctx ctx = (ntlm_ctx)*context_handle; + gss_cred_id_t cred = (gss_cred_id_t)ctx->client; + + *context_handle = GSS_C_NO_CONTEXT; + + if (ctx->server) + (*ctx->server->nsi_destroy)(minor_status, ctx->ictx); + + _gss_ntlm_release_cred(NULL, &cred); + memset_s(ctx->sessionkey.data, ctx->sessionkey.length, 0, + ctx->sessionkey.length); + krb5_data_free(&ctx->sessionkey); + gss_release_buffer(&min, &ctx->pac); + + memset(ctx, 0, sizeof(*ctx)); + free(ctx); + } + if (output_token) { + output_token->length = 0; + output_token->value = NULL; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/display_name.c b/third_party/heimdal/lib/gssapi/ntlm/display_name.c new file mode 100644 index 0000000..59d2c84 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/display_name.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_display_name + (OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + *minor_status = 0; + + if (output_name_type) + *output_name_type = GSS_NTLM_MECHANISM; + + if (output_name_buffer) { + ntlm_name n = (ntlm_name)input_name; + char *str = NULL; + int len; + + output_name_buffer->length = 0; + output_name_buffer->value = NULL; + + if (n == NULL) { + *minor_status = 0; + return GSS_S_BAD_NAME; + } + + len = asprintf(&str, "%s@%s", n->user, n->domain); + if (len < 0 || str == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + output_name_buffer->length = len; + output_name_buffer->value = str; + } + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/display_status.c b/third_party/heimdal/lib/gssapi/ntlm/display_status.c new file mode 100644 index 0000000..c9e1792 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/display_status.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_display_status + (OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + if (minor_status) + *minor_status = 0; + if (status_string) { + status_string->length = 0; + status_string->value = NULL; + } + if (message_context) + *message_context = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/duplicate_cred.c b/third_party/heimdal/lib/gssapi/ntlm/duplicate_cred.c new file mode 100644 index 0000000..d05f9fa --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/duplicate_cred.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2006-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_duplicate_cred(OM_uint32 *minor_status, + gss_const_cred_id_t input_cred_handle, + gss_cred_id_t *output_cred_handle) +{ + ntlm_const_cred cred = (ntlm_const_cred)input_cred_handle; + ntlm_cred new_cred; + OM_uint32 junk; + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) + return _gss_ntlm_acquire_cred_from(minor_status, GSS_C_NO_NAME, + GSS_C_INDEFINITE, GSS_C_NO_OID_SET, + GSS_C_BOTH, GSS_C_NO_CRED_STORE, + output_cred_handle, NULL, NULL); + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + *minor_status = _gss_ntlm_copy_cred((ntlm_cred)input_cred_handle, + (ntlm_cred *)output_cred_handle); + + return *minor_status == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/duplicate_name.c b/third_party/heimdal/lib/gssapi/ntlm/duplicate_name.c new file mode 100644 index 0000000..060fa55 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/duplicate_name.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_duplicate_name ( + OM_uint32 * minor_status, + gss_const_name_t src_name, + gss_name_t * dest_name + ) +{ + if (minor_status) + *minor_status = 0; + if (dest_name) + *dest_name = NULL; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/export_name.c b/third_party/heimdal/lib/gssapi/ntlm/export_name.c new file mode 100644 index 0000000..e5bdca4 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/export_name.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 1999, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_export_name + (OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_buffer_t exported_name + ) +{ + if (minor_status) + *minor_status = 0; + if (exported_name) { + exported_name->length = 0; + exported_name->value = NULL; + } + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/export_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/export_sec_context.c new file mode 100644 index 0000000..027a921 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/export_sec_context.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ) +{ + if (minor_status) + *minor_status = 0; + if (interprocess_token) { + interprocess_token->length = 0; + interprocess_token->value = NULL; + } + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/external.c b/third_party/heimdal/lib/gssapi/ntlm/external.c new file mode 100644 index 0000000..ff2cd2d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/external.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2006-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +static gss_mo_desc ntlm_mo[] = { + { + GSS_C_MA_SASL_MECH_NAME, + GSS_MO_MA, + "SASL mech name", + rk_UNCONST("NTLM"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_NAME, + GSS_MO_MA, + "Mechanism name", + rk_UNCONST("NTLMSPP"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_DESCRIPTION, + GSS_MO_MA, + "Mechanism description", + rk_UNCONST("Heimdal NTLMSSP Mechanism"), + _gss_mo_get_ctx_as_string, + NULL + } +}; + +static gssapi_mech_interface_desc ntlm_mech = { + GMI_VERSION, + "ntlm", + {10, rk_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a") }, + 0, + NULL, + _gss_ntlm_release_cred, + _gss_ntlm_init_sec_context, + _gss_ntlm_accept_sec_context, + _gss_ntlm_process_context_token, + _gss_ntlm_delete_sec_context, + _gss_ntlm_context_time, + _gss_ntlm_get_mic, + _gss_ntlm_verify_mic, + _gss_ntlm_wrap, + _gss_ntlm_unwrap, + _gss_ntlm_display_status, + NULL, + _gss_ntlm_compare_name, + _gss_ntlm_display_name, + _gss_ntlm_import_name, + _gss_ntlm_export_name, + _gss_ntlm_release_name, + _gss_ntlm_inquire_cred, + _gss_ntlm_inquire_context, + _gss_ntlm_wrap_size_limit, + _gss_ntlm_add_cred, + _gss_ntlm_inquire_cred_by_mech, + _gss_ntlm_export_sec_context, + _gss_ntlm_import_sec_context, + _gss_ntlm_inquire_names_for_mech, + _gss_ntlm_inquire_mechs_for_name, + _gss_ntlm_canonicalize_name, + _gss_ntlm_duplicate_name, + _gss_ntlm_inquire_sec_context_by_oid, + NULL, + _gss_ntlm_set_sec_context_option, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _gss_ntlm_acquire_cred_from, + NULL, /* gm_acquire_cred_impersonate_name */ + _gss_ntlm_iter_creds_f, + _gss_ntlm_destroy_cred, + NULL, + NULL, + NULL, + NULL, + ntlm_mo, + sizeof(ntlm_mo) / sizeof(ntlm_mo[0]), + NULL, /* gm_localname */ + NULL, /* gm_authorize_localname */ + NULL, /* gm_display_name_ext */ + NULL, /* gm_inquire_name */ + NULL, /* gm_get_name_attribute */ + NULL, /* gm_set_name_attribute */ + NULL, /* gm_delete_name_attribute */ + NULL, /* gm_export_name_composite */ + NULL, /* gm_duplicate_cred */ + NULL, /* gm_add_cred_from */ + NULL, /* gm_store_cred_into */ + NULL, /* gm_query_mechanism_info */ + NULL, /* gm_query_meta_data */ + NULL, /* gm_exchange_meta_data */ + NULL, /* gm_store_cred_into2 */ + NULL, /* gm_compat */ +}; + +gssapi_mech_interface +__gss_ntlm_initialize(void) +{ + return &ntlm_mech; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/import_name.c b/third_party/heimdal/lib/gssapi/ntlm/import_name.c new file mode 100644 index 0000000..e75388d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/import_name.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + char *name, *p, *p2; + int is_hostnamed; + int is_username; + ntlm_name n; + + *minor_status = 0; + + if (output_name == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *output_name = GSS_C_NO_NAME; + + is_hostnamed = gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE); + is_username = gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME); + + if (!is_hostnamed && !is_username) + return GSS_S_BAD_NAMETYPE; + + name = malloc(input_name_buffer->length + 1); + if (name == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(name, input_name_buffer->value, input_name_buffer->length); + name[input_name_buffer->length] = '\0'; + + /* find "domain" part of the name and uppercase it */ + p = strchr(name, '@'); + if (p == NULL) { + free(name); + return GSS_S_BAD_NAME; + } + p[0] = '\0'; + p++; + p2 = strchr(p, '.'); + if (p2 && p2[1] != '\0') { + if (is_hostnamed) { + p = p2 + 1; + p2 = strchr(p, '.'); + } + if (p2) + *p2 = '\0'; + } + strupr(p); + + n = calloc(1, sizeof(*n)); + if (n == NULL) { + free(name); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + n->user = strdup(name); + n->domain = strdup(p); + + free(name); + + if (n->user == NULL || n->domain == NULL) { + free(n->user); + free(n->domain); + free(n); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *output_name = (gss_name_t)n; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/import_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/import_sec_context.c new file mode 100644 index 0000000..fe637c0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/import_sec_context.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t * context_handle + ) +{ + if (minor_status) + *minor_status = 0; + if (context_handle) + *context_handle = GSS_C_NO_CONTEXT; + return GSS_S_FAILURE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/indicate_mechs.c b/third_party/heimdal/lib/gssapi/ntlm/indicate_mechs.c new file mode 100644 index 0000000..7cda475 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/indicate_mechs.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 _gss_ntlm_indicate_mechs +(OM_uint32 * minor_status, + gss_OID_set * mech_set + ) +{ + if (minor_status) + *minor_status = 0; + if (mech_set) + *mech_set = GSS_C_NO_OID_SET; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c new file mode 100644 index 0000000..be9c987 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +static int +from_file(const char *fn, const char *target_domain, + char **domainp, char **usernamep, struct ntlm_buf *key) +{ + char *str, buf[1024]; + FILE *f; + + *domainp = NULL; + + f = fopen(fn, "r"); + if (f == NULL) + return ENOENT; + rk_cloexec_file(f); + + while (fgets(buf, sizeof(buf), f) != NULL) { + char *d, *u, *p; + buf[strcspn(buf, "\r\n")] = '\0'; + if (buf[0] == '#') + continue; + str = NULL; + d = strtok_r(buf, ":", &str); + free(*domainp); + *domainp = NULL; + if (!d) + continue; + if (d && target_domain != NULL && strcasecmp(target_domain, d) != 0) + continue; + *domainp = strdup(d); + if (*domainp == NULL) { + fclose(f); + return ENOMEM; + } + u = strtok_r(NULL, ":", &str); + p = strtok_r(NULL, ":", &str); + if (u == NULL || p == NULL) + continue; + + *usernamep = strdup(u); + if (*usernamep == NULL) { + fclose(f); + return ENOMEM; + } + heim_ntlm_nt_key(p, key); + + memset_s(buf, sizeof(buf), 0, sizeof(buf)); + fclose(f); + return 0; + } + memset_s(buf, sizeof(buf), 0, sizeof(buf)); + fclose(f); + return ENOENT; +} + +static int +get_user_file(const ntlm_name target_name, + char **domainp, char **usernamep, struct ntlm_buf *key) +{ + const char *domain; + const char *fn; + + *domainp = NULL; + + domain = target_name != NULL ? target_name->domain : NULL; + + fn = secure_getenv("NTLM_USER_FILE"); + if (fn == NULL) + return ENOENT; + if (from_file(fn, domain, domainp, usernamep, key) == 0) + return 0; + + return ENOENT; +} + +/* + * Pick up the ntlm cred from the default krb5 credential cache. + */ + +static int +get_user_ccache(const ntlm_name name, char **domainp, char **usernamep, struct ntlm_buf *key) +{ + krb5_context context = NULL; + krb5_principal client; + krb5_ccache id = NULL; + krb5_error_code ret; + char *confname; + krb5_data data; + int aret; + + *domainp = NULL; + *usernamep = NULL; + krb5_data_zero(&data); + key->length = 0; + key->data = NULL; + + ret = krb5_init_context(&context); + if (ret) + return ret; + + ret = krb5_cc_default(context, &id); + if (ret) + goto out; + + ret = krb5_cc_get_principal(context, id, &client); + if (ret) + goto out; + + ret = krb5_unparse_name_flags(context, client, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + usernamep); + krb5_free_principal(context, client); + if (ret) + goto out; + + if (name != NULL) { + *domainp = strdup(name->domain); + } else { + krb5_data data_domain; + + krb5_data_zero(&data_domain); + ret = krb5_cc_get_config(context, id, NULL, "default-ntlm-domain", + &data_domain); + if (ret) + goto out; + + *domainp = strndup(data_domain.data, data_domain.length); + krb5_data_free(&data_domain); + } + + if (*domainp == NULL) { + ret = krb5_enomem(context); + goto out; + } + + aret = asprintf(&confname, "ntlm-key-%s", *domainp); + if (aret == -1) { + ret = krb5_enomem(context); + goto out; + } + + ret = krb5_cc_get_config(context, id, NULL, confname, &data); + if (ret) + goto out; + + key->data = malloc(data.length); + if (key->data == NULL) { + ret = ENOMEM; + goto out; + } + key->length = data.length; + memcpy(key->data, data.data, data.length); + + out: + krb5_data_free(&data); + if (id) + krb5_cc_close(context, id); + + krb5_free_context(context); + + return ret; +} + +int +_gss_ntlm_get_user_cred(const ntlm_name target_name, + ntlm_cred *rcred) +{ + ntlm_cred cred; + int ret; + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) + return ENOMEM; + + ret = get_user_file(target_name, + &cred->domain, &cred->username, &cred->key); + if (ret) + ret = get_user_ccache(target_name, + &cred->domain, &cred->username, &cred->key); + if (ret) { + OM_uint32 tmp; + _gss_ntlm_release_cred(&tmp, (gss_cred_id_t *)&cred); + return ret; + } + + *rcred = cred; + + return ret; +} + +int +_gss_ntlm_copy_cred(ntlm_cred from, ntlm_cred *to) +{ + *to = calloc(1, sizeof(**to)); + if (*to == NULL) + return ENOMEM; + (*to)->usage = from->usage; + (*to)->username = strdup(from->username); + if ((*to)->username == NULL) { + free(*to); + return ENOMEM; + } + (*to)->domain = strdup(from->domain); + if ((*to)->domain == NULL) { + free((*to)->username); + free(*to); + return ENOMEM; + } + (*to)->key.data = malloc(from->key.length); + if ((*to)->key.data == NULL) { + free((*to)->domain); + free((*to)->username); + free(*to); + return ENOMEM; + } + memcpy((*to)->key.data, from->key.data, from->key.length); + (*to)->key.length = from->key.length; + + return 0; +} + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_init_sec_context + (OM_uint32 * minor_status, + gss_const_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + gss_const_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + ntlm_ctx ctx; + ntlm_name name = (ntlm_name)target_name; + + *minor_status = 0; + + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + if (actual_mech_type) + *actual_mech_type = GSS_C_NO_OID; + + if (*context_handle == GSS_C_NO_CONTEXT) { + struct ntlm_type1 type1; + struct ntlm_buf data; + uint32_t flags = 0; + int ret; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + ctx->status = STATUS_CLIENT; + *context_handle = (gss_ctx_id_t)ctx; + + if (initiator_cred_handle != GSS_C_NO_CREDENTIAL) { + ntlm_cred cred = (ntlm_cred)initiator_cred_handle; + ret = _gss_ntlm_copy_cred(cred, &ctx->client); + } else + ret = _gss_ntlm_get_user_cred(name, &ctx->client); + + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (req_flags & GSS_C_CONF_FLAG) + flags |= NTLM_NEG_SEAL; + if (req_flags & GSS_C_INTEG_FLAG) + flags |= NTLM_NEG_SIGN; + else + flags |= NTLM_NEG_ALWAYS_SIGN; + + flags |= NTLM_NEG_UNICODE; + flags |= NTLM_NEG_NTLM; + flags |= NTLM_NEG_NTLM2_SESSION; + flags |= NTLM_NEG_KEYEX; + + memset(&type1, 0, sizeof(type1)); + + type1.flags = flags; + type1.domain = name->domain; + type1.hostname = NULL; + type1.os[0] = 0; + type1.os[1] = 0; + + ret = heim_ntlm_encode_type1(&type1, &data); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = ret; + return GSS_S_FAILURE; + } + + output_token->value = data.data; + output_token->length = data.length; + + return GSS_S_CONTINUE_NEEDED; + } else { + krb5_error_code ret; + struct ntlm_type2 type2; + struct ntlm_type3 type3; + struct ntlm_buf data; + + ctx = (ntlm_ctx)*context_handle; + + data.data = input_token->value; + data.length = input_token->length; + + ret = heim_ntlm_decode_type2(&data, &type2); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + ctx->flags = type2.flags; + + /* XXX check that type2.targetinfo matches `target_name´ */ + /* XXX check verify targetinfo buffer */ + + memset(&type3, 0, sizeof(type3)); + + type3.username = ctx->client->username; + type3.flags = type2.flags; + type3.targetname = type2.targetname; + type3.ws = rk_UNCONST("workstation"); + + /* + * NTLM Version 1 if no targetinfo buffer. + */ + + if (1 || type2.targetinfo.length == 0) { + struct ntlm_buf sessionkey; + + if (type2.flags & NTLM_NEG_NTLM2_SESSION) { + unsigned char nonce[8]; + + if (RAND_bytes(nonce, sizeof(nonce)) != 1) { + _gss_ntlm_delete_sec_context(minor_status, + context_handle, NULL); + heim_ntlm_free_type2(&type2); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = heim_ntlm_calculate_ntlm2_sess(nonce, + type2.challenge, + ctx->client->key.data, + &type3.lm, + &type3.ntlm); + } else { + ret = heim_ntlm_calculate_ntlm1(ctx->client->key.data, + ctx->client->key.length, + type2.challenge, + &type3.ntlm); + + } + if (ret) { + _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = heim_ntlm_build_ntlm1_master(ctx->client->key.data, + ctx->client->key.length, + &sessionkey, + &type3.sessionkey); + if (ret) { + if (type3.lm.data) + free(type3.lm.data); + if (type3.ntlm.data) + free(type3.ntlm.data); + _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_data_copy(&ctx->sessionkey, + sessionkey.data, sessionkey.length); + free(sessionkey.data); + if (ret) { + if (type3.lm.data) + free(type3.lm.data); + if (type3.ntlm.data) + free(type3.ntlm.data); + _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_FAILURE; + } + ctx->status |= STATUS_SESSIONKEY; + + } else { + struct ntlm_buf sessionkey; + unsigned char ntlmv2[16]; + struct ntlm_targetinfo ti; + + /* verify infotarget */ + + ret = heim_ntlm_decode_targetinfo(&type2.targetinfo, 1, &ti); + if(ret) { + _gss_ntlm_delete_sec_context(minor_status, + context_handle, NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) { + _gss_ntlm_delete_sec_context(minor_status, + context_handle, NULL); + heim_ntlm_free_type2(&type2); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = heim_ntlm_calculate_ntlm2(ctx->client->key.data, + ctx->client->key.length, + ctx->client->username, + name->domain, + type2.challenge, + &type2.targetinfo, + ntlmv2, + &type3.ntlm); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, + context_handle, NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), + &sessionkey, + &type3.sessionkey); + memset_s(ntlmv2, sizeof(ntlmv2), 0, sizeof(ntlmv2)); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, + context_handle, NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ctx->flags |= NTLM_NEG_NTLM2_SESSION; + + ret = krb5_data_copy(&ctx->sessionkey, + sessionkey.data, sessionkey.length); + free(sessionkey.data); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, + context_handle, NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_FAILURE; + } + } + + + _gss_ntlm_set_keys(ctx); + + + ret = heim_ntlm_encode_type3(&type3, &data, NULL); + free(type3.sessionkey.data); + if (type3.lm.data) + free(type3.lm.data); + if (type3.ntlm.data) + free(type3.ntlm.data); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + heim_ntlm_free_type2(&type2); + *minor_status = ret; + return GSS_S_FAILURE; + } + + output_token->length = data.length; + output_token->value = data.data; + + if (actual_mech_type) + *actual_mech_type = GSS_NTLM_MECHANISM; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + + ctx->status |= STATUS_OPEN; + + heim_ntlm_free_type2(&type2); + return GSS_S_COMPLETE; + } +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/inquire_context.c b/third_party/heimdal/lib/gssapi/ntlm/inquire_context.c new file mode 100644 index 0000000..741ad6e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/inquire_context.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_inquire_context ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + ntlm_ctx ctx = (ntlm_ctx)context_handle; + + *minor_status = 0; + if (src_name) + *src_name = GSS_C_NO_NAME; + if (targ_name) + *targ_name = GSS_C_NO_NAME; + if (lifetime_rec) + *lifetime_rec = GSS_C_INDEFINITE; + if (mech_type) + *mech_type = GSS_NTLM_MECHANISM; + if (ctx_flags) + *ctx_flags = ctx->gssflags; + if (locally_initiated) + *locally_initiated = (ctx->status & STATUS_CLIENT) ? 1 : 0; + if (open_context) + *open_context = (ctx->status & STATUS_OPEN) ? 1 : 0; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/inquire_cred_by_mech.c b/third_party/heimdal/lib/gssapi/ntlm/inquire_cred_by_mech.c new file mode 100644 index 0000000..ed42094 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/inquire_cred_by_mech.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_inquire_cred_by_mech ( + OM_uint32 * minor_status, + gss_const_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ) +{ + if (minor_status) + *minor_status = 0; + if (name) + *name = GSS_C_NO_NAME; + if (initiator_lifetime) + *initiator_lifetime = 0; + if (acceptor_lifetime) + *acceptor_lifetime = 0; + if (cred_usage) + *cred_usage = 0; + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/inquire_mechs_for_name.c b/third_party/heimdal/lib/gssapi/ntlm/inquire_mechs_for_name.c new file mode 100644 index 0000000..25450ab --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/inquire_mechs_for_name.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_inquire_mechs_for_name ( + OM_uint32 * minor_status, + gss_const_name_t input_name, + gss_OID_set * mech_types + ) +{ + if (minor_status) + *minor_status = 0; + if (mech_types) + *mech_types = GSS_C_NO_OID_SET; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/inquire_names_for_mech.c b/third_party/heimdal/lib/gssapi/ntlm/inquire_names_for_mech.c new file mode 100644 index 0000000..7f49b33 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/inquire_names_for_mech.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + OM_uint32 ret; + + ret = gss_create_empty_oid_set(minor_status, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/inquire_sec_context_by_oid.c b/third_party/heimdal/lib/gssapi/ntlm/inquire_sec_context_by_oid.c new file mode 100644 index 0000000..2b42b1f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/inquire_sec_context_by_oid.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_inquire_sec_context_by_oid(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + ntlm_ctx ctx = (ntlm_ctx)context_handle; + + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + if (gss_oid_equal(desired_object, GSS_NTLM_GET_SESSION_KEY_X) || + gss_oid_equal(desired_object, GSS_C_INQ_SSPI_SESSION_KEY)) { + gss_buffer_desc value; + + value.length = ctx->sessionkey.length; + value.value = ctx->sessionkey.data; + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); + } else if (gss_oid_equal(desired_object, GSS_C_INQ_WIN2K_PAC_X)) { + if (ctx->pac.length == 0) { + *minor_status = ENOENT; + return GSS_S_FAILURE; + } + + return gss_add_buffer_set_member(minor_status, + &ctx->pac, + data_set); + + } else if (gss_oid_equal(desired_object, GSS_C_NTLM_AVGUEST)) { + gss_buffer_desc value; + uint32_t num; + + if (ctx->kcmflags & KCM_NTLM_FLAG_AV_GUEST) + num = 1; + else + num = 0; + + value.length = sizeof(num); + value.value = # + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); + } else { + *minor_status = 0; + return GSS_S_FAILURE; + } +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/iter_cred.c b/third_party/heimdal/lib/gssapi/ntlm/iter_cred.c new file mode 100644 index 0000000..ee5ec17 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/iter_cred.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +void GSSAPI_CALLCONV +_gss_ntlm_iter_creds_f(OM_uint32 flags, + void *userctx , + void (*cred_iter)(void *, gss_OID, gss_cred_id_t)) +{ +#ifdef HAVE_KCM + krb5_error_code ret; + krb5_context context = NULL; + krb5_storage *request, *response; + krb5_data response_data; + + ret = krb5_init_context(&context); + if (ret) + goto done; + + ret = krb5_kcm_storage_request(context, KCM_OP_GET_NTLM_USER_LIST, &request); + if (ret) + goto done; + + ret = krb5_kcm_call(context, request, &response, &response_data); + krb5_storage_free(request); + if (ret) + goto done; + + while (1) { + uint32_t morep; + char *user = NULL, *domain = NULL; + ntlm_cred dn; + + ret = krb5_ret_uint32(response, &morep); + if (ret) goto out; + + if (!morep) goto out; + + ret = krb5_ret_stringz(response, &user); + if (ret) goto out; + ret = krb5_ret_stringz(response, &domain); + if (ret) { + free(user); + goto out; + } + + dn = calloc(1, sizeof(*dn)); + if (dn == NULL) { + free(user); + free(domain); + goto out; + } + dn->username = user; + dn->domain = domain; + + cred_iter(userctx, GSS_NTLM_MECHANISM, (gss_cred_id_t)dn); + } + out: + krb5_storage_free(response); + krb5_data_free(&response_data); + done: + if (context) + krb5_free_context(context); +#endif /* HAVE_KCM */ + (*cred_iter)(userctx, NULL, NULL); +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/kdc.c b/third_party/heimdal/lib/gssapi/ntlm/kdc.c new file mode 100644 index 0000000..1bce00f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/kdc.c @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +#ifdef DIGEST + +/* + * + */ + +struct ntlmkrb5 { + krb5_context context; + krb5_ntlm ntlm; + krb5_realm kerberos_realm; + krb5_ccache id; + krb5_data opaque; + int destroy; + OM_uint32 flags; + struct ntlm_buf key; + krb5_data sessionkey; +}; + +static OM_uint32 kdc_destroy(OM_uint32 *, void *); + +/* + * Get credential cache that the ntlm code can use to talk to the KDC + * using the digest API. + */ + +static krb5_error_code +get_ccache(krb5_context context, int *destroy, krb5_ccache *id) +{ + krb5_principal principal = NULL; + krb5_error_code ret; + krb5_keytab kt = NULL; + const char *cache = secure_getenv("NTLM_ACCEPTOR_CCACHE"); + + *id = NULL; + + if (cache) { + ret = krb5_cc_resolve(context, cache, id); + if (ret) + goto out; + return 0; + } + + ret = krb5_sname_to_principal(context, NULL, "host", + KRB5_NT_SRV_HST, &principal); + if (ret) + goto out; + + ret = krb5_cc_cache_match(context, principal, id); + if (ret == 0) + return 0; + + /* did not find in default credcache, lets try default keytab */ + ret = krb5_kt_default(context, &kt); + if (ret) + goto out; + + /* XXX check in keytab */ + { + krb5_get_init_creds_opt *opt; + krb5_creds cred; + + memset(&cred, 0, sizeof(cred)); + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, id); + if (ret) + goto out; + *destroy = 1; + ret = krb5_get_init_creds_opt_alloc(context, &opt); + if (ret) + goto out; + ret = krb5_get_init_creds_keytab (context, + &cred, + principal, + kt, + 0, + NULL, + opt); + krb5_get_init_creds_opt_free(context, opt); + if (ret) + goto out; + ret = krb5_cc_initialize (context, *id, cred.client); + if (ret) { + krb5_free_cred_contents (context, &cred); + goto out; + } + ret = krb5_cc_store_cred (context, *id, &cred); + krb5_free_cred_contents (context, &cred); + if (ret) + goto out; + } + + krb5_kt_close(context, kt); + + return 0; + +out: + if (*id) { + if (*destroy) + krb5_cc_destroy(context, *id); + else + krb5_cc_close(context, *id); + *id = NULL; + } + + if (kt) + krb5_kt_close(context, kt); + + if (principal) + krb5_free_principal(context, principal); + return ret; +} + +/* + * + */ + +static OM_uint32 +kdc_alloc(OM_uint32 *minor, void **ctx) +{ + krb5_error_code ret; + struct ntlmkrb5 *c; + OM_uint32 junk; + + c = calloc(1, sizeof(*c)); + if (c == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + ret = krb5_init_context(&c->context); + if (ret) { + kdc_destroy(&junk, c); + *minor = ret; + return GSS_S_FAILURE; + } + + ret = get_ccache(c->context, &c->destroy, &c->id); + if (ret) { + kdc_destroy(&junk, c); + *minor = ret; + return GSS_S_FAILURE; + } + + ret = krb5_ntlm_alloc(c->context, &c->ntlm); + if (ret) { + kdc_destroy(&junk, c); + *minor = ret; + return GSS_S_FAILURE; + } + + *ctx = c; + + return GSS_S_COMPLETE; +} + +static int +kdc_probe(OM_uint32 *minor, void *ctx, const char *realm) +{ + struct ntlmkrb5 *c = ctx; + krb5_error_code ret; + unsigned flags; + + ret = krb5_digest_probe(c->context, rk_UNCONST(realm), c->id, &flags); + if (ret) + return ret; + + if ((flags & (1|2|4)) == 0) + return EINVAL; + + return 0; +} + +/* + * + */ + +static OM_uint32 +kdc_destroy(OM_uint32 *minor, void *ctx) +{ + struct ntlmkrb5 *c = ctx; + krb5_data_free(&c->opaque); + krb5_data_free(&c->sessionkey); + if (c->ntlm) + krb5_ntlm_free(c->context, c->ntlm); + if (c->id) { + if (c->destroy) + krb5_cc_destroy(c->context, c->id); + else + krb5_cc_close(c->context, c->id); + } + if (c->context) + krb5_free_context(c->context); + memset(c, 0, sizeof(*c)); + free(c); + + return GSS_S_COMPLETE; +} + +/* + * + */ + +static OM_uint32 +kdc_type2(OM_uint32 *minor_status, + void *ctx, + uint32_t flags, + const char *hostname, + const char *domain, + uint32_t *ret_flags, + struct ntlm_buf *out) +{ + struct ntlmkrb5 *c = ctx; + krb5_error_code ret; + struct ntlm_type2 type2; + krb5_data challenge; + struct ntlm_buf data; + krb5_data ti; + + memset(&type2, 0, sizeof(type2)); + memset(out, 0, sizeof(*out)); + + /* + * Request data for type 2 packet from the KDC. + */ + ret = krb5_ntlm_init_request(c->context, + c->ntlm, + NULL, + c->id, + flags, + hostname, + domain); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* + * + */ + + ret = krb5_ntlm_init_get_opaque(c->context, c->ntlm, &c->opaque); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* + * + */ + + ret = krb5_ntlm_init_get_flags(c->context, c->ntlm, &type2.flags); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + *ret_flags = type2.flags; + + ret = krb5_ntlm_init_get_challenge(c->context, c->ntlm, &challenge); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (challenge.length != sizeof(type2.challenge)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + memcpy(type2.challenge, challenge.data, sizeof(type2.challenge)); + krb5_data_free(&challenge); + + ret = krb5_ntlm_init_get_targetname(c->context, c->ntlm, + &type2.targetname); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_ntlm_init_get_targetinfo(c->context, c->ntlm, &ti); + if (ret) { + free(type2.targetname); + *minor_status = ret; + return GSS_S_FAILURE; + } + + type2.targetinfo.data = ti.data; + type2.targetinfo.length = ti.length; + + ret = heim_ntlm_encode_type2(&type2, &data); + free(type2.targetname); + krb5_data_free(&ti); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + out->data = data.data; + out->length = data.length; + + return GSS_S_COMPLETE; +} + +/* + * + */ + +static OM_uint32 +kdc_type3(OM_uint32 *minor_status, + void *ctx, + const struct ntlm_type3 *type3, + struct ntlm_buf *sessionkey) +{ + struct ntlmkrb5 *c = ctx; + krb5_error_code ret; + + sessionkey->data = NULL; + sessionkey->length = 0; + + ret = krb5_ntlm_req_set_flags(c->context, c->ntlm, type3->flags); + if (ret) goto out; + ret = krb5_ntlm_req_set_username(c->context, c->ntlm, type3->username); + if (ret) goto out; + ret = krb5_ntlm_req_set_targetname(c->context, c->ntlm, + type3->targetname); + if (ret) goto out; + ret = krb5_ntlm_req_set_lm(c->context, c->ntlm, + type3->lm.data, type3->lm.length); + if (ret) goto out; + ret = krb5_ntlm_req_set_ntlm(c->context, c->ntlm, + type3->ntlm.data, type3->ntlm.length); + if (ret) goto out; + ret = krb5_ntlm_req_set_opaque(c->context, c->ntlm, &c->opaque); + if (ret) goto out; + + if (type3->sessionkey.length) { + ret = krb5_ntlm_req_set_session(c->context, c->ntlm, + type3->sessionkey.data, + type3->sessionkey.length); + if (ret) goto out; + } + + /* + * Verify with the KDC the type3 packet is ok + */ + ret = krb5_ntlm_request(c->context, + c->ntlm, + NULL, + c->id); + if (ret) + goto out; + + if (krb5_ntlm_rep_get_status(c->context, c->ntlm) != TRUE) { + ret = EINVAL; + goto out; + } + + if (type3->sessionkey.length) { + ret = krb5_ntlm_rep_get_sessionkey(c->context, + c->ntlm, + &c->sessionkey); + if (ret) + goto out; + + sessionkey->data = c->sessionkey.data; + sessionkey->length = c->sessionkey.length; + } + + return 0; + + out: + *minor_status = ret; + return GSS_S_FAILURE; +} + +/* + * + */ + +static void +kdc_free_buffer(struct ntlm_buf *sessionkey) +{ + if (sessionkey->data) + free(sessionkey->data); + sessionkey->data = NULL; + sessionkey->length = 0; +} + +/* + * + */ + +struct ntlm_server_interface ntlmsspi_kdc_digest = { + kdc_alloc, + kdc_destroy, + kdc_probe, + kdc_type2, + kdc_type3, + kdc_free_buffer +}; + +#endif /* DIGEST */ diff --git a/third_party/heimdal/lib/gssapi/ntlm/ntlm.h b/third_party/heimdal/lib/gssapi/ntlm/ntlm.h new file mode 100644 index 0000000..a0ad815 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/ntlm.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2006-2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef NTLM_NTLM_H +#define NTLM_NTLM_H + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <errno.h> + +#include <roken.h> + +#include <gssapi.h> +#include <gssapi_ntlm.h> +#include <gssapi_mech.h> +#include <gssapi_oid.h> + +#include <krb5.h> +#include <kcm.h> +#include <heim_threads.h> + +#include <heimntlm.h> + +#define HC_DEPRECATED_CRYPTO +#include "crypto-headers.h" + +typedef OM_uint32 +(*ntlm_interface_init)(OM_uint32 *, void **); + +typedef OM_uint32 +(*ntlm_interface_destroy)(OM_uint32 *, void *); + +typedef int +(*ntlm_interface_probe)(OM_uint32 *, void *, const char *); + +typedef OM_uint32 +(*ntlm_interface_type2)(OM_uint32 *, void *, uint32_t, const char *, + const char *, uint32_t *, struct ntlm_buf *); + +typedef OM_uint32 +(*ntlm_interface_type3)(OM_uint32 *, void *, const struct ntlm_type3 *, + struct ntlm_buf *); + +typedef void +(*ntlm_interface_free_buffer)(struct ntlm_buf *); + +struct ntlm_server_interface { + ntlm_interface_init nsi_init; + ntlm_interface_destroy nsi_destroy; + ntlm_interface_probe nsi_probe; + ntlm_interface_type2 nsi_type2; + ntlm_interface_type3 nsi_type3; + ntlm_interface_free_buffer nsi_free_buffer; +}; + + +struct ntlmv2_key { + uint32_t seq; + RC4_KEY sealkey; + RC4_KEY *signsealkey; + unsigned char signkey[16]; +}; + +extern struct ntlm_server_interface ntlmsspi_kdc_digest; + +typedef struct ntlm_cred { + gss_cred_usage_t usage; + char *username; + char *domain; + struct ntlm_buf key; +} *ntlm_cred; +typedef const struct ntlm_cred *ntlm_const_cred; + +typedef struct { + struct ntlm_server_interface *server; + void *ictx; + ntlm_cred client; + OM_uint32 gssflags; + uint32_t kcmflags; + uint32_t flags; + uint32_t status; +#define STATUS_OPEN 1 +#define STATUS_CLIENT 2 +#define STATUS_SESSIONKEY 4 + krb5_data sessionkey; + + gss_buffer_desc pac; + + union { + struct { + struct { + uint32_t seq; + RC4_KEY key; + } crypto_send, crypto_recv; + } v1; + struct { + struct ntlmv2_key send, recv; + } v2; + } u; +} *ntlm_ctx; + +typedef struct { + char *user; + char *domain; +} *ntlm_name; + +#include <ntlm-private.h> + + +#endif /* NTLM_NTLM_H */ diff --git a/third_party/heimdal/lib/gssapi/ntlm/process_context_token.c b/third_party/heimdal/lib/gssapi/ntlm/process_context_token.c new file mode 100644 index 0000000..2add53b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/process_context_token.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV _gss_ntlm_process_context_token ( + OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/release_cred.c b/third_party/heimdal/lib/gssapi/ntlm/release_cred.c new file mode 100644 index 0000000..e31a316 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/release_cred.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV _gss_ntlm_release_cred + (OM_uint32 * minor_status, + gss_cred_id_t * cred_handle + ) +{ + ntlm_cred cred; + + if (minor_status) + *minor_status = 0; + + if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_COMPLETE; + + cred = (ntlm_cred)*cred_handle; + *cred_handle = GSS_C_NO_CREDENTIAL; + + if (cred->username) + free(cred->username); + if (cred->domain) + free(cred->domain); + if (cred->key.data) { + memset(cred->key.data, 0, cred->key.length); + free(cred->key.data); + } + + memset(cred, 0, sizeof(*cred)); + free(cred); + + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/ntlm/release_name.c b/third_party/heimdal/lib/gssapi/ntlm/release_name.c new file mode 100644 index 0000000..4a5c56d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/release_name.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ) +{ + if (minor_status) + *minor_status = 0; + if (input_name && *input_name) { + ntlm_name n = (ntlm_name)*input_name; + *input_name = GSS_C_NO_NAME; + free(n->user); + free(n->domain); + free(n); + } + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/ntlm/set_sec_context_option.c b/third_party/heimdal/lib/gssapi/ntlm/set_sec_context_option.c new file mode 100644 index 0000000..f97443d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/ntlm/set_sec_context_option.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_set_sec_context_option(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID object, + const gss_buffer_t value) +{ + ntlm_ctx ctx; + + if (context_handle == NULL) + return GSS_S_UNAVAILABLE; + + *minor_status = 0; + + ctx = (ntlm_ctx)*context_handle; + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + if (gss_oid_equal(object, GSS_C_NTLM_RESET_CRYPTO)) { + _gss_ntlm_set_keys(ctx); + return GSS_S_COMPLETE; + } else + return GSS_S_UNAVAILABLE; +} diff --git a/third_party/heimdal/lib/gssapi/oid.txt b/third_party/heimdal/lib/gssapi/oid.txt new file mode 100644 index 0000000..fa210d6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/oid.txt @@ -0,0 +1,173 @@ +# /* +# * Contact Love Hörnquist Ã…strand <lha at h5l.org> for new oid arcs */ +# */ +# /* +# * 1.2.752.43 is SU's arc. SU's registry has arcs 13, 14, and 16 +# * below that registered for Heimdal to use. The Heimdal source tree +# * is the authoritative registry for Heimdal's three arcs off of SU's arc. +# * This file is the authoritative registry for 1.2.752.43.13 and 1.2.752.14. +# * ASN.1 modules in lib/asn1/ are authoritative for 1.2.752.43.16. +# * +# * Confirmed by SU's erstwhile registrar, Leif Johansson <leifj at sunet.se>, +# * as well as by SU's current registrar (through Leif), as: +# * +# * 1.2.752.43.13 Namn Heimdal GSS-API extentions +# * Beskrivning OIDar för användning av Heimdal projektet +# * 1.2.752.43.14 Namn Heimdal GSS-API mechs +# * Beskrivning OIDar för användning av Heimdal projektet +# * 1.2.752.43.16 Namn Heimdal Internal crypto ops +# * Beskrivning OIDar för användning av Heimdal projektet +# * +# * 1.2.752.43.16 is now also used in Heimdal for PKIX-related things. +# * See lib/asn1/ and lib/hx509/. +# * +# * Contact the SU registrar for new oid arcs if any are needed, or carve +# * out an arc of one of the above, preferably off 1.2.752.43.16. +# */ + +# /* +# * 1.2.752.43.13 Heimdal GSS-API Extensions +# */ + +oid base GSS_KRB5_COPY_CCACHE_X 1.2.752.43.13.1 +oid base GSS_KRB5_GET_TKT_FLAGS_X 1.2.752.43.13.2 +oid base GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X 1.2.752.43.13.3 +oid base GSS_KRB5_COMPAT_DES3_MIC_X 1.2.752.43.13.4 +oid base GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X 1.2.752.43.13.5 +oid base GSS_KRB5_EXPORT_LUCID_CONTEXT_X 1.2.752.43.13.6 +oid base GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X 1.2.752.43.13.6.1 +oid base GSS_KRB5_SET_DNS_CANONICALIZE_X 1.2.752.43.13.7 +oid base GSS_KRB5_GET_SUBKEY_X 1.2.752.43.13.8 +oid base GSS_KRB5_GET_INITIATOR_SUBKEY_X 1.2.752.43.13.9 +oid base GSS_KRB5_GET_ACCEPTOR_SUBKEY_X 1.2.752.43.13.10 +oid base GSS_KRB5_SEND_TO_KDC_X 1.2.752.43.13.11 +oid base GSS_KRB5_GET_AUTHTIME_X 1.2.752.43.13.12 +oid base GSS_KRB5_GET_SERVICE_KEYBLOCK_X 1.2.752.43.13.13 +oid base GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X 1.2.752.43.13.14 +oid base GSS_KRB5_SET_DEFAULT_REALM_X 1.2.752.43.13.15 +oid base GSS_KRB5_CCACHE_NAME_X 1.2.752.43.13.16 +oid base GSS_KRB5_SET_TIME_OFFSET_X 1.2.752.43.13.17 +oid base GSS_KRB5_GET_TIME_OFFSET_X 1.2.752.43.13.18 +oid base GSS_KRB5_PLUGIN_REGISTER_X 1.2.752.43.13.19 +oid base GSS_NTLM_GET_SESSION_KEY_X 1.2.752.43.13.20 +oid base GSS_C_NT_NTLM 1.2.752.43.13.21 +oid base GSS_C_NT_DN 1.2.752.43.13.22 +oid base GSS_KRB5_NT_PRINCIPAL_NAME_REFERRAL 1.2.752.43.13.23 +oid base GSS_C_NTLM_AVGUEST 1.2.752.43.13.24 +oid base GSS_C_NTLM_V1 1.2.752.43.13.25 +oid base GSS_C_NTLM_V2 1.2.752.43.13.26 +oid base GSS_C_NTLM_SESSION_KEY 1.2.752.43.13.27 +oid base GSS_C_NTLM_FORCE_V1 1.2.752.43.13.28 +oid base GSS_KRB5_CRED_NO_CI_FLAGS_X 1.2.752.43.13.29 +oid base GSS_KRB5_IMPORT_CRED_X 1.2.752.43.13.30 +oid base GSS_KRB5_IMPORT_RFC4121_CONTEXT_X 1.2.752.43.13.31 + +# /* glue for gss_inquire_saslname_for_mech */ +oid base GSS_C_MA_SASL_MECH_NAME 1.2.752.43.13.100 +oid base GSS_C_MA_MECH_NAME 1.2.752.43.13.101 +oid base GSS_C_MA_MECH_DESCRIPTION 1.2.752.43.13.102 + +#/* Heimdal mechanisms - 1.2.752.43.14 */ + +oid base GSS_SASL_DIGEST_MD5_MECHANISM 1.2.752.43.14.1 +oid base GSS_NETLOGON_MECHANISM 1.2.752.43.14.2 +oid base GSS_NETLOGON_SET_SESSION_KEY_X 1.2.752.43.14.3 +oid base GSS_NETLOGON_SET_SIGN_ALGORITHM_X 1.2.752.43.14.4 +oid base GSS_NETLOGON_NT_NETBIOS_DNS_NAME 1.2.752.43.14.5 + +#/* GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X.128 */ +oid base GSS_C_INQ_WIN2K_PAC_X 1.2.752.43.13.3.128 +oid base GSS_C_INQ_SSPI_SESSION_KEY 1.2.840.113554.1.2.2.5.5 +oid base GSS_C_INQ_NEGOEX_KEY 1.2.840.113554.1.2.2.5.16 +oid base GSS_C_INQ_NEGOEX_VERIFY_KEY 1.2.840.113554.1.2.2.5.17 +oid base GSS_C_INQ_REQUIRE_MECHLIST_MIC 1.3.6.1.4.1.7165.655.1.2 + +#/* +# * "Standard" mechs +# */ + +oid base GSS_KRB5_MECHANISM 1.2.840.113554.1.2.2 +oid base GSS_NTLM_MECHANISM 1.3.6.1.4.1.311.2.2.10 +oid base GSS_SPNEGO_MECHANISM 1.3.6.1.5.5.2 + +# /* From Luke Howard */ + +oid base GSS_C_INQ_PEER_HAS_BUGGY_SPNEGO 1.3.6.1.4.1.5322.19.6 +oid base GSS_C_NTLM_RESET_CRYPTO 1.3.6.1.4.1.7165.655.1.3 +oid base GSS_NEGOEX_MECHANISM 1.3.6.1.4.1.311.2.2.30 +oid base GSS_SANON_X25519_MECHANISM 1.3.6.1.4.1.5322.26.1.110 + +#/* +# * OID mappings with name and short description and and slightly longer description +# */ + +desc mech GSS_KRB5_MECHANISM "Kerberos 5" "Heimdal Kerberos 5 mechanism" +desc mech GSS_NTLM_MECHANISM "NTLM" "Heimdal NTLM mechanism" +desc mech GSS_SPNEGO_MECHANISM "SPNEGO" "Heimdal SPNEGO mechanism" +desc mech GSS_SANON_X25519_MECHANISM "SAnon-X25519" "Heimdal Simple Anonymous (X25519) mechanism" + +desc ma GSS_C_MA_MECH_NAME "GSS mech name" "The name of the GSS-API mechanism" +desc ma GSS_C_MA_SASL_MECH_NAME "SASL mechanism name" "The name of the SASL mechanism" +desc ma GSS_C_MA_MECH_DESCRIPTION "Mech description" "The long description of the mechanism" + +#/* +# * RFC5587 +# */ + +oid base GSS_C_MA_MECH_CONCRETE 1.3.6.1.5.5.13.1 +oid base GSS_C_MA_MECH_PSEUDO 1.3.6.1.5.5.13.2 +oid base GSS_C_MA_MECH_COMPOSITE 1.3.6.1.5.5.13.3 +oid base GSS_C_MA_MECH_NEGO 1.3.6.1.5.5.13.4 +oid base GSS_C_MA_MECH_GLUE 1.3.6.1.5.5.13.5 +oid base GSS_C_MA_NOT_MECH 1.3.6.1.5.5.13.6 +oid base GSS_C_MA_DEPRECATED 1.3.6.1.5.5.13.7 +oid base GSS_C_MA_NOT_DFLT_MECH 1.3.6.1.5.5.13.8 +oid base GSS_C_MA_ITOK_FRAMED 1.3.6.1.5.5.13.9 +oid base GSS_C_MA_AUTH_INIT 1.3.6.1.5.5.13.10 +oid base GSS_C_MA_AUTH_TARG 1.3.6.1.5.5.13.11 +oid base GSS_C_MA_AUTH_INIT_INIT 1.3.6.1.5.5.13.12 +oid base GSS_C_MA_AUTH_TARG_INIT 1.3.6.1.5.5.13.13 +oid base GSS_C_MA_AUTH_INIT_ANON 1.3.6.1.5.5.13.14 +oid base GSS_C_MA_AUTH_TARG_ANON 1.3.6.1.5.5.13.15 +oid base GSS_C_MA_DELEG_CRED 1.3.6.1.5.5.13.16 +oid base GSS_C_MA_INTEG_PROT 1.3.6.1.5.5.13.17 +oid base GSS_C_MA_CONF_PROT 1.3.6.1.5.5.13.18 +oid base GSS_C_MA_MIC 1.3.6.1.5.5.13.19 +oid base GSS_C_MA_WRAP 1.3.6.1.5.5.13.20 +oid base GSS_C_MA_PROT_READY 1.3.6.1.5.5.13.21 +oid base GSS_C_MA_REPLAY_DET 1.3.6.1.5.5.13.22 +oid base GSS_C_MA_OOS_DET 1.3.6.1.5.5.13.23 +oid base GSS_C_MA_CBINDINGS 1.3.6.1.5.5.13.24 +oid base GSS_C_MA_PFS 1.3.6.1.5.5.13.25 +oid base GSS_C_MA_COMPRESS 1.3.6.1.5.5.13.26 +oid base GSS_C_MA_CTX_TRANS 1.3.6.1.5.5.13.27 +oid base GSS_C_MA_NEGOEX_AND_SPNEGO 1.2.840.113554.1.2.2.5.18 + +desc ma GSS_C_MA_MECH_CONCRETE "concrete-mech" "Indicates that a mech is neither a pseudo-mechanism nor a composite mechanism" +desc ma GSS_C_MA_MECH_PSEUDO "pseudo-mech" "" +desc ma GSS_C_MA_MECH_COMPOSITE "composite-mech" "" +desc ma GSS_C_MA_MECH_NEGO "mech-negotiation-mech" "" +desc ma GSS_C_MA_MECH_GLUE "mech-glue" "" +desc ma GSS_C_MA_NOT_MECH "not-mech" "" +desc ma GSS_C_MA_DEPRECATED "mech-deprecated" "" +desc ma GSS_C_MA_NOT_DFLT_MECH "mech-not-default" "" +desc ma GSS_C_MA_ITOK_FRAMED "initial-is-framed" "" +desc ma GSS_C_MA_AUTH_INIT "auth-init-princ" "" +desc ma GSS_C_MA_AUTH_TARG "auth-targ-princ" "" +desc ma GSS_C_MA_AUTH_INIT_INIT "auth-init-princ-initial" "" +desc ma GSS_C_MA_AUTH_TARG_INIT "auth-targ-princ-initial" "" +desc ma GSS_C_MA_AUTH_INIT_ANON "auth-init-princ-anon" "" +desc ma GSS_C_MA_AUTH_TARG_ANON "auth-targ-princ-anon" "" +desc ma GSS_C_MA_DELEG_CRED "deleg-cred" "" +desc ma GSS_C_MA_INTEG_PROT "integ-prot" "" +desc ma GSS_C_MA_CONF_PROT "conf-prot" "" +desc ma GSS_C_MA_MIC "mic" "" +desc ma GSS_C_MA_WRAP "wrap" "" +desc ma GSS_C_MA_PROT_READY "prot-ready" "" +desc ma GSS_C_MA_REPLAY_DET "replay-detection" "" +desc ma GSS_C_MA_OOS_DET "oos-detection" "" +desc ma GSS_C_MA_CBINDINGS "channel-bindings" "" +desc ma GSS_C_MA_PFS "pfs" "" +desc ma GSS_C_MA_COMPRESS "compress" "" +desc ma GSS_C_MA_CTX_TRANS "context-transfer" "" +desc ma GSS_C_MA_NEGOEX_AND_SPNEGO "negoex-and-spnego" "Indicates that a mechanism supports both NegoEx and SPNEGO" diff --git a/third_party/heimdal/lib/gssapi/sanon/accept_sec_context.c b/third_party/heimdal/lib/gssapi/sanon/accept_sec_context.c new file mode 100644 index 0000000..72cbe09 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/accept_sec_context.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_accept_sec_context(OM_uint32 *minor, + gss_ctx_id_t *context_handle, + gss_const_cred_id_t verifier_cred_handle, + const gss_buffer_t input_token, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle) +{ + static gss_buffer_desc empty = GSS_C_EMPTY_BUFFER; + OM_uint32 major, tmp; + sanon_ctx sc = (sanon_ctx)*context_handle; + gss_buffer_desc mech_input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc initiator_pk = GSS_C_EMPTY_BUFFER; + gss_buffer_desc hok_mic = GSS_C_EMPTY_BUFFER; + gss_buffer_desc session_key = GSS_C_EMPTY_BUFFER; + OM_uint32 req_flags = 0; + + if (output_token == GSS_C_NO_BUFFER) { + *minor = EINVAL; + major = GSS_S_FAILURE; + goto out; + } + + _mg_buffer_zero(output_token); + + if (input_token == GSS_C_NO_BUFFER) { + major = GSS_S_DEFECTIVE_TOKEN; + goto out; + } else if (sc != NULL) { + major = GSS_S_BAD_STATUS; + goto out; + } + + major = gss_decapsulate_token(input_token, + GSS_SANON_X25519_MECHANISM, + &mech_input_token); + if (major != GSS_S_COMPLETE) + goto out; + + sc = calloc(1, sizeof(*sc)); + if (sc == NULL) { + *minor = ENOMEM; + major = GSS_S_FAILURE; + goto out; + } + + /* initiator token can include optional 64-bit flags */ + if (mech_input_token.length != crypto_scalarmult_curve25519_BYTES && + mech_input_token.length != crypto_scalarmult_curve25519_BYTES + 8) { + *minor = 0; + major = GSS_S_DEFECTIVE_TOKEN; + goto out; + } + + initiator_pk = mech_input_token; + initiator_pk.length = crypto_scalarmult_curve25519_BYTES; + + /* compute public and secret keys */ + major = _gss_sanon_curve25519_base(minor, sc); + if (major != GSS_S_COMPLETE) + goto out; + + if (mech_input_token.length > crypto_scalarmult_curve25519_BYTES) { + /* extra flags */ + uint8_t *p = (uint8_t *)mech_input_token.value + crypto_scalarmult_curve25519_BYTES; + uint32_t dummy; + + _gss_mg_decode_be_uint32(p, &dummy); /* upper 32 bits presently unused */ + _gss_mg_decode_be_uint32(&p[4], &req_flags); + } + + /* compute shared secret */ + major = _gss_sanon_curve25519(minor, sc, &initiator_pk, req_flags, + input_chan_bindings, &session_key); + if (major != GSS_S_COMPLETE) + goto out; + + /* do not let initiator set any other flags */ + req_flags &= SANON_PROTOCOL_FLAG_MASK; + + req_flags |= GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | + GSS_C_INTEG_FLAG | GSS_C_ANON_FLAG | GSS_C_TRANS_FLAG | + GSS_C_CHANNEL_BOUND_FLAG; /* CB part of KDF, so always validated */ + + major = _gss_sanon_import_rfc4121_context(minor, sc, req_flags, &session_key); + if (major != GSS_S_COMPLETE) + goto out; + + major = _gss_sanon_get_mic(minor, (gss_const_ctx_id_t)sc, + GSS_C_QOP_DEFAULT, &empty, &hok_mic); + if (major != GSS_S_COMPLETE) + goto out; + + output_token->length = sizeof(sc->pk) + hok_mic.length; + output_token->value = malloc(output_token->length); + if (output_token->value == NULL) { + output_token->length = 0; + *minor = ENOMEM; + major = GSS_S_FAILURE; + goto out; + } + + memcpy(output_token->value, sc->pk, sizeof(sc->pk)); + memcpy((uint8_t *)output_token->value + sizeof(sc->pk), hok_mic.value, hok_mic.length); + + major = GSS_S_COMPLETE; + + *context_handle = (gss_ctx_id_t)sc; + + if (src_name) + *src_name = _gss_sanon_anonymous_identity; + if (ret_flags) + *ret_flags = req_flags; + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + +out: + if (mech_type) + *mech_type = GSS_SANON_X25519_MECHANISM; + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + if (GSS_ERROR(major)) { + _gss_sanon_delete_sec_context(&tmp, (gss_ctx_id_t *)&sc, GSS_C_NO_BUFFER); + *context_handle = GSS_C_NO_CONTEXT; + } + gss_release_buffer(&tmp, &mech_input_token); + gss_release_buffer(&tmp, &hok_mic); + _gss_secure_release_buffer(&tmp, &session_key); + + return major; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/acquire_cred.c b/third_party/heimdal/lib/gssapi/sanon/acquire_cred.c new file mode 100644 index 0000000..7aedd3e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/acquire_cred.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +/* SAnon credential handles are aliases of their underyling name */ + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_acquire_cred_from(OM_uint32 *minor, + gss_const_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_stor, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + *minor = 0; + + if (desired_name == GSS_C_NO_NAME || + desired_name == _gss_sanon_anonymous_identity) + *output_cred_handle = _gss_sanon_anonymous_cred; + else + *output_cred_handle = _gss_sanon_non_anonymous_cred; + + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/add_cred.c b/third_party/heimdal/lib/gssapi/sanon/add_cred.c new file mode 100644 index 0000000..f1dfeba --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/add_cred.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_add_cred_from(OM_uint32 *minor, + gss_cred_id_t input_cred_handle, + gss_const_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + *minor = 0; + + if (output_cred_handle != NULL) { + if (desired_name == GSS_C_NO_NAME || + desired_name == _gss_sanon_anonymous_identity) + *output_cred_handle = _gss_sanon_anonymous_cred; + else + *output_cred_handle = _gss_sanon_non_anonymous_cred; + } + + if (initiator_time_rec) + *initiator_time_rec = GSS_C_INDEFINITE; + if (acceptor_time_rec) + *acceptor_time_rec = GSS_C_INDEFINITE; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/canonicalize_name.c b/third_party/heimdal/lib/gssapi/sanon/canonicalize_name.c new file mode 100644 index 0000000..fa1ade0 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/canonicalize_name.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_canonicalize_name(OM_uint32 *minor, + gss_const_name_t src_name, + const gss_OID mech_type, + gss_name_t *dest_name) +{ + *minor = 0; + + if (src_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + *dest_name = (gss_name_t)src_name; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/compare_name.c b/third_party/heimdal/lib/gssapi/sanon/compare_name.c new file mode 100644 index 0000000..85b13b2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/compare_name.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_compare_name(OM_uint32 *minor, + gss_const_name_t name1, + gss_const_name_t name2, + int *name_equal) +{ + *minor = 0; + + /* + * RFC 2743 Section 2.4.3: + * If either name presented to GSS_Compare_name() denotes + * an anonymous principal, GSS_Compare_name() shall indicate + * FALSE + * + * We also have to apply the same logic to non-anonymous + * names as we erase their contents. + */ + *name_equal = FALSE; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/context_time.c b/third_party/heimdal/lib/gssapi/sanon/context_time.c new file mode 100644 index 0000000..338f3ac --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/context_time.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_context_time(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + OM_uint32 *time_rec) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + *minor = 0; + *time_rec = GSS_C_INDEFINITE; + + if (sc == NULL) + return GSS_S_NO_CONTEXT; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/crypto.c b/third_party/heimdal/lib/gssapi/sanon/crypto.c new file mode 100644 index 0000000..0c7a67f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/crypto.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_wrap(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_wrap(minor, sc->rfc4121, + conf_req_flag, qop_req, + input_message_buffer, conf_state, + output_message_buffer); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_wrap_size_limit(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_wrap_size_limit(minor, sc->rfc4121, + conf_req_flag, qop_req, + req_output_size, max_input_size); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_wrap_iov(OM_uint32 *minor, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_wrap_iov(minor, sc->rfc4121, + conf_req_flag, qop_req, + conf_state, iov, iov_count); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_wrap_iov_length(OM_uint32 *minor, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_wrap_iov_length(minor, sc->rfc4121, + conf_req_flag, qop_req, + conf_state, iov, iov_count); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_unwrap(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t * qop_state) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_unwrap(minor, sc->rfc4121, + input_message_buffer, output_message_buffer, + conf_state, qop_state); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_unwrap_iov(OM_uint32 *minor, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_unwrap_iov(minor, sc->rfc4121, + conf_state, qop_state, + iov, iov_count); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_get_mic(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_get_mic(minor, sc->rfc4121, + qop_req, message_buffer, + message_token); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_verify_mic(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_verify_mic(minor, sc->rfc4121, + message_buffer, token_buffer, + qop_state); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_pseudo_random(OM_uint32 *minor, + gss_ctx_id_t context_handle, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = GSS_KRB5_S_KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + return gss_pseudo_random(minor, sc->rfc4121, + prf_key, prf_in, desired_output_len, + prf_out); +} + +/* + * Generate a curve25519 secret and public key + */ + +OM_uint32 +_gss_sanon_curve25519_base(OM_uint32 *minor, sanon_ctx sc) +{ + krb5_generate_random_block(sc->sk, crypto_scalarmult_curve25519_BYTES); + + if (crypto_scalarmult_curve25519_base(sc->pk, sc->sk) != 0) { + *minor = EINVAL; + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; +} + +/* + * Derive the context session key using SP800-108 KDF in HMAC mode + * and the public keys and channel binding data. + */ + +OM_uint32 +_gss_sanon_curve25519(OM_uint32 *minor, + sanon_ctx sc, + gss_buffer_t pk, + OM_uint32 gss_flags, + const gss_channel_bindings_t input_chan_bindings, + gss_buffer_t session_key) +{ + uint8_t shared[crypto_scalarmult_curve25519_BYTES], *p; + krb5_error_code ret; + krb5_context context; + krb5_data kdf_K1, kdf_label, kdf_context, keydata; + + _mg_buffer_zero(session_key); + + if (pk == GSS_C_NO_BUFFER || pk->length != crypto_scalarmult_curve25519_BYTES) + return GSS_S_DEFECTIVE_TOKEN; + + if (crypto_scalarmult_curve25519(shared, sc->sk, pk->value) != 0) + return GSS_S_FAILURE; + + ret = krb5_init_context(&context); + if (ret != 0) { + *minor = ret; + return GSS_S_FAILURE; + } + + kdf_K1.data = shared; + kdf_K1.length = sizeof(shared); + + kdf_label.data = "sanon-x25519"; + kdf_label.length = sizeof("sanon-x25519") - 1; + + ret = krb5_data_alloc(&kdf_context, + 2 * crypto_scalarmult_curve25519_BYTES + 8 + + (input_chan_bindings ? input_chan_bindings->application_data.length : 0)); + if (ret != 0) { + krb5_free_context(context); + *minor = ret; + return GSS_S_FAILURE; + } + + p = kdf_context.data; + + if (sc->is_initiator) { + memcpy(p, sc->pk, sizeof(sc->pk)); + memcpy(&p[pk->length], pk->value, pk->length); + } else { + memcpy(p, pk->value, pk->length); + memcpy(&p[sizeof(sc->pk)], sc->pk, sizeof(sc->pk)); + } + p += 2 * crypto_scalarmult_curve25519_BYTES; + _gss_mg_encode_be_uint32(0, p); /* upper 32 bits presently unused */ + p += 4; + _gss_mg_encode_be_uint32(gss_flags, p); + p += 4; + + if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS && + input_chan_bindings->application_data.value != NULL) { + memcpy(p, input_chan_bindings->application_data.value, + input_chan_bindings->application_data.length); + } + + ret = krb5_data_alloc(&keydata, 16); + if (ret == 0) { + ret = _krb5_SP800_108_HMAC_KDF(context, &kdf_K1, &kdf_label, + &kdf_context, EVP_sha256(), &keydata); + + session_key->length = keydata.length; + session_key->value = keydata.data; + } else { + krb5_data_free(&keydata); + } + + memset_s(kdf_context.data, kdf_context.length, 0, kdf_context.length); + krb5_data_free(&kdf_context); + + memset_s(shared, sizeof(shared), 0, sizeof(shared)); + + krb5_free_context(context); + + *minor = ret; + return ret != 0 ? GSS_S_FAILURE : GSS_S_COMPLETE; +} + +OM_uint32 +_gss_sanon_import_rfc4121_context(OM_uint32 *minor, + sanon_ctx sc, + OM_uint32 gss_flags, + gss_const_buffer_t session_key) +{ + return _gss_mg_import_rfc4121_context(minor, sc->is_initiator, gss_flags, + KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128, + session_key, &sc->rfc4121); +} + diff --git a/third_party/heimdal/lib/gssapi/sanon/delete_sec_context.c b/third_party/heimdal/lib/gssapi/sanon/delete_sec_context.c new file mode 100644 index 0000000..fdb8a85 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/delete_sec_context.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_delete_sec_context(OM_uint32 *minor, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token) +{ + sanon_ctx sc; + + *minor = 0; + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + if (*context_handle == GSS_C_NO_CONTEXT) + return GSS_S_COMPLETE; + + sc = (sanon_ctx)*context_handle; + + *context_handle = GSS_C_NO_CONTEXT; + + gss_delete_sec_context(minor, &sc->rfc4121, GSS_C_NO_BUFFER); + + memset_s(sc, sizeof(*sc), 0, sizeof(*sc)); + free(sc); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/display_name.c b/third_party/heimdal/lib/gssapi/sanon/display_name.c new file mode 100644 index 0000000..1bd55f3 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/display_name.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_display_name(OM_uint32 *minor, + gss_const_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type) +{ + *minor = 0; + + if (input_name != _gss_sanon_anonymous_identity) + return GSS_S_BAD_NAME; + + if (output_name_type) + *output_name_type = GSS_C_NT_ANONYMOUS; + + return _gss_copy_buffer(minor, _gss_sanon_wellknown_user_name, + output_name_buffer); +} diff --git a/third_party/heimdal/lib/gssapi/sanon/display_status.c b/third_party/heimdal/lib/gssapi/sanon/display_status.c new file mode 100644 index 0000000..4e039c6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/display_status.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1998 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_display_status(OM_uint32 *minor, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + _mg_buffer_zero(status_string); + + if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && + gss_oid_equal(mech_type, GSS_SANON_X25519_MECHANISM) == 0) { + *minor = 0; + return GSS_S_BAD_MECH; + } + + if (status_type == GSS_C_MECH_CODE) { + return gss_display_status(minor, status_value, + GSS_C_MECH_CODE, GSS_KRB5_MECHANISM, + message_context, status_string); + } else { + *minor = EINVAL; + return GSS_S_BAD_STATUS; + } +} diff --git a/third_party/heimdal/lib/gssapi/sanon/duplicate_cred.c b/third_party/heimdal/lib/gssapi/sanon/duplicate_cred.c new file mode 100644 index 0000000..8c5c5d8 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/duplicate_cred.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_duplicate_cred(OM_uint32 *minor, + gss_const_cred_id_t input_cred_handle, + gss_cred_id_t *output_cred_handle) +{ + *minor = 0; + *output_cred_handle = (gss_cred_id_t)input_cred_handle; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/duplicate_name.c b/third_party/heimdal/lib/gssapi/sanon/duplicate_name.c new file mode 100644 index 0000000..698e83d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/duplicate_name.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_duplicate_name(OM_uint32 *minor, + gss_const_name_t src_name, + gss_name_t *dest_name) +{ + *minor = 0; + *dest_name = (gss_name_t)src_name; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/export_cred.c b/third_party/heimdal/lib/gssapi/sanon/export_cred.c new file mode 100644 index 0000000..06c2458 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/export_cred.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_export_cred(OM_uint32 *minor, + gss_cred_id_t input_cred, + gss_buffer_t token) +{ + return _gss_sanon_export_name(minor, (gss_name_t)input_cred, token); +} diff --git a/third_party/heimdal/lib/gssapi/sanon/export_name.c b/third_party/heimdal/lib/gssapi/sanon/export_name.c new file mode 100644 index 0000000..474c58c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/export_name.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_export_name(OM_uint32 *minor, + gss_const_name_t input_name, + gss_buffer_t exported_name) +{ + uint8_t is_anonymous; + + *minor = 0; + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + is_anonymous = input_name == _gss_sanon_anonymous_identity; + if (!is_anonymous) + return GSS_S_BAD_NAME; + + return gss_mg_export_name(minor, GSS_SANON_X25519_MECHANISM, + &is_anonymous, 1, exported_name); +} diff --git a/third_party/heimdal/lib/gssapi/sanon/export_sec_context.c b/third_party/heimdal/lib/gssapi/sanon/export_sec_context.c new file mode 100644 index 0000000..52ba6fb --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/export_sec_context.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_export_sec_context(OM_uint32 *minor, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token) +{ + OM_uint32 major; + const sanon_ctx sc = (sanon_ctx)*context_handle; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + _mg_buffer_zero(interprocess_token); + *minor = 0; + return GSS_S_UNAVAILABLE; + } + + major = gss_export_sec_context(minor, &sc->rfc4121, interprocess_token); + if (major == GSS_S_COMPLETE) + _gss_sanon_delete_sec_context(minor, context_handle, GSS_C_NO_BUFFER); + return major; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/external.c b/third_party/heimdal/lib/gssapi/sanon/external.c new file mode 100644 index 0000000..8812f9e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/external.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2006-2020 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "sanon_locl.h" + +static uint8_t anonymous_identity; +gss_name_t +_gss_sanon_anonymous_identity = (gss_name_t)&anonymous_identity; +gss_cred_id_t +_gss_sanon_anonymous_cred = (gss_cred_id_t)&anonymous_identity; + +static uint8_t non_anonymous_identity; +gss_name_t +_gss_sanon_non_anonymous_identity = (gss_name_t)&non_anonymous_identity; +gss_cred_id_t +_gss_sanon_non_anonymous_cred = (gss_cred_id_t)&non_anonymous_identity; + +static gss_buffer_desc wellknown_user_name = { + SANON_WELLKNOWN_USER_NAME_LEN, + SANON_WELLKNOWN_USER_NAME +}; +gss_buffer_t +_gss_sanon_wellknown_user_name = &wellknown_user_name; + +static gss_buffer_desc wellknown_service_name = { + SANON_WELLKNOWN_SERVICE_NAME_LEN, + SANON_WELLKNOWN_SERVICE_NAME +}; +gss_buffer_t +_gss_sanon_wellknown_service_name = &wellknown_service_name; + +static gss_mo_desc sanon_mo[] = { + { + GSS_C_MA_MECH_NAME, + GSS_MO_MA, + "Mechanism name", + rk_UNCONST("SANON-X25519"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_DESCRIPTION, + GSS_MO_MA, + "Mechanism description", + rk_UNCONST("Heimdal Simple Anonymous (X25519) Mechanism"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_CONCRETE, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_ITOK_FRAMED, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_AUTH_INIT_ANON, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_AUTH_TARG_ANON, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_INTEG_PROT, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_CONF_PROT, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_MIC, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_WRAP, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_REPLAY_DET, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_OOS_DET, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_CBINDINGS, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_PFS, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_CTX_TRANS, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_NEGOEX_AND_SPNEGO, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + } +}; + +static gssapi_mech_interface_desc sanon_mech = { + GMI_VERSION, + "sanon-x25519", + { 10, rk_UNCONST("\x2b\x06\x01\x04\x01\xa9\x4a\x1a\x01\x6e") }, + 0, + NULL, + _gss_sanon_release_cred, + _gss_sanon_init_sec_context, + _gss_sanon_accept_sec_context, + _gss_sanon_process_context_token, + _gss_sanon_delete_sec_context, + _gss_sanon_context_time, + _gss_sanon_get_mic, + _gss_sanon_verify_mic, + _gss_sanon_wrap, + _gss_sanon_unwrap, + _gss_sanon_display_status, + NULL, /* gm_indicate_mechs */ + _gss_sanon_compare_name, + _gss_sanon_display_name, + _gss_sanon_import_name, + _gss_sanon_export_name, + _gss_sanon_release_name, + _gss_sanon_inquire_cred, + _gss_sanon_inquire_context, + _gss_sanon_wrap_size_limit, + NULL, /* gm_add_cred */ + _gss_sanon_inquire_cred_by_mech, + _gss_sanon_export_sec_context, + _gss_sanon_import_sec_context, + _gss_sanon_inquire_names_for_mech, + _gss_sanon_inquire_mechs_for_name, + _gss_sanon_canonicalize_name, + _gss_sanon_duplicate_name, + _gss_sanon_inquire_sec_context_by_oid, + NULL, /* gm_inquire_cred_by_oid */ + NULL, /* gm_set_sec_context_option */ + NULL, /* gm_set_cred_option */ + _gss_sanon_pseudo_random, + _gss_sanon_wrap_iov, + _gss_sanon_unwrap_iov, + _gss_sanon_wrap_iov_length, + NULL, /* gm_store_cred */ + _gss_sanon_export_cred, + _gss_sanon_import_cred, + _gss_sanon_acquire_cred_from, + NULL, /* gm_acquire_cred_impersonate_name */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + sanon_mo, + sizeof(sanon_mo) / sizeof(sanon_mo[0]), + NULL, /* gm_localname */ + NULL, /* gm_authorize_localname */ + NULL, /* gm_display_name_ext */ + NULL, /* gm_inquire_name */ + NULL, /* gm_get_name_attribute */ + NULL, /* gm_set_name_attribute */ + NULL, /* gm_delete_name_attribute */ + NULL, /* gm_export_name_composite */ + _gss_sanon_duplicate_cred, + _gss_sanon_add_cred_from, + NULL, /* gm_store_cred_into */ + _gssspi_sanon_query_mechanism_info, + _gssspi_sanon_query_meta_data, + _gssspi_sanon_exchange_meta_data, + NULL, /* gm_store_cred_into2 */ + NULL, /* gm_compat */ +}; + +gssapi_mech_interface +__gss_sanon_initialize(void) +{ + return &sanon_mech; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/import_cred.c b/third_party/heimdal/lib/gssapi/sanon/import_cred.c new file mode 100644 index 0000000..4266ef1 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/import_cred.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_import_cred(OM_uint32 *minor, + gss_buffer_t token, + gss_cred_id_t *cred_handle) +{ + return _gss_sanon_import_name(minor, token, + GSS_C_NT_EXPORT_NAME, + (gss_name_t *)cred_handle); +} diff --git a/third_party/heimdal/lib/gssapi/sanon/import_name.c b/third_party/heimdal/lib/gssapi/sanon/import_name.c new file mode 100644 index 0000000..1a228b6 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/import_name.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +static int +is_anonymous_identity_p(gss_buffer_t name_string, gss_OID name_type) +{ + if (gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)) + return TRUE; + else if ((name_type == GSS_C_NO_OID || + gss_oid_equal(name_type, GSS_C_NT_USER_NAME) || + gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) && + buffer_equal_p(name_string, _gss_sanon_wellknown_user_name)) + return TRUE; + else if (gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) && + buffer_equal_p(name_string, _gss_sanon_wellknown_service_name)) + return TRUE; + + return FALSE; +} + +static krb5_error_code +storage_ret_der_oid(krb5_storage *sp, gss_OID_desc *oid) +{ + krb5_error_code ret; + uint16_t der_oid_len; + uint8_t oid_len, tag; + + oid->length = 0; + oid->elements = NULL; + + ret = krb5_ret_uint16(sp, &der_oid_len); + if (ret == 0) + ret = krb5_ret_uint8(sp, &tag); + if (ret == 0) + ret = krb5_ret_uint8(sp, &oid_len); + if (ret) + return ret; + if (tag != 0x06) + return EINVAL; + + if (der_oid_len != 2 + oid_len) + return EINVAL; + + oid->elements = malloc(oid_len); + if (oid->elements == NULL) + return ENOMEM; + + if (krb5_storage_read(sp, oid->elements, oid_len) != oid_len) { + free(oid->elements); + oid->elements = NULL; + oid->length = 0; + return EINVAL; + } + + oid->length = oid_len; + + return 0; +} + +static OM_uint32 +import_export_name(OM_uint32 *minor, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + OM_uint32 major; + krb5_error_code ret; + krb5_storage *sp; + uint32_t name_len = 0; + uint16_t tok_id; + gss_OID_desc oid_buf = { 0, NULL }; + uint8_t is_anonymous; + + sp = krb5_storage_from_readonly_mem(input_name_buffer->value, + input_name_buffer->length); + if (sp == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + major = GSS_S_BAD_NAME; + *minor = 0; + + ret = krb5_ret_uint16(sp, &tok_id); + if (ret == 0 && tok_id != 0x0401) + ret = EINVAL; + if (ret == 0) + ret = storage_ret_der_oid(sp, &oid_buf); + if (ret == 0) { + if (!gss_oid_equal(&oid_buf, GSS_SANON_X25519_MECHANISM)) + ret = EINVAL; + free(oid_buf.elements); + } + if (ret == 0) + ret = krb5_ret_uint32(sp, &name_len); + if (ret == 0) + ret = krb5_ret_uint8(sp, &is_anonymous); + if (ret == 0) { + if (name_len != 1) + ret = EINVAL; + if (is_anonymous == 1) { + *output_name = _gss_sanon_anonymous_identity; + major = GSS_S_COMPLETE; + } else { + major = GSS_S_BAD_NAME; + } + } + + krb5_storage_free(sp); + + if (*minor == 0) + *minor = ret; + + return major; +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_import_name(OM_uint32 *minor, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t *output_name) +{ + if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) + return import_export_name(minor, input_name_buffer, output_name); + + *minor = 0; + *output_name = + is_anonymous_identity_p(input_name_buffer, input_name_type) ? + _gss_sanon_anonymous_identity : _gss_sanon_non_anonymous_identity; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/import_sec_context.c b/third_party/heimdal/lib/gssapi/sanon/import_sec_context.c new file mode 100644 index 0000000..9aa682a --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/import_sec_context.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_import_sec_context(OM_uint32 *minor, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle) +{ + OM_uint32 major = GSS_S_FAILURE; + sanon_ctx sc; + + *minor = ENOMEM; + *context_handle = GSS_C_NO_CONTEXT; + + if ((sc = calloc(1, sizeof(*sc))) && + (major = gss_import_sec_context(minor, + interprocess_token, + &sc->rfc4121)) == GSS_S_COMPLETE) { + *context_handle = (gss_ctx_id_t)sc; + sc = NULL; + } + + free(sc); + return major; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/init_sec_context.c b/third_party/heimdal/lib/gssapi/sanon/init_sec_context.c new file mode 100644 index 0000000..4c199ed --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/init_sec_context.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +int +_gss_sanon_available_p(gss_const_cred_id_t claimant_cred_handle, + gss_const_name_t target_name, + OM_uint32 req_flags) +{ + OM_uint32 minor; + gss_name_t initiator_name = GSS_C_NO_NAME; + int available; + + if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) { + _gss_sanon_inquire_cred(&minor, claimant_cred_handle, + &initiator_name, NULL, NULL, NULL); + heim_assert(initiator_name != GSS_C_NO_NAME, + "Invalid null SAnon initiator name"); + } + + /* + * SAnon is available if one of the following is true: + * + * The caller set anon_req_flag (GSS_C_ANON_FLAG) + * The claimant_cred_handle identity is anonymous + * The claimant_cred_handle is the default credential + * and target_name is anonymous + */ + if (req_flags & GSS_C_ANON_FLAG) + available = TRUE; + else if (initiator_name == _gss_sanon_anonymous_identity) + available = TRUE; + else if (claimant_cred_handle == GSS_C_NO_CREDENTIAL && + target_name == _gss_sanon_anonymous_identity) + available = TRUE; + else + available = FALSE; + + _gss_sanon_release_name(&minor, &initiator_name); + return available; +} + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_init_sec_context(OM_uint32 *minor, + gss_const_cred_id_t cred_handle, + gss_ctx_id_t *context_handle, + gss_const_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID *actual_mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec) +{ + gss_buffer_desc mech_token = GSS_C_EMPTY_BUFFER; + OM_uint32 major, tmp; + sanon_ctx sc = (sanon_ctx)*context_handle; + OM_uint32 flags; + gss_buffer_desc session_key = GSS_C_EMPTY_BUFFER; + + *minor = 0; + _mg_buffer_zero(output_token); + + if (!_gss_sanon_available_p(cred_handle, target_name, req_flags)) { + major = GSS_S_UNAVAILABLE; + goto out; + } + + /* we always support the following flags */ + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | + GSS_C_INTEG_FLAG | GSS_C_ANON_FLAG; + /* we support the following optional flags */ + flags |= req_flags & SANON_PROTOCOL_FLAG_MASK; + + if (sc == NULL) { + uint8_t pk_and_flags[crypto_scalarmult_curve25519_BYTES + 8]; + + if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) { + major = GSS_S_DEFECTIVE_TOKEN; + goto out; + } + + sc = calloc(1, sizeof(*sc)); + if (sc == NULL) { + *minor = ENOMEM; + major = GSS_S_FAILURE; + goto out; + } + + sc->is_initiator = 1; + + /* compute public and secret keys */ + major = _gss_sanon_curve25519_base(minor, sc); + if (major != GSS_S_COMPLETE) + goto out; + + if (flags & SANON_PROTOCOL_FLAG_MASK) { + memcpy(pk_and_flags, sc->pk, sizeof(sc->pk)); + _gss_mg_encode_be_uint32(0, &pk_and_flags[sizeof(sc->pk)]); + _gss_mg_encode_be_uint32(flags & SANON_PROTOCOL_FLAG_MASK, + &pk_and_flags[sizeof(sc->pk) + 4]); + mech_token.length = sizeof(pk_and_flags); + mech_token.value = pk_and_flags; + } else { + mech_token.length = sizeof(sc->pk); + mech_token.value = sc->pk; + } + + /* send public key to acceptor */ + major = gss_encapsulate_token(&mech_token, + GSS_SANON_X25519_MECHANISM, + output_token); + if (major != GSS_S_COMPLETE) + goto out; + + *context_handle = (gss_ctx_id_t)sc; + major = GSS_S_CONTINUE_NEEDED; + } else { + static gss_buffer_desc empty = GSS_C_EMPTY_BUFFER; + gss_buffer_desc pk, hok_mic; + + if (input_token == GSS_C_NO_BUFFER || + input_token->length < crypto_scalarmult_curve25519_BYTES) { + major = GSS_S_DEFECTIVE_TOKEN; + goto out; + } else if (sc->rfc4121 != GSS_C_NO_CONTEXT || !(sc->is_initiator)) { + major = GSS_S_BAD_STATUS; + goto out; + } + + pk.length = crypto_scalarmult_curve25519_BYTES; + pk.value = input_token->value; + + /* compute shared secret */ + major = _gss_sanon_curve25519(minor, sc, &pk, + flags & SANON_PROTOCOL_FLAG_MASK, + input_chan_bindings, &session_key); + if (major != GSS_S_COMPLETE) + goto out; + + flags |= GSS_C_TRANS_FLAG; + + major = _gss_sanon_import_rfc4121_context(minor, sc, flags, &session_key); + if (major != GSS_S_COMPLETE) + goto out; + + /* verify holder of key MIC */ + hok_mic.length = input_token->length - pk.length; + hok_mic.value = (uint8_t *)input_token->value + pk.length; + + major = _gss_sanon_verify_mic(minor, (gss_const_ctx_id_t)sc, + &empty, &hok_mic, NULL); + if (major != GSS_S_COMPLETE) + goto out; + } + + if (ret_flags) + *ret_flags = flags; + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + +out: + if (actual_mech_type) + *actual_mech_type = GSS_SANON_X25519_MECHANISM; + + if (GSS_ERROR(major)) { + _gss_sanon_delete_sec_context(&tmp, (gss_ctx_id_t *)&sc, GSS_C_NO_BUFFER); + *context_handle = GSS_C_NO_CONTEXT; + } + _gss_secure_release_buffer(&tmp, &session_key); + + return major; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/inquire_context.c b/third_party/heimdal/lib/gssapi/sanon/inquire_context.c new file mode 100644 index 0000000..f5aa727 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/inquire_context.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_inquire_context(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *open_context) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + OM_uint32 major = GSS_S_COMPLETE; + + *minor = 0; + + if (sc == NULL) + return GSS_S_NO_CONTEXT; + + if (src_name) + *src_name = _gss_sanon_anonymous_identity; + if (targ_name) + *targ_name = _gss_sanon_anonymous_identity; + if (lifetime_rec) + *lifetime_rec = GSS_C_INDEFINITE; + if (mech_type) + *mech_type = GSS_SANON_X25519_MECHANISM; + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + if (locally_initiated) + *locally_initiated = sc->is_initiator; + if (open_context) + *open_context = 0; + if (ctx_flags) + *ctx_flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_ANON_FLAG; + } else { + major = gss_inquire_context(minor, sc->rfc4121, NULL, NULL, NULL, + NULL, ctx_flags, locally_initiated, + open_context); + } + return major; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/inquire_cred.c b/third_party/heimdal/lib/gssapi/sanon/inquire_cred.c new file mode 100644 index 0000000..b25ff2f --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/inquire_cred.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +_gss_sanon_inquire_cred(OM_uint32 *minor, + gss_const_cred_id_t cred_handle, + gss_name_t *name_ret, + OM_uint32 *lifetime, + gss_cred_usage_t *cred_usage, + gss_OID_set *mechanisms) +{ + *minor = 0; + + if (cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_NO_CRED; + + /* the credential handle is a reference to the cred name */ + if (name_ret) + *name_ret = (gss_name_t)cred_handle; + if (lifetime) + *lifetime = GSS_C_INDEFINITE; + if (cred_usage) + *cred_usage = GSS_C_BOTH; + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/inquire_cred_by_mech.c b/third_party/heimdal/lib/gssapi/sanon/inquire_cred_by_mech.c new file mode 100644 index 0000000..4f8bf66 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/inquire_cred_by_mech.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2003, 2006, 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_inquire_cred_by_mech(OM_uint32 *minor, + gss_const_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t *name, + OM_uint32 *initiator_lifetime, + OM_uint32 *acceptor_lifetime, + gss_cred_usage_t *cred_usage) +{ + gss_cred_usage_t usage; + OM_uint32 major; + OM_uint32 lifetime; + + major = _gss_sanon_inquire_cred(minor, cred_handle, + name, &lifetime, &usage, NULL); + if (major) + return major; + + if (initiator_lifetime) { + if (usage == GSS_C_INITIATE || usage == GSS_C_BOTH) + *initiator_lifetime = lifetime; + else + *initiator_lifetime = 0; + } + + if (acceptor_lifetime) { + if (usage == GSS_C_ACCEPT || usage == GSS_C_BOTH) + *acceptor_lifetime = lifetime; + else + *acceptor_lifetime = 0; + } + + if (cred_usage) + *cred_usage = usage; + + *minor = 0; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/inquire_mechs_for_name.c b/third_party/heimdal/lib/gssapi/sanon/inquire_mechs_for_name.c new file mode 100644 index 0000000..df7387c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/inquire_mechs_for_name.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_inquire_mechs_for_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + gss_OID_set *mech_types) +{ + OM_uint32 ret, tmp; + + ret = gss_create_empty_oid_set(minor_status, mech_types); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_add_oid_set_member(minor_status, + GSS_SANON_X25519_MECHANISM, + mech_types); + if (ret != GSS_S_COMPLETE) + gss_release_oid_set(&tmp, mech_types); + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/inquire_names_for_mech.c b/third_party/heimdal/lib/gssapi/sanon/inquire_names_for_mech.c new file mode 100644 index 0000000..c8b7f23 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/inquire_names_for_mech.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "sanon_locl.h" + +static gss_OID name_list[] = { + GSS_C_NT_HOSTBASED_SERVICE, + GSS_C_NT_USER_NAME, + GSS_C_NT_EXPORT_NAME, + GSS_C_NT_ANONYMOUS, + GSS_KRB5_NT_PRINCIPAL_NAME, + NULL +}; + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_inquire_names_for_mech(OM_uint32 *minor, + const gss_OID mechanism, + gss_OID_set *name_types) +{ + OM_uint32 ret, tmp; + int i; + + *minor = 0; + + if (gss_oid_equal(mechanism, GSS_SANON_X25519_MECHANISM) == 0 && + gss_oid_equal(mechanism, GSS_C_NULL_OID) == 0) { + *name_types = GSS_C_NO_OID_SET; + return GSS_S_BAD_MECH; + } + + ret = gss_create_empty_oid_set(minor, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + for (i = 0; name_list[i] != NULL; i++) { + ret = gss_add_oid_set_member(minor, + name_list[i], + name_types); + if (ret != GSS_S_COMPLETE) + break; + } + + if (ret != GSS_S_COMPLETE) + gss_release_oid_set(&tmp, name_types); + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/inquire_sec_context_by_oid.c b/third_party/heimdal/lib/gssapi/sanon/inquire_sec_context_by_oid.c new file mode 100644 index 0000000..1d8bc4b --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/inquire_sec_context_by_oid.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_inquire_sec_context_by_oid(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + const sanon_ctx sc = (const sanon_ctx)context_handle; + + if (sc == NULL) + return GSS_S_NO_CONTEXT; + + *data_set = GSS_C_NO_BUFFER_SET; + + if (gss_oid_equal(desired_object, GSS_C_INQ_SSPI_SESSION_KEY) || + gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X) || + gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X) || + gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X) || + gss_oid_equal(desired_object, GSS_KRB5_EXPORT_LUCID_CONTEXT_X)) + return gss_inquire_sec_context_by_oid(minor, sc->rfc4121, + desired_object, data_set); + else if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY) || + gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY)) + return _gss_sanon_inquire_negoex_key(minor, sc, desired_object, data_set); + else { + *minor = EINVAL; + return GSS_S_UNAVAILABLE; + } +} diff --git a/third_party/heimdal/lib/gssapi/sanon/negoex.c b/third_party/heimdal/lib/gssapi/sanon/negoex.c new file mode 100644 index 0000000..c6a21dd --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/negoex.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gssspi_sanon_query_mechanism_info(OM_uint32 *minor, + gss_const_OID mech_oid, + unsigned char auth_scheme[16]) +{ + heim_assert(gss_oid_equal(mech_oid, GSS_SANON_X25519_MECHANISM), + "Invalid mechanism OID passed to query_mechanism_info"); + + *minor = 0; + + /* {DEE384FF-1086-4E86-BE78-B94170BFD376} */ + memcpy(auth_scheme, + "\xff\x84\xe3\xde\x86\x10\x86\x4e\xbe\x78\xb9\x41\x70\xbf\xd3\x76", 16); + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gss_sanon_inquire_negoex_key(OM_uint32 *minor, + const sanon_ctx sc, + gss_const_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 major, tmpMinor; + int initiator_key; + uint8_t typebytes[4]; + gss_buffer_desc salt, keyvalue = GSS_C_EMPTY_BUFFER, keytype; + + if (sc->rfc4121 == GSS_C_NO_CONTEXT) { + *minor = KRB5KRB_AP_ERR_NOKEY; + return GSS_S_UNAVAILABLE; + } + + initiator_key = !!(sc->is_initiator); + + if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY)) + initiator_key ^= 1; + else if (!gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY)) + return GSS_S_UNAVAILABLE; + + if (initiator_key) { + salt.length = sizeof("sanon-x25519-initiator-negoex-key") - 1; + salt.value = "sanon-x25519-initiator-negoex-key"; + } else { + salt.length = sizeof("sanon-x25519-acceptor-negoex-key") - 1; + salt.value = "sanon-x25519-acceptor-negoex-key"; + } + + _gss_mg_encode_le_uint32(KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128, typebytes); + + keytype.length = sizeof(typebytes); + keytype.value = typebytes; + + major = gss_pseudo_random(minor, sc->rfc4121, + GSS_C_PRF_KEY_FULL, &salt, + 16, &keyvalue); + if (major == GSS_S_COMPLETE) + major = gss_add_buffer_set_member(minor, &keyvalue, data_set); + if (major == GSS_S_COMPLETE) + major = gss_add_buffer_set_member(minor, &keytype, data_set); + + _gss_secure_release_buffer(&tmpMinor, &keyvalue); + + return major; +} + +OM_uint32 GSSAPI_CALLCONV +_gssspi_sanon_query_meta_data(OM_uint32 *minor, + gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *context_handle, + gss_const_name_t targ_name, + OM_uint32 req_flags, + gss_buffer_t meta_data) +{ + int is_initiator = (targ_name != GSS_C_NO_NAME); + + *minor = 0; + + if (is_initiator && + !_gss_sanon_available_p(cred_handle, targ_name, req_flags)) + return GSS_S_UNAVAILABLE; + + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gssspi_sanon_exchange_meta_data(OM_uint32 *minor, + gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *context_handle, + gss_const_name_t targ_name, + OM_uint32 req_flags, + gss_const_buffer_t meta_data) +{ + *minor = 0; + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/process_context_token.c b/third_party/heimdal/lib/gssapi/sanon/process_context_token.c new file mode 100644 index 0000000..077c8cb --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/process_context_token.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +_gss_sanon_process_context_token(OM_uint32 *minor, + gss_const_ctx_id_t context_handle, + const gss_buffer_t token_buffer) +{ + *minor = 0; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/release_cred.c b/third_party/heimdal/lib/gssapi/sanon/release_cred.c new file mode 100644 index 0000000..aa95272 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/release_cred.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_release_cred(OM_uint32 *minor, + gss_cred_id_t *cred_handle) +{ + *minor = 0; + *cred_handle = GSS_C_NO_CREDENTIAL; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/release_name.c b/third_party/heimdal/lib/gssapi/sanon/release_name.c new file mode 100644 index 0000000..7ba788c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/release_name.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanon_locl.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_sanon_release_name(OM_uint32 *minor, + gss_name_t *input_name) +{ + *minor = 0; + *input_name = GSS_C_NO_NAME; + + return GSS_S_COMPLETE; +} diff --git a/third_party/heimdal/lib/gssapi/sanon/sanon_locl.h b/third_party/heimdal/lib/gssapi/sanon/sanon_locl.h new file mode 100644 index 0000000..93d6aa8 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/sanon/sanon_locl.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019-2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SANON_LOCL_H +#define SANON_LOCL_H 1 + +#include <config.h> + +#include <krb5_locl.h> /* for _krb5_SP800_108_HMAC_KDF() */ + +#include <hcrypto/x25519_ref10.h> + +#include <gssapi.h> +#include <gkrb5_err.h> /* for GSS_KRB5_S_XXX */ + +#include "mech/mech_locl.h" + +typedef struct sanon_ctx_desc { + /* X25519 ECDH secret key */ + uint8_t sk[crypto_scalarmult_curve25519_BYTES]; + /* X25519 ECDH public key */ + uint8_t pk[crypto_scalarmult_curve25519_BYTES]; + /* krb5 context for message protection/PRF */ + gss_ctx_id_t rfc4121; + unsigned is_initiator : 1; +} *sanon_ctx; + +extern gss_name_t _gss_sanon_anonymous_identity; +extern gss_name_t _gss_sanon_non_anonymous_identity; + +extern gss_cred_id_t _gss_sanon_anonymous_cred; +extern gss_cred_id_t _gss_sanon_non_anonymous_cred; + +#include "sanon-private.h" + +#define SANON_WELLKNOWN_USER_NAME "WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS" +#define SANON_WELLKNOWN_USER_NAME_LEN (sizeof(SANON_WELLKNOWN_USER_NAME) - 1) + +extern gss_buffer_t _gss_sanon_wellknown_user_name; + +#define SANON_WELLKNOWN_SERVICE_NAME "WELLKNOWN@ANONYMOUS" +#define SANON_WELLKNOWN_SERVICE_NAME_LEN (sizeof(SANON_WELLKNOWN_SERVICE_NAME) - 1) + +extern gss_buffer_t _gss_sanon_wellknown_service_name; + +static inline int +buffer_equal_p(gss_const_buffer_t b1, gss_const_buffer_t b2) +{ + return b1->length == b2->length && + memcmp(b1->value, b2->value, b2->length) == 0; +} + +/* flags that are valid to be sent from a SAnon initiator in the flags field */ +#define SANON_PROTOCOL_FLAG_MASK ( GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG ) + +#endif /* SANON_LOCL_H */ diff --git a/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c b/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c new file mode 100644 index 0000000..c4ac745 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -0,0 +1,1024 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego_locl.h" + +static OM_uint32 +send_reject (OM_uint32 *minor_status, + gss_const_buffer_t mech_token, + gss_buffer_t output_token) +{ + NegotiationToken nt; + size_t size; + heim_octet_string responseToken; + + nt.element = choice_NegotiationToken_negTokenResp; + + ALLOC(nt.u.negTokenResp.negState, 1); + if (nt.u.negTokenResp.negState == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + *(nt.u.negTokenResp.negState) = reject; + nt.u.negTokenResp.supportedMech = NULL; + nt.u.negTokenResp.responseToken = NULL; + + if (mech_token != GSS_C_NO_BUFFER && mech_token->value != NULL) { + responseToken.length = mech_token->length; + responseToken.data = mech_token->value; + nt.u.negTokenResp.responseToken = &responseToken; + } else + nt.u.negTokenResp.responseToken = NULL; + nt.u.negTokenResp.mechListMIC = NULL; + + ASN1_MALLOC_ENCODE(NegotiationToken, + output_token->value, output_token->length, &nt, + &size, *minor_status); + nt.u.negTokenResp.responseToken = NULL; /* allocated on stack */ + free_NegotiationToken(&nt); + if (*minor_status != 0) + return GSS_S_FAILURE; + + return GSS_S_BAD_MECH; +} + +static OM_uint32 +acceptor_approved(OM_uint32 *minor_status, + void *userptr, + gss_const_name_t target_name, + gss_const_cred_id_t cred_handle, + gss_OID mech) +{ + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_OID_set oidset = GSS_C_NO_OID_SET; + OM_uint32 junk, ret; + + if (target_name == GSS_C_NO_NAME) + return GSS_S_COMPLETE; + + if (gss_oid_equal(mech, GSS_NEGOEX_MECHANISM)) { + size_t i; + + ret = _gss_spnego_indicate_mechs(minor_status, &oidset); + if (ret != GSS_S_COMPLETE) + return ret; + + /* before committing to NegoEx, check we can negotiate a mech */ + for (i = 0; i < oidset->count; i++) { + gss_OID inner_mech = &oidset->elements[i]; + + if (_gss_negoex_mech_p(inner_mech)) { + ret = acceptor_approved(minor_status, userptr, + target_name, cred_handle, + inner_mech); + if (ret == GSS_S_COMPLETE) + break; + } + } + } else if (cred_handle != GSS_C_NO_CREDENTIAL) { + ret = gss_inquire_cred_by_mech(minor_status, cred_handle, mech, + NULL, NULL, NULL, NULL); + } else { + ret = gss_create_empty_oid_set(minor_status, &oidset); + if (ret == GSS_S_COMPLETE) + ret = gss_add_oid_set_member(minor_status, mech, &oidset); + if (ret == GSS_S_COMPLETE) + ret = gss_acquire_cred(minor_status, target_name, + GSS_C_INDEFINITE, oidset, + GSS_C_ACCEPT, &cred, NULL, NULL); + } + + gss_release_oid_set(&junk, &oidset); + gss_release_cred(&junk, &cred); + + return ret; +} + +static OM_uint32 +send_supported_mechs (OM_uint32 *minor_status, + gssspnego_ctx ctx, + gss_const_cred_id_t acceptor_cred, + gss_buffer_t output_token) +{ + NegotiationToken2 nt; + size_t buf_len = 0; + gss_buffer_desc data; + OM_uint32 ret; + + memset(&nt, 0, sizeof(nt)); + + nt.element = choice_NegotiationToken2_negTokenInit; + nt.u.negTokenInit.reqFlags = NULL; + nt.u.negTokenInit.mechToken = NULL; + nt.u.negTokenInit.negHints = NULL; + + ret = _gss_spnego_indicate_mechtypelist(minor_status, GSS_C_NO_NAME, 0, + acceptor_approved, ctx, 1, acceptor_cred, + &nt.u.negTokenInit.mechTypes, NULL); + if (ret != GSS_S_COMPLETE) { + return ret; + } + + ALLOC(nt.u.negTokenInit.negHints, 1); + if (nt.u.negTokenInit.negHints == NULL) { + *minor_status = ENOMEM; + free_NegotiationToken2(&nt); + return GSS_S_FAILURE; + } + + ALLOC(nt.u.negTokenInit.negHints->hintName, 1); + if (nt.u.negTokenInit.negHints->hintName == NULL) { + *minor_status = ENOMEM; + free_NegotiationToken2(&nt); + return GSS_S_FAILURE; + } + + *nt.u.negTokenInit.negHints->hintName = strdup("not_defined_in_RFC4178@please_ignore"); + nt.u.negTokenInit.negHints->hintAddress = NULL; + + ASN1_MALLOC_ENCODE(NegotiationToken2, + data.value, data.length, &nt, &buf_len, ret); + free_NegotiationToken2(&nt); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + if (data.length != buf_len) { + abort(); + UNREACHABLE(return GSS_S_FAILURE); + } + + ret = gss_encapsulate_token(&data, GSS_SPNEGO_MECHANISM, output_token); + + free (data.value); + + if (ret != GSS_S_COMPLETE) + return ret; + + *minor_status = 0; + + return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +send_accept (OM_uint32 *minor_status, + gssspnego_ctx context_handle, + int optimistic_mech_ok, + gss_buffer_t mech_token, + gss_const_OID selected_mech, /* valid on initial response only */ + gss_buffer_t mech_buf, + gss_buffer_t output_token) +{ + int initial_response = (selected_mech != GSS_C_NO_OID); + NegotiationToken nt; + OM_uint32 ret, minor; + gss_buffer_desc mech_mic_buf; + size_t size; + + memset(&nt, 0, sizeof(nt)); + + nt.element = choice_NegotiationToken_negTokenResp; + + ALLOC(nt.u.negTokenResp.negState, 1); + if (nt.u.negTokenResp.negState == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (context_handle->flags.open) { + if (mech_token != GSS_C_NO_BUFFER + && mech_token->length != 0 + && mech_buf != GSS_C_NO_BUFFER) + *(nt.u.negTokenResp.negState) = accept_incomplete; + else + *(nt.u.negTokenResp.negState) = accept_completed; + } else { + if (initial_response && !optimistic_mech_ok) + *(nt.u.negTokenResp.negState) = request_mic; + else + *(nt.u.negTokenResp.negState) = accept_incomplete; + } + + if (initial_response) { + ALLOC(nt.u.negTokenResp.supportedMech, 1); + if (nt.u.negTokenResp.supportedMech == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + goto out; + } + + ret = der_get_oid(selected_mech->elements, + selected_mech->length, + nt.u.negTokenResp.supportedMech, + NULL); + if (ret) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + goto out; + } + + _gss_spnego_log_mech("acceptor sending selected mech", selected_mech); + } else { + nt.u.negTokenResp.supportedMech = NULL; + } + + if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0) { + ALLOC(nt.u.negTokenResp.responseToken, 1); + if (nt.u.negTokenResp.responseToken == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + goto out; + } + nt.u.negTokenResp.responseToken->length = mech_token->length; + nt.u.negTokenResp.responseToken->data = mech_token->value; + mech_token->length = 0; + mech_token->value = NULL; + } else { + nt.u.negTokenResp.responseToken = NULL; + } + + if (mech_buf != GSS_C_NO_BUFFER) { + ret = gss_get_mic(minor_status, + context_handle->negotiated_ctx_id, + 0, + mech_buf, + &mech_mic_buf); + if (ret == GSS_S_COMPLETE) { + _gss_spnego_ntlm_reset_crypto(&minor, context_handle, FALSE); + + ALLOC(nt.u.negTokenResp.mechListMIC, 1); + if (nt.u.negTokenResp.mechListMIC == NULL) { + gss_release_buffer(minor_status, &mech_mic_buf); + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + goto out; + } + nt.u.negTokenResp.mechListMIC->length = mech_mic_buf.length; + nt.u.negTokenResp.mechListMIC->data = mech_mic_buf.value; + } else if (ret == GSS_S_UNAVAILABLE) { + nt.u.negTokenResp.mechListMIC = NULL; + } else { + goto out; + } + + } else + nt.u.negTokenResp.mechListMIC = NULL; + + ASN1_MALLOC_ENCODE(NegotiationToken, + output_token->value, output_token->length, + &nt, &size, ret); + if (ret) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + goto out; + } + + /* + * The response should not be encapsulated, because + * it is a SubsequentContextToken (note though RFC 1964 + * specifies encapsulation for all _Kerberos_ tokens). + */ + + if (*(nt.u.negTokenResp.negState) == accept_completed) + ret = GSS_S_COMPLETE; + else + ret = GSS_S_CONTINUE_NEEDED; + + out: + free_NegotiationToken(&nt); + return ret; +} + +/* + * Return the default acceptor identity based on the local hostname + * or the GSSAPI_SPNEGO_NAME environment variable. + */ + +static OM_uint32 +default_acceptor_name(OM_uint32 *minor_status, + gss_name_t *namep) +{ + OM_uint32 major_status; + gss_buffer_desc namebuf; + char *str = NULL, *host, hostname[MAXHOSTNAMELEN]; + + *namep = GSS_C_NO_NAME; + + host = secure_getenv("GSSAPI_SPNEGO_NAME"); + if (host == NULL) { + int rv; + + if (gethostname(hostname, sizeof(hostname)) != 0) { + *minor_status = errno; + return GSS_S_FAILURE; + } + + rv = asprintf(&str, "host@%s", hostname); + if (rv < 0 || str == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + host = str; + } + + namebuf.length = strlen(host); + namebuf.value = host; + + major_status = gss_import_name(minor_status, &namebuf, + GSS_C_NT_HOSTBASED_SERVICE, namep); + + free(str); + + return major_status; +} + +/* + * Determine whether the mech in mechType can be negotiated. If the + * mech is NegoEx, make NegoEx mechanisms available for negotiation. + */ + +static OM_uint32 +select_mech(OM_uint32 *minor_status, + gssspnego_ctx ctx, + gss_const_cred_id_t cred, + gss_const_OID_set supported_mechs, + MechType *mechType, + int verify_p, /* set on non-optimistic tokens */ + gss_const_OID *advertised_mech_p) +{ + char mechbuf[64]; + size_t mech_len; + gss_OID_desc oid; + gss_OID selected_mech = GSS_C_NO_OID; + OM_uint32 ret, junk; + int negoex_proposed = FALSE, negoex_selected = FALSE; + int includeMSCompatOID = FALSE; + size_t i; + + *minor_status = 0; + *advertised_mech_p = GSS_C_NO_OID; /* deals with broken MS OID */ + + ctx->selected_mech_type = GSS_C_NO_OID; + + ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, + sizeof(mechbuf), + mechType, + &mech_len); + if (ret) + return GSS_S_DEFECTIVE_TOKEN; + + oid.length = (OM_uint32)mech_len; + oid.elements = mechbuf + sizeof(mechbuf) - mech_len; + + if (gss_oid_equal(&oid, GSS_NEGOEX_MECHANISM)) + negoex_proposed = TRUE; + else if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) + includeMSCompatOID = TRUE; + + for (i = 0; i < supported_mechs->count; i++) { + gss_OID iter = &supported_mechs->elements[i]; + auth_scheme scheme; + int is_negoex_mech = /* mechanism is negotiable under NegoEx */ + gssspi_query_mechanism_info(&junk, iter, scheme) == GSS_S_COMPLETE; + + if (is_negoex_mech && negoex_proposed) { + ret = _gss_negoex_add_auth_mech(minor_status, ctx, iter, scheme); + if (ret != GSS_S_COMPLETE) + break; + + negoex_selected = TRUE; + } + + if (gss_oid_equal(includeMSCompatOID ? GSS_KRB5_MECHANISM : &oid, iter)) { + ret = _gss_intern_oid(minor_status, iter, &selected_mech); + if (ret != GSS_S_COMPLETE) + return ret; + + break; + } + } + + /* always prefer NegoEx if a mechanism supported both */ + if (negoex_selected) + selected_mech = GSS_NEGOEX_MECHANISM; + if (selected_mech == GSS_C_NO_OID) + ret = GSS_S_BAD_MECH; + if (ret != GSS_S_COMPLETE) + return ret; + + heim_assert(!gss_oid_equal(selected_mech, GSS_SPNEGO_MECHANISM), + "SPNEGO should not be able to negotiate itself"); + + if (verify_p) { + gss_name_t name = GSS_C_NO_NAME; + + /* + * If we do not have a credential, acquire a default name as a hint + * to acceptor_approved() so it can attempt to acquire a default + * credential. + */ + if (cred == GSS_C_NO_CREDENTIAL) { + ret = default_acceptor_name(minor_status, &name); + if (ret != GSS_S_COMPLETE) + return ret; + } + + ret = acceptor_approved(minor_status, ctx, name, cred, selected_mech); + + gss_release_name(&junk, &name); + } else { + /* Stash optimistic mech for use by _gss_spnego_require_mechlist_mic() */ + ret = gss_duplicate_oid(minor_status, &oid, &ctx->preferred_mech_type); + } + + if (ret == GSS_S_COMPLETE) { + *minor_status = 0; + + *advertised_mech_p = ctx->selected_mech_type = selected_mech; + + /* if the initiator used the broken MS OID, send that instead */ + if (includeMSCompatOID && gss_oid_equal(selected_mech, GSS_KRB5_MECHANISM)) + *advertised_mech_p = &_gss_spnego_mskrb_mechanism_oid_desc; + } + + return ret; +} + + +static OM_uint32 +acceptor_complete(OM_uint32 * minor_status, + gssspnego_ctx ctx, + int *get_mic, + gss_buffer_t mech_input_token, + gss_buffer_t mech_output_token, + heim_octet_string *mic, + gss_buffer_t output_token) +{ + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + OM_uint32 ret; + int verify_mic; + + ctx->flags.require_mic = 1; + ctx->flags.safe_omit = _gss_spnego_safe_omit_mechlist_mic(ctx); + + if (ctx->flags.open) { + if (mech_input_token == GSS_C_NO_BUFFER) { /* Even/One */ + verify_mic = 1; + *get_mic = 0; + } else if (mech_output_token != GSS_C_NO_BUFFER && + mech_output_token->length == 0) { /* Odd */ + *get_mic = verify_mic = 1; + } else { /* Even/One */ + verify_mic = 0; + *get_mic = 1; + } + + /* + * Change from previous versions: do not generate a MIC if not + * necessary. This conforms to RFC4178 s.5 ("if the accepted + * mechanism is the most preferred mechanism of both the initiator + * and acceptor, then the MIC token exchange... is OPTIONAL"), + * and is consistent with MIT and Windows behavior. + */ + if (ctx->flags.safe_omit) + *get_mic = 0; + + if (verify_mic && mic == NULL && ctx->flags.safe_omit) { + /* + * Peer is old and didn't send a mic while we expected + * one, but since it safe to omit, let do that + */ + } else if (verify_mic) { + ret = _gss_spnego_verify_mechtypes_mic(minor_status, ctx, mic); + if (ret) { + if (*get_mic) + send_reject(minor_status, GSS_C_NO_BUFFER, output_token); + if (buf.value) + free(buf.value); + return ret; + } + } + } else + *get_mic = 0; + + return GSS_S_COMPLETE; +} + +/* + * Call gss_accept_sec_context() via mechglue or NegoEx, depending on + * whether mech_oid is NegoEx. + */ + +static OM_uint32 +mech_accept(OM_uint32 *minor_status, + gssspnego_ctx ctx, + gss_const_cred_id_t acceptor_cred_handle, + gss_const_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_buffer_t output_token, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 ret, junk; + + heim_assert(ctx->selected_mech_type != GSS_C_NO_OID, + "mech_accept called with no selected mech"); + + if (gss_oid_equal(ctx->selected_mech_type, GSS_NEGOEX_MECHANISM)) { + ret = _gss_negoex_accept(minor_status, + ctx, + (gss_cred_id_t)acceptor_cred_handle, + input_token_buffer, + input_chan_bindings, + output_token, + delegated_cred_handle); + } else { + if (ctx->mech_src_name != GSS_C_NO_NAME) + gss_release_name(&junk, &ctx->mech_src_name); + + ret = gss_accept_sec_context(minor_status, + &ctx->negotiated_ctx_id, + acceptor_cred_handle, + (gss_buffer_t)input_token_buffer, + input_chan_bindings, + &ctx->mech_src_name, + &ctx->negotiated_mech_type, + output_token, + &ctx->mech_flags, + &ctx->mech_time_rec, + delegated_cred_handle); + if (GSS_ERROR(ret)) + gss_mg_collect_error(ctx->negotiated_mech_type, ret, *minor_status); + else if (ctx->negotiated_mech_type != GSS_C_NO_OID && + !gss_oid_equal(ctx->negotiated_mech_type, ctx->selected_mech_type)) + _gss_mg_log(1, "spnego client didn't send the mech they said they would"); + } + + return ret; +} + +static OM_uint32 GSSAPI_CALLCONV +acceptor_start + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t *delegated_cred_handle + ) +{ + OM_uint32 ret, junk; + NegotiationToken nt; + gss_OID_set supported_mechs = GSS_C_NO_OID_SET; + size_t size; + NegTokenInit *ni; + gss_buffer_desc data; + gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; + gss_buffer_desc mech_output_token; + gssspnego_ctx ctx; + int get_mic = 0, first_ok = 0, canonical_order; + gss_const_OID advertised_mech = GSS_C_NO_OID; + + memset(&nt, 0, sizeof(nt)); + + mech_output_token.value = NULL; + mech_output_token.length = 0; + + if (input_token_buffer->length == 0) + return send_supported_mechs (minor_status, NULL, + acceptor_cred_handle, output_token); + + ret = _gss_spnego_alloc_sec_context(minor_status, context_handle); + if (ret != GSS_S_COMPLETE) + return ret; + + ctx = (gssspnego_ctx)*context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + /* + * The GSS-API encapsulation is only present on the initial + * context token (negTokenInit). + */ + ret = gss_decapsulate_token (input_token_buffer, + GSS_SPNEGO_MECHANISM, + &data); + if (ret) + goto out; + + ret = decode_NegotiationToken(data.value, data.length, &nt, &size); + gss_release_buffer(minor_status, &data); + if (ret) { + *minor_status = ret; + ret = GSS_S_DEFECTIVE_TOKEN; + goto out; + } + if (nt.element != choice_NegotiationToken_negTokenInit) { + *minor_status = 0; + ret = GSS_S_DEFECTIVE_TOKEN; + goto out; + } + ni = &nt.u.negTokenInit; + + if (ni->mechTypes.len < 1) { + free_NegotiationToken(&nt); + *minor_status = 0; + ret = GSS_S_DEFECTIVE_TOKEN; + goto out; + } + + _gss_spnego_log_mechTypes(&ni->mechTypes); + + { + MechTypeList mt; + int kret; + + mt.len = ni->mechTypes.len; + mt.val = ni->mechTypes.val; + + ASN1_MALLOC_ENCODE(MechTypeList, + ctx->NegTokenInit_mech_types.value, + ctx->NegTokenInit_mech_types.length, + &mt, &size, kret); + if (kret) { + *minor_status = kret; + ret = GSS_S_FAILURE; + goto out; + } + } + + if (acceptor_cred_handle != GSS_C_NO_CREDENTIAL) + ret = _gss_spnego_inquire_cred_mechs(minor_status, + acceptor_cred_handle, + &supported_mechs, + &canonical_order); + else + ret = _gss_spnego_indicate_mechs(minor_status, &supported_mechs); + if (ret != GSS_S_COMPLETE) + goto out; + + /* + * First we try the opportunistic token if we have support for it, + * don't try to verify we have credential for the token, + * gss_accept_sec_context() will (hopefully) tell us that. + * If that failes, + */ + + ret = select_mech(minor_status, + ctx, + acceptor_cred_handle, + supported_mechs, + &ni->mechTypes.val[0], + 0, /* optimistic token */ + &advertised_mech); + + if (ret == GSS_S_COMPLETE && ni->mechToken != NULL) { + gss_buffer_desc ibuf; + + ibuf.length = ni->mechToken->length; + ibuf.value = ni->mechToken->data; + mech_input_token = &ibuf; + + _gss_spnego_log_mech("acceptor selected opportunistic mech", ctx->selected_mech_type); + + ret = mech_accept(&junk, + ctx, + acceptor_cred_handle, + mech_input_token, + input_chan_bindings, + &mech_output_token, + delegated_cred_handle); + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + first_ok = 1; + } else { + ctx->selected_mech_type = GSS_C_NO_OID; + } + + if (ret == GSS_S_COMPLETE) { + ret = acceptor_complete(minor_status, + ctx, + &get_mic, + mech_input_token, + &mech_output_token, + ni->mechListMIC, + output_token); + if (ret != GSS_S_COMPLETE) + goto out; + + ctx->flags.open = 1; + } + } else { + *minor_status = 0; + gss_release_oid_set(&junk, &supported_mechs); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return gss_mg_set_error_string(GSS_C_NO_OID, GSS_S_NO_CONTEXT, + *minor_status, + "SPNEGO acceptor didn't find a prefered mechanism"); + } + + /* + * If opportunistic token failed, lets try the other mechs. + */ + + if (!first_ok) { + size_t j; + + /* Call glue layer to find first mech we support */ + for (j = 1; j < ni->mechTypes.len; ++j) { + ret = select_mech(&junk, + ctx, + acceptor_cred_handle, + supported_mechs, + &ni->mechTypes.val[j], + 1, /* not optimistic token */ + &advertised_mech); + if (ret == GSS_S_COMPLETE) { + _gss_spnego_log_mech("acceptor selected non-opportunistic mech", + ctx->selected_mech_type); + break; + } + } + } + if (ctx->selected_mech_type == GSS_C_NO_OID) { + heim_assert(ret != GSS_S_COMPLETE, "no oid and no error code?"); + *minor_status = junk; + goto out; + } + + /* The initial token always has a response */ + ret = send_accept(minor_status, + ctx, + first_ok, + &mech_output_token, + advertised_mech, + get_mic ? &ctx->NegTokenInit_mech_types : NULL, + output_token); + if (ret) + goto out; + +out: + gss_release_oid_set(&junk, &supported_mechs); + if (mech_output_token.value != NULL) + gss_release_buffer(&junk, &mech_output_token); + free_NegotiationToken(&nt); + + + if (ret == GSS_S_COMPLETE) { + if (src_name != NULL && ctx->mech_src_name != GSS_C_NO_NAME) + ret = gss_duplicate_name(minor_status, + ctx->mech_src_name, + src_name); + } + + if (mech_type != NULL) + *mech_type = ctx->negotiated_mech_type; + if (ret_flags != NULL) + *ret_flags = ctx->mech_flags; + if (time_rec != NULL) + *time_rec = ctx->mech_time_rec; + + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + + _gss_spnego_internal_delete_sec_context(&junk, context_handle, + GSS_C_NO_BUFFER); + + return ret; +} + + +static OM_uint32 GSSAPI_CALLCONV +acceptor_continue + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t *delegated_cred_handle + ) +{ + OM_uint32 ret, ret2, minor, junk; + NegotiationToken nt; + size_t nt_len; + NegTokenResp *na; + unsigned int negState = accept_incomplete; + gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; + gss_buffer_t mech_output_token = GSS_C_NO_BUFFER; + gssspnego_ctx ctx; + + ctx = (gssspnego_ctx)*context_handle; + + /* + * The GSS-API encapsulation is only present on the initial + * context token (negTokenInit). + */ + + ret = decode_NegotiationToken(input_token_buffer->value, + input_token_buffer->length, + &nt, &nt_len); + if (ret) { + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + if (nt.element != choice_NegotiationToken_negTokenResp) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + na = &nt.u.negTokenResp; + + if (na->negState != NULL) { + negState = *(na->negState); + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + { + gss_buffer_desc ibuf, obuf; + int get_mic = 0; + int require_response; + + if (na->responseToken != NULL) { + ibuf.length = na->responseToken->length; + ibuf.value = na->responseToken->data; + mech_input_token = &ibuf; + } else { + ibuf.value = NULL; + ibuf.length = 0; + } + + if (mech_input_token != GSS_C_NO_BUFFER) { + + ret = mech_accept(minor_status, + ctx, + acceptor_cred_handle, + mech_input_token, + input_chan_bindings, + &obuf, + delegated_cred_handle); + mech_output_token = &obuf; + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + free_NegotiationToken(&nt); + send_reject(&junk, mech_output_token, output_token); + gss_release_buffer(&junk, mech_output_token); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + if (ret == GSS_S_COMPLETE) + ctx->flags.open = 1; + } else + ret = GSS_S_COMPLETE; + + if (ret == GSS_S_COMPLETE) + ret = acceptor_complete(minor_status, + ctx, + &get_mic, + mech_input_token, + mech_output_token, + na->mechListMIC, + output_token); + + if (ctx->mech_flags & GSS_C_DCE_STYLE) + require_response = (negState != accept_completed); + else + require_response = 0; + + /* + * Check whether we need to send a result: there should be only + * one accept_completed response sent in the entire negotiation + */ + if ((mech_output_token != GSS_C_NO_BUFFER && + mech_output_token->length != 0) + || (ctx->flags.open && negState == accept_incomplete) + || require_response + || get_mic) { + ret2 = send_accept (minor_status, + ctx, + 0, /* ignored on subsequent tokens */ + mech_output_token, + GSS_C_NO_OID, + get_mic ? &ctx->NegTokenInit_mech_types : NULL, + output_token); + if (ret2) + goto out; + } else + ret2 = GSS_S_COMPLETE; + + out: + if (ret2 != GSS_S_COMPLETE) + ret = ret2; + if (mech_output_token != NULL) + gss_release_buffer(&minor, mech_output_token); + free_NegotiationToken(&nt); + } + + if (ret == GSS_S_COMPLETE) { + if (src_name != NULL && ctx->mech_src_name != GSS_C_NO_NAME) + ret = gss_duplicate_name(minor_status, + ctx->mech_src_name, + src_name); + } + + if (mech_type != NULL) + *mech_type = ctx->negotiated_mech_type; + if (ret_flags != NULL) + *ret_flags = ctx->mech_flags; + if (time_rec != NULL) + *time_rec = ctx->mech_time_rec; + + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + + _gss_spnego_internal_delete_sec_context(&minor, context_handle, + GSS_C_NO_BUFFER); + + return ret; +} + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_const_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t *delegated_cred_handle + ) +{ + _gss_accept_sec_context_t *func; + + *minor_status = 0; + + output_token->length = 0; + output_token->value = NULL; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + if (ret_flags != NULL) + *ret_flags = 0; + if (time_rec != NULL) + *time_rec = 0; + if (delegated_cred_handle != NULL) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + + if (*context_handle == GSS_C_NO_CONTEXT) + func = acceptor_start; + else + func = acceptor_continue; + + + return (*func)(minor_status, context_handle, acceptor_cred_handle, + input_token_buffer, input_chan_bindings, + src_name, mech_type, output_token, ret_flags, + time_rec, delegated_cred_handle); +} diff --git a/third_party/heimdal/lib/gssapi/spnego/compat.c b/third_party/heimdal/lib/gssapi/spnego/compat.c new file mode 100644 index 0000000..6cfe552 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/compat.c @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego_locl.h" + +/* + * Apparently Microsoft got the OID wrong, and used + * 1.2.840.48018.1.2.2 instead. We need both this and + * the correct Kerberos OID here in order to deal with + * this. Because this is manifest in SPNEGO only I'd + * prefer to deal with this here rather than inside the + * Kerberos mechanism. + */ +gss_OID_desc _gss_spnego_mskrb_mechanism_oid_desc = + {9, rk_UNCONST("\x2a\x86\x48\x82\xf7\x12\x01\x02\x02")}; + +/* + * Allocate a SPNEGO context handle + */ +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_alloc_sec_context (OM_uint32 * minor_status, + gss_ctx_id_t *context_handle) +{ + gssspnego_ctx ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ctx->NegTokenInit_mech_types.value = NULL; + ctx->NegTokenInit_mech_types.length = 0; + + ctx->preferred_mech_type = GSS_C_NO_OID; + ctx->selected_mech_type = GSS_C_NO_OID; + ctx->negotiated_mech_type = GSS_C_NO_OID; + + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + + ctx->mech_flags = 0; + ctx->mech_time_rec = 0; + ctx->mech_src_name = GSS_C_NO_NAME; + + ctx->flags.open = 0; + ctx->flags.local = 0; + ctx->flags.peer_require_mic = 0; + ctx->flags.require_mic = 0; + ctx->flags.verified_mic = 0; + + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + ctx->negoex_step = 0; + ctx->negoex_transcript = NULL; + ctx->negoex_seqnum = 0; + HEIM_TAILQ_INIT(&ctx->negoex_mechs); + memset(ctx->negoex_conv_id, 0, GUID_LENGTH); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + +/* + * Free a SPNEGO context handle. The caller must have acquired + * the lock before this is called. + */ +OM_uint32 GSSAPI_CALLCONV _gss_spnego_internal_delete_sec_context + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token + ) +{ + gssspnego_ctx ctx; + OM_uint32 ret, minor; + + *minor_status = 0; + + if (context_handle == NULL) { + return GSS_S_NO_CONTEXT; + } + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + ctx = (gssspnego_ctx)*context_handle; + *context_handle = GSS_C_NO_CONTEXT; + + if (ctx == NULL) { + return GSS_S_NO_CONTEXT; + } + + if (ctx->NegTokenInit_mech_types.value) + free(ctx->NegTokenInit_mech_types.value); + + ctx->preferred_mech_type = GSS_C_NO_OID; + ctx->negotiated_mech_type = GSS_C_NO_OID; + ctx->selected_mech_type = GSS_C_NO_OID; + + gss_release_name(&minor, &ctx->target_name); + gss_release_name(&minor, &ctx->mech_src_name); + + if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { + ret = gss_delete_sec_context(minor_status, + &ctx->negotiated_ctx_id, + output_token); + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + } else { + ret = GSS_S_COMPLETE; + } + + _gss_negoex_release_context(ctx); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + + free(ctx); + + return ret; +} + +static int +inq_context_by_oid_bool(gssspnego_ctx ctx, gss_OID oid) +{ + OM_uint32 major, minor; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + uint8_t ret = 0; + + major = gss_inquire_sec_context_by_oid(&minor, ctx->negotiated_ctx_id, + oid, &data_set); + if (major != GSS_S_COMPLETE) + return FALSE; + + if (data_set != GSS_C_NO_BUFFER_SET && + data_set->count == 1 && + data_set->elements[0].length == 1) + ret = *((uint8_t *)data_set->elements[0].value); + + gss_release_buffer_set(&minor, &data_set); + + return ret != 0; +} + +/* + * Returns TRUE if it is safe to omit mechListMIC. + */ + +int +_gss_spnego_safe_omit_mechlist_mic(gssspnego_ctx ctx) +{ + int safe_omit = FALSE; + + if (ctx->flags.peer_require_mic) { + _gss_mg_log(10, "spnego: mechListMIC required by peer"); + } else if (inq_context_by_oid_bool(ctx, GSS_C_INQ_PEER_HAS_BUGGY_SPNEGO)) { + /* [MS-SPNG] Appendix A <7> Section 3.1.5.1: may be old peer with buggy SPNEGO */ + safe_omit = TRUE; + _gss_mg_log(10, "spnego: mechListMIC omitted for legacy interoperability"); + } else if (inq_context_by_oid_bool(ctx, GSS_C_INQ_REQUIRE_MECHLIST_MIC)) { + /* [MS-SPNG] Appendix A <7> Section 3.1.5.1: allow NTLM to force MIC */ + _gss_mg_log(10, "spnego: mechListMIC required by mechanism"); + } else if (gss_oid_equal(ctx->selected_mech_type, ctx->preferred_mech_type)) { + safe_omit = TRUE; + _gss_mg_log(10, "spnego: mechListMIC omitted as preferred mechanism selected"); + } else { + _gss_mg_log(10, "spnego: mechListMIC required by default"); + } + + return safe_omit; +} + +/* + * A map between a GSS-API flag and a (mechanism attribute, weight) + * tuple. The list of mechanisms is re-ordered by aggregate weight + * (highest weight is more preferred, e.g. if GSS_C_MUTUAL_FLAG and + * GSS_C_ANON_FLAG are set, we prefer a mechanism that supports + * mutual authentication over one that only supports anonymous). + */ +static struct { + OM_uint32 flag; + gss_OID ma; + int weight; +} flag_to_ma_map[] = { + { GSS_C_MUTUAL_FLAG, GSS_C_MA_AUTH_TARG, 2 }, + { GSS_C_ANON_FLAG, GSS_C_MA_AUTH_INIT_ANON, 1 }, +}; + +/* + * Returns a bitmask indicating GSS flags we can sort on. + */ +static inline OM_uint32 +mech_flag_mask(void) +{ + size_t i; + OM_uint32 mask = 0; + + for (i = 0; i < sizeof(flag_to_ma_map)/sizeof(flag_to_ma_map[0]); i++) + mask |= flag_to_ma_map[i].flag; + + return mask; +} + +/* + * Returns an integer representing the preference weighting for a + * mechanism, based on the requested GSS flags. + */ +static int +mech_weight(gss_const_OID mech, OM_uint32 req_flags) +{ + OM_uint32 major, minor; + gss_OID_set mech_attrs = GSS_C_NO_OID_SET; + int weight = 0; + size_t i, j; + + major = gss_inquire_attrs_for_mech(&minor, mech, &mech_attrs, NULL); + if (GSS_ERROR(major)) + return 0; + + for (i = 0; i < sizeof(flag_to_ma_map)/sizeof(flag_to_ma_map[0]); i++) { + if ((req_flags & flag_to_ma_map[i].flag) == 0) + continue; + + for (j = 0; j < mech_attrs->count; j++) { + if (gss_oid_equal(flag_to_ma_map[i].ma, &mech_attrs->elements[j])) { + weight += flag_to_ma_map[i].weight; + continue; + } + } + } + + gss_release_oid_set(&minor, &mech_attrs); + + return weight; +} + +static int +mech_compare(const void *mech1, const void *mech2, void *req_flags_p) +{ + OM_uint32 req_flags = *((OM_uint32 *)req_flags_p); + int mech1_weight = mech_weight(mech1, req_flags); + int mech2_weight = mech_weight(mech2, req_flags); + + return mech2_weight - mech1_weight; +} + +/* + * Order a list of mechanisms by weight based on requested GSS flags. + */ +static void +order_mechs_by_flags(gss_OID_set mechs, OM_uint32 req_flags) +{ + if (req_flags & mech_flag_mask()) { /* skip if flags irrelevant */ + /* + * NB: must be a stable sort to preserve the existing order + * of mechanisms that are equally weighted. + */ + mergesort_r(mechs->elements, mechs->count, + sizeof(gss_OID_desc), mech_compare, &req_flags); + } +} + +static OM_uint32 +add_mech_type(OM_uint32 *minor_status, + gss_OID mech_type, + MechTypeList *mechtypelist) +{ + MechType mech; + int ret; + + heim_assert(!gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM), + "SPNEGO mechanism not filtered"); + + ret = der_get_oid(mech_type->elements, mech_type->length, &mech, NULL); + if (ret == 0) { + ret = add_MechTypeList(mechtypelist, &mech); + free_MechType(&mech); + } + + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; +} + +static int +add_mech_if_approved(OM_uint32 *minor_status, + gss_const_name_t target_name, + OM_uint32 (*func)(OM_uint32 *, void *, gss_const_name_t, gss_const_cred_id_t, gss_OID), + void *userptr, + int includeMSCompatOID, + gss_const_cred_id_t cred_handle, + MechTypeList *mechtypelist, + gss_OID mech_oid, + gss_OID *first_mech, + OM_uint32 *first_major, + OM_uint32 *first_minor, + int *added_negoex) +{ + OM_uint32 major, minor; + + /* + * Unapproved mechanisms are ignored, but we capture their result + * code in case we didn't find any other mechanisms, in which case + * we return that to the caller of _gss_spnego_indicate_mechtypelist(). + */ + major = (*func)(&minor, userptr, target_name, cred_handle, mech_oid); + if (major != GSS_S_COMPLETE) { + if (*first_mech == GSS_C_NO_OID) { + *first_major = major; + *first_minor = minor; + } + return GSS_S_COMPLETE; + } + + if (_gss_negoex_mech_p(mech_oid)) { + if (*added_negoex == FALSE) { + major = add_mech_type(minor_status, GSS_NEGOEX_MECHANISM, mechtypelist); + if (major != GSS_S_COMPLETE) + return major; + *added_negoex = TRUE; + } + + if (*first_mech == GSS_C_NO_OID) + *first_mech = GSS_NEGOEX_MECHANISM; + + /* if NegoEx-only mech, we are done */ + if (!_gss_negoex_and_spnego_mech_p(mech_oid)) + return GSS_S_COMPLETE; + } + + if (includeMSCompatOID && gss_oid_equal(mech_oid, GSS_KRB5_MECHANISM)) { + major = add_mech_type(minor_status, + &_gss_spnego_mskrb_mechanism_oid_desc, + mechtypelist); + if (major != GSS_S_COMPLETE) + return major; + } + + major = add_mech_type(minor_status, mech_oid, mechtypelist); + if (major != GSS_S_COMPLETE) + return major; + + if (*first_mech == GSS_C_NO_OID) + *first_mech = mech_oid; + + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, + gss_const_name_t target_name, + OM_uint32 req_flags, + OM_uint32 (*func)(OM_uint32 *, void *, gss_const_name_t, gss_const_cred_id_t, gss_OID), + void *userptr, + int includeMSCompatOID, + gss_const_cred_id_t cred_handle, + MechTypeList *mechtypelist, + gss_OID *preferred_mech) +{ + gss_OID_set supported_mechs = GSS_C_NO_OID_SET; + gss_OID first_mech = GSS_C_NO_OID; + OM_uint32 ret, minor; + OM_uint32 first_major = GSS_S_BAD_MECH, first_minor = 0; + size_t i; + int added_negoex = FALSE, canonical_order = FALSE; + + mechtypelist->len = 0; + mechtypelist->val = NULL; + + if (cred_handle != GSS_C_NO_CREDENTIAL) + ret = _gss_spnego_inquire_cred_mechs(minor_status, cred_handle, + &supported_mechs, &canonical_order); + else + ret = _gss_spnego_indicate_mechs(minor_status, &supported_mechs); + if (ret != GSS_S_COMPLETE) + return ret; + + if (!canonical_order) + order_mechs_by_flags(supported_mechs, req_flags); + + heim_assert(supported_mechs != GSS_C_NO_OID_SET, + "NULL mech set returned by SPNEGO inquire/indicate mechs"); + + /* + * Previously krb5 was tried explicitly, but now the internal mech + * list is reordered so that krb5 is first, this should no longer + * be required. This permits an application to specify another + * mechanism as preferred over krb5 using gss_set_neg_mechs(). + */ + for (i = 0; i < supported_mechs->count; i++) { + ret = add_mech_if_approved(minor_status, target_name, + func, userptr, includeMSCompatOID, + cred_handle, mechtypelist, + &supported_mechs->elements[i], + &first_mech, + &first_major, &first_minor, + &added_negoex); + if (ret != GSS_S_COMPLETE) { + gss_release_oid_set(&minor, &supported_mechs); + return ret; + } + } + + heim_assert(mechtypelist->len == 0 || first_mech != GSS_C_NO_OID, + "mechtypelist non-empty but no mech selected"); + + if (first_mech != GSS_C_NO_OID) + ret = _gss_intern_oid(minor_status, first_mech, &first_mech); + else if (GSS_ERROR(first_major)) { + ret = first_major; + *minor_status = first_minor; + } else + ret = GSS_S_BAD_MECH; + + if (preferred_mech != NULL) + *preferred_mech = first_mech; + + gss_release_oid_set(&minor, &supported_mechs); + + return ret; +} + +/* + * + */ + +OM_uint32 +_gss_spnego_verify_mechtypes_mic(OM_uint32 *minor_status, + gssspnego_ctx ctx, + heim_octet_string *mic) +{ + gss_buffer_desc mic_buf; + OM_uint32 major_status; + + if (mic == NULL) { + *minor_status = 0; + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_DEFECTIVE_TOKEN, 0, + "SPNEGO peer failed to send mechListMIC"); + } + + if (ctx->flags.verified_mic) { + /* This doesn't make sense, we've already verified it? */ + *minor_status = 0; + return GSS_S_DUPLICATE_TOKEN; + } + + mic_buf.length = mic->length; + mic_buf.value = mic->data; + + major_status = gss_verify_mic(minor_status, + ctx->negotiated_ctx_id, + &ctx->NegTokenInit_mech_types, + &mic_buf, + NULL); + if (major_status == GSS_S_COMPLETE) { + _gss_spnego_ntlm_reset_crypto(minor_status, ctx, TRUE); + } else if (major_status == GSS_S_UNAVAILABLE) { + _gss_mg_log(10, "mech doesn't support MIC, allowing anyway"); + } else if (major_status) { + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_DEFECTIVE_TOKEN, *minor_status, + "SPNEGO peer sent invalid mechListMIC"); + } + ctx->flags.verified_mic = 1; + + *minor_status = 0; + + return GSS_S_COMPLETE; +} + +/* + * According to [MS-SPNG] 3.3.5.1 the crypto state for NTLM is reset + * before the completed context is returned to the application. + */ + +OM_uint32 +_gss_spnego_ntlm_reset_crypto(OM_uint32 *minor_status, + gssspnego_ctx ctx, + OM_uint32 verify) +{ + if (gss_oid_equal(ctx->negotiated_mech_type, GSS_NTLM_MECHANISM)) { + gss_buffer_desc value; + + value.length = sizeof(verify); + value.value = &verify; + + return gss_set_sec_context_option(minor_status, + &ctx->negotiated_ctx_id, + GSS_C_NTLM_RESET_CRYPTO, + &value); + } + + return GSS_S_COMPLETE; +} + +void +_gss_spnego_log_mech(const char *prefix, gss_const_OID oid) +{ + gss_buffer_desc oidbuf = GSS_C_EMPTY_BUFFER; + OM_uint32 junk; + const char *name = NULL; + + if (!_gss_mg_log_level(10)) + return; + + if (oid == GSS_C_NO_OID || + gss_oid_to_str(&junk, (gss_OID)oid, &oidbuf) != GSS_S_COMPLETE) { + _gss_mg_log(10, "spnego: %s (null)", prefix); + return; + } + + if (gss_oid_equal(oid, GSS_NEGOEX_MECHANISM)) + name = "negoex"; /* not a real mech */ + else if (gss_oid_equal(oid, &_gss_spnego_mskrb_mechanism_oid_desc)) + name = "mskrb"; + else { + gssapi_mech_interface m = __gss_get_mechanism(oid); + if (m) + name = m->gm_name; + } + + _gss_mg_log(10, "spnego: %s %s { %.*s }", + prefix, + name ? name : "unknown", + (int)oidbuf.length, (char *)oidbuf.value); + gss_release_buffer(&junk, &oidbuf); +} + +void +_gss_spnego_log_mechTypes(MechTypeList *mechTypes) +{ + size_t i; + char mechbuf[64]; + size_t mech_len; + gss_OID_desc oid; + int ret; + + if (!_gss_mg_log_level(10)) + return; + + for (i = 0; i < mechTypes->len; i++) { + ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, + sizeof(mechbuf), + &mechTypes->val[i], + &mech_len); + if (ret) + continue; + + oid.length = (OM_uint32)mech_len; + oid.elements = mechbuf + sizeof(mechbuf) - mech_len; + + _gss_spnego_log_mech("initiator proposed mech", &oid); + } +} + +/* + * Indicate mechs negotiable by SPNEGO + */ + +OM_uint32 +_gss_spnego_indicate_mechs(OM_uint32 *minor_status, + gss_OID_set *mechs_p) +{ + gss_OID_desc oids[3]; + gss_OID_set_desc except; + + *mechs_p = GSS_C_NO_OID_SET; + + oids[0] = *GSS_C_MA_DEPRECATED; + oids[1] = *GSS_C_MA_NOT_DFLT_MECH; + oids[2] = *GSS_C_MA_MECH_NEGO; + + except.count = sizeof(oids) / sizeof(oids[0]); + except.elements = oids; + + return gss_indicate_mechs_by_attrs(minor_status, + GSS_C_NO_OID_SET, + &except, + GSS_C_NO_OID_SET, + mechs_p); +} + +/* + * Indicate mechs in cred negotiatble by SPNEGO + */ + +OM_uint32 +_gss_spnego_inquire_cred_mechs(OM_uint32 *minor_status, + gss_const_cred_id_t cred, + gss_OID_set *mechs_p, + int *canonical_order) +{ + OM_uint32 ret, junk; + gss_OID_set cred_mechs = GSS_C_NO_OID_SET; + gss_OID_set negotiable_mechs = GSS_C_NO_OID_SET; + size_t i; + + *mechs_p = GSS_C_NO_OID_SET; + *canonical_order = FALSE; + + heim_assert(cred != GSS_C_NO_CREDENTIAL, "Invalid null credential handle"); + + ret = gss_get_neg_mechs(minor_status, cred, &cred_mechs); + if (ret == GSS_S_COMPLETE) { + *canonical_order = TRUE; + } else { + ret = gss_inquire_cred(minor_status, cred, NULL, NULL, NULL, &cred_mechs); + if (ret != GSS_S_COMPLETE) + goto out; + } + + heim_assert(cred_mechs != GSS_C_NO_OID_SET && cred_mechs->count > 0, + "gss_inquire_cred succeeded but returned no mechanisms"); + + ret = _gss_spnego_indicate_mechs(minor_status, &negotiable_mechs); + if (ret != GSS_S_COMPLETE) + goto out; + + heim_assert(negotiable_mechs != GSS_C_NO_OID_SET, + "_gss_spnego_indicate_mechs succeeded but returned null OID set"); + + ret = gss_create_empty_oid_set(minor_status, mechs_p); + if (ret != GSS_S_COMPLETE) + goto out; + + /* Filter credential mechs by negotiable mechs, order by credential mechs */ + for (i = 0; i < cred_mechs->count; i++) { + gss_OID cred_mech = &cred_mechs->elements[i]; + int present = 0; + + gss_test_oid_set_member(&junk, cred_mech, negotiable_mechs, &present); + if (!present) + continue; + + ret = gss_add_oid_set_member(minor_status, cred_mech, mechs_p); + if (ret != GSS_S_COMPLETE) + break; + } + +out: + if (ret != GSS_S_COMPLETE) + gss_release_oid_set(&junk, mechs_p); + gss_release_oid_set(&junk, &cred_mechs); + gss_release_oid_set(&junk, &negotiable_mechs); + + return ret; +} + diff --git a/third_party/heimdal/lib/gssapi/spnego/context_storage.c b/third_party/heimdal/lib/gssapi/spnego/context_storage.c new file mode 100644 index 0000000..13e20d7 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/context_storage.c @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2021, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spnego_locl.h" + +#define SC_MECH_TYPES 0x0001 +#define SC_PREFERRED_MECH_TYPE 0x0002 +#define SC_SELECTED_MECH_TYPE 0x0004 +#define SC_NEGOTIATED_MECH_TYPE 0x0008 +#define SC_NEGOTIATED_CTX_ID 0x0010 +#define SC_MECH_FLAGS 0x0020 +#define SC_MECH_TIME_REC 0x0040 +#define SC_MECH_SRC_NAME 0x0080 +#define SC_TARGET_NAME 0x0100 +#define SC_NEGOEX 0x0200 + +#define SNC_OID 0x01 +#define SNC_MECH_CONTEXT 0x02 +#define SNC_METADATA 0x04 + +static krb5_error_code +ret_spnego_context(krb5_storage *sp, gssspnego_ctx *ctxp); +static krb5_error_code +store_spnego_context(krb5_storage *sp, gssspnego_ctx ctx); + +static krb5_error_code +ret_negoex_auth_mech(krb5_storage *sp, struct negoex_auth_mech **mechp); +static krb5_error_code +store_negoex_auth_mech(krb5_storage *sp, struct negoex_auth_mech *mech); + +static uint16_t +spnego_flags_to_int(struct spnego_flags flags); +static struct spnego_flags +int_to_spnego_flags(uint16_t f); + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_import_sec_context_internal(OM_uint32 *minor, + gss_const_buffer_t buffer, + gssspnego_ctx *ctxp) +{ + krb5_error_code ret; + krb5_storage *sp; + + sp = krb5_storage_from_readonly_mem(buffer->value, buffer->length); + if (sp == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_PACKED); + + ret = ret_spnego_context(sp, ctxp); + + krb5_storage_free(sp); + + *minor = ret; + return ret ? GSS_S_FAILURE : GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_export_sec_context_internal(OM_uint32 *minor, + gssspnego_ctx ctx, + gss_buffer_t buffer) +{ + krb5_error_code ret; + krb5_storage *sp; + krb5_data data; + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + krb5_data_zero(&data); + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_PACKED); + + ret = store_spnego_context(sp, ctx); + if (ret == 0) + ret = krb5_storage_to_data(sp, &data); + if (ret == 0) { + buffer->length = data.length; + buffer->value = data.data; + } + + krb5_storage_free(sp); + + *minor = ret; + return ret ? GSS_S_FAILURE : GSS_S_COMPLETE; +} + +static krb5_error_code +ret_spnego_context(krb5_storage *sp, gssspnego_ctx *ctxp) +{ + OM_uint32 major = GSS_S_COMPLETE, minor; + gssspnego_ctx ctx = NULL; + krb5_error_code ret = 0; + krb5_data data; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + uint16_t sc_flags, spnego_flags; + + *ctxp = NULL; + krb5_data_zero(&data); + + CHECK(major, _gss_spnego_alloc_sec_context(&minor, (gss_ctx_id_t *)&ctx)); + + CHECK(ret, krb5_ret_uint16(sp, &sc_flags)); + CHECK(ret, krb5_ret_uint16(sp, &spnego_flags)); + ctx->flags = int_to_spnego_flags(spnego_flags); + + if (sc_flags & SC_MECH_TYPES) + CHECK(major, _gss_mg_ret_buffer(&minor, sp, &ctx->NegTokenInit_mech_types)); + if (sc_flags & SC_PREFERRED_MECH_TYPE) + CHECK(major, _gss_mg_ret_oid(&minor, sp, &ctx->preferred_mech_type)); + if (sc_flags & SC_SELECTED_MECH_TYPE) + CHECK(major, _gss_mg_ret_oid(&minor, sp, &ctx->selected_mech_type)); + if (sc_flags & SC_NEGOTIATED_MECH_TYPE) + CHECK(major, _gss_mg_ret_oid(&minor, sp, &ctx->negotiated_mech_type)); + + if (sc_flags & SC_NEGOTIATED_CTX_ID) { + CHECK(major, _gss_mg_ret_buffer(&minor, sp, &buf)); + CHECK(major, gss_import_sec_context(&minor, &buf, + &ctx->negotiated_ctx_id)); + gss_release_buffer(&minor, &buf); + } + + if (sc_flags & SC_MECH_FLAGS) + CHECK(ret, krb5_ret_uint32(sp, &ctx->mech_flags)); + if (sc_flags & SC_MECH_TIME_REC) + CHECK(ret, krb5_ret_uint32(sp, &ctx->mech_time_rec)); + else + ctx->mech_time_rec = GSS_C_INDEFINITE; + + if (sc_flags & SC_MECH_SRC_NAME) { + CHECK(major, _gss_mg_ret_buffer(&minor, sp, &buf)); + CHECK(major, gss_import_name(&minor, &buf, GSS_C_NT_EXPORT_NAME, + &ctx->mech_src_name)); + gss_release_buffer(&minor, &buf); + } + + if (sc_flags & SC_TARGET_NAME) { + CHECK(major, _gss_mg_ret_buffer(&minor, sp, &buf)); + CHECK(major, gss_import_name(&minor, &buf, GSS_C_NT_EXPORT_NAME, + &ctx->target_name)); + gss_release_buffer(&minor, &buf); + } + + if (sc_flags & SC_NEGOEX) { + uint8_t i, nschemes; + + CHECK(ret, krb5_ret_uint8(sp, &ctx->negoex_step)); + + CHECK(ret, krb5_ret_data(sp, &data)); + ctx->negoex_transcript = krb5_storage_emem(); + if (ctx->negoex_transcript == NULL) { + ret = ENOMEM; + goto fail; + } + + krb5_storage_set_byteorder(ctx->negoex_transcript, + KRB5_STORAGE_BYTEORDER_LE); + if (krb5_storage_write(ctx->negoex_transcript, + data.data, data.length) != data.length) { + ret = ENOMEM; + goto fail; + } + krb5_data_free(&data); + + CHECK(ret, krb5_ret_uint32(sp, &ctx->negoex_seqnum)); + + if (krb5_storage_read(sp, ctx->negoex_conv_id, + GUID_LENGTH) != GUID_LENGTH) { + ret = KRB5_BAD_MSIZE; + goto fail; + } + + CHECK(ret, krb5_ret_uint8(sp, &nschemes)); + for (i = 0; i < nschemes; i++) { + struct negoex_auth_mech *mech; + + CHECK(ret, ret_negoex_auth_mech(sp, &mech)); + HEIM_TAILQ_INSERT_TAIL(&ctx->negoex_mechs, mech, links); + } + } + + *ctxp = ctx; + +fail: + if (ret == 0 && GSS_ERROR(major)) + ret = minor ? minor : KRB5_BAD_MSIZE; + if (ret) + _gss_spnego_delete_sec_context(&minor, (gss_ctx_id_t *)&ctx, + GSS_C_NO_BUFFER); + krb5_data_free(&data); + gss_release_buffer(&minor, &buf); + + return ret; +} + +static krb5_error_code +store_spnego_context(krb5_storage *sp, gssspnego_ctx ctx) +{ + OM_uint32 major = GSS_S_COMPLETE, minor; + krb5_error_code ret = 0; + krb5_data data; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + uint16_t sc_flags = 0, spnego_flags; + + krb5_data_zero(&data); + + if (ctx->NegTokenInit_mech_types.length) + sc_flags |= SC_MECH_TYPES; + if (ctx->preferred_mech_type) + sc_flags |= SC_PREFERRED_MECH_TYPE; + if (ctx->selected_mech_type) + sc_flags |= SC_SELECTED_MECH_TYPE; + if (ctx->negotiated_mech_type) + sc_flags |= SC_NEGOTIATED_MECH_TYPE; + if (ctx->negotiated_ctx_id) + sc_flags |= SC_NEGOTIATED_CTX_ID; + if (ctx->mech_flags) + sc_flags |= SC_MECH_FLAGS; + if (ctx->mech_time_rec != GSS_C_INDEFINITE) + sc_flags |= SC_MECH_TIME_REC; + if (ctx->mech_src_name) + sc_flags |= SC_MECH_SRC_NAME; + if (ctx->target_name) + sc_flags |= SC_TARGET_NAME; + if (ctx->negoex_step) + sc_flags |= SC_NEGOEX; + + CHECK(ret, krb5_store_uint16(sp, sc_flags)); + spnego_flags = spnego_flags_to_int(ctx->flags); + CHECK(ret, krb5_store_uint16(sp, spnego_flags)); + + if (sc_flags & SC_MECH_TYPES) + CHECK(major, _gss_mg_store_buffer(&minor, sp, &ctx->NegTokenInit_mech_types)); + if (sc_flags & SC_PREFERRED_MECH_TYPE) + CHECK(major, _gss_mg_store_oid(&minor, sp, ctx->preferred_mech_type)); + if (sc_flags & SC_SELECTED_MECH_TYPE) + CHECK(major, _gss_mg_store_oid(&minor, sp, ctx->selected_mech_type)); + if (sc_flags & SC_NEGOTIATED_MECH_TYPE) + CHECK(major, _gss_mg_store_oid(&minor, sp, ctx->negotiated_mech_type)); + if (sc_flags & SC_NEGOTIATED_CTX_ID) { + CHECK(major, gss_export_sec_context(&minor, &ctx->negotiated_ctx_id, + &buf)); + CHECK(major, _gss_mg_store_buffer(&minor, sp, &buf)); + gss_release_buffer(&minor, &buf); + } + if (sc_flags & SC_MECH_FLAGS) + CHECK(ret, krb5_store_uint32(sp, ctx->mech_flags)); + if (sc_flags & SC_MECH_TIME_REC) + CHECK(ret, krb5_store_uint32(sp, ctx->mech_time_rec)); + if (sc_flags & SC_MECH_SRC_NAME) { + CHECK(major, gss_export_name(&minor, ctx->mech_src_name, &buf)); + CHECK(major, _gss_mg_store_buffer(&minor, sp, &buf)); + gss_release_buffer(&minor, &buf); + } + + if (sc_flags & SC_TARGET_NAME) { + CHECK(major, gss_export_name(&minor, ctx->target_name, &buf)); + CHECK(major, _gss_mg_store_buffer(&minor, sp, &buf)); + gss_release_buffer(&minor, &buf); + } + + if (sc_flags & SC_NEGOEX) { + uint32_t nschemes; + struct negoex_auth_mech *mech; + + CHECK(ret, krb5_store_uint8(sp, ctx->negoex_step)); + + if (ctx->negoex_transcript) { + CHECK(ret, krb5_storage_to_data(ctx->negoex_transcript, &data)); + } + CHECK(ret, krb5_store_data(sp, data)); + krb5_data_free(&data); + + CHECK(ret, krb5_store_uint32(sp, ctx->negoex_seqnum)); + CHECK(ret, krb5_store_bytes(sp, ctx->negoex_conv_id, GUID_LENGTH)); + + nschemes = 0; + HEIM_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) + nschemes++; + + if (nschemes > 0xff) { + ret = ERANGE; + goto fail; + } + CHECK(ret, krb5_store_uint8(sp, nschemes)); + + HEIM_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) + CHECK(ret, store_negoex_auth_mech(sp, mech)); + } + +fail: + if (ret == 0 && GSS_ERROR(major)) + ret = minor ? minor : KRB5_BAD_MSIZE; + krb5_data_free(&data); + gss_release_buffer(&minor, &buf); + + return ret; +} + +static krb5_error_code +ret_negoex_auth_mech(krb5_storage *sp, struct negoex_auth_mech **mechp) +{ + krb5_error_code ret; + OM_uint32 major = GSS_S_COMPLETE, minor; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + struct negoex_auth_mech *mech; + krb5_context context = _gss_mg_krb5_context(); + uint8_t snc_flags, negoex_flags; + + *mechp = NULL; + + mech = calloc(1, sizeof(*mech)); + if (mech == NULL) { + ret = ENOMEM; + goto fail; + } + + CHECK(ret, krb5_ret_uint8(sp, &snc_flags)); + CHECK(ret, krb5_ret_uint8(sp, &negoex_flags)); + if (negoex_flags & (1 << 0)) + mech->complete = 1; + if (negoex_flags & (1 << 1)) + mech->sent_checksum = 1; + if (negoex_flags & (1 << 2)) + mech->verified_checksum = 1; + + if (snc_flags & SNC_OID) + CHECK(major, _gss_mg_ret_oid(&minor, sp, &mech->oid)); + + if (krb5_storage_read(sp, mech->scheme, GUID_LENGTH) != GUID_LENGTH) { + ret = KRB5_BAD_MSIZE; + goto fail; + } + + if (snc_flags & SNC_MECH_CONTEXT) { + CHECK(major, _gss_mg_ret_buffer(&minor, sp, &buf)); + CHECK(major, gss_import_sec_context(&minor, &buf, + &mech->mech_context)); + gss_release_buffer(&minor, &buf); + } + + if (snc_flags & SNC_METADATA) + CHECK(major, _gss_mg_ret_buffer(&minor, sp, &mech->metadata)); + + *mechp = mech; + +fail: + if (ret == 0 && GSS_ERROR(major)) + ret = minor ? minor : KRB5_BAD_MSIZE; + if (ret) + _gss_negoex_release_auth_mech(context, mech); + gss_release_buffer(&minor, &buf); + + return ret; +} + +static krb5_error_code +store_negoex_auth_mech(krb5_storage *sp, struct negoex_auth_mech *mech) +{ + krb5_error_code ret; + OM_uint32 major = GSS_S_COMPLETE, minor; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + uint8_t negoex_flags = 0, snc_flags = 0; + + negoex_flags = 0; + if (mech->complete) + negoex_flags |= (1 << 0); + if (mech->sent_checksum) + negoex_flags |= (1 << 1); + if (mech->verified_checksum) + negoex_flags |= (1 << 2); + + if (mech->oid) + snc_flags |= SNC_OID; + if (mech->mech_context) + snc_flags |= SNC_MECH_CONTEXT; + if (mech->metadata.length) + snc_flags |= SNC_METADATA; + + CHECK(ret, krb5_store_uint8(sp, snc_flags)); + CHECK(ret, krb5_store_uint8(sp, negoex_flags)); + + if (snc_flags & SNC_OID) + CHECK(major, _gss_mg_store_oid(&minor, sp, mech->oid)); + + CHECK(ret, krb5_store_bytes(sp, mech->scheme, GUID_LENGTH)); + + if (snc_flags & SNC_MECH_CONTEXT) { + CHECK(major, gss_export_sec_context(&minor, &mech->mech_context, + &buf)); + CHECK(major, _gss_mg_store_buffer(&minor, sp, &buf)); + gss_release_buffer(&minor, &buf); + } + + if (snc_flags & SNC_METADATA) + CHECK(major, _gss_mg_store_buffer(&minor, sp, &mech->metadata)); + +fail: + if (ret == 0 && GSS_ERROR(major)) + ret = minor ? minor : KRB5_BAD_MSIZE; + gss_release_buffer(&minor, &buf); + + return ret; +} + +static uint16_t +spnego_flags_to_int(struct spnego_flags flags) +{ + uint16_t f = 0; + + if (flags.open) + f |= (1 << 0); + if (flags.local) + f |= (1 << 1); + if (flags.require_mic) + f |= (1 << 2); + if (flags.peer_require_mic) + f |= (1 << 3); + if (flags.sent_mic) + f |= (1 << 4); + if (flags.verified_mic) + f |= (1 << 5); + if (flags.safe_omit) + f |= (1 << 6); + if (flags.maybe_open) + f |= (1 << 7); + if (flags.seen_supported_mech) + f |= (1 << 8); + + return f; +} + +static struct spnego_flags +int_to_spnego_flags(uint16_t f) +{ + struct spnego_flags flags; + + memset(&flags, 0, sizeof(flags)); + + if (f & (1 << 0)) + flags.open = 1; + if (f & (1 << 1)) + flags.local = 1; + if (f & (1 << 2)) + flags.require_mic = 1; + if (f & (1 << 3)) + flags.peer_require_mic = 1; + if (f & (1 << 4)) + flags.sent_mic = 1; + if (f & (1 << 5)) + flags.verified_mic = 1; + if (f & (1 << 6)) + flags.safe_omit = 1; + if (f & (1 << 7)) + flags.maybe_open = 1; + if (f & (1 << 8)) + flags.seen_supported_mech = 1; + + return flags; +} diff --git a/third_party/heimdal/lib/gssapi/spnego/context_stubs.c b/third_party/heimdal/lib/gssapi/spnego/context_stubs.c new file mode 100644 index 0000000..638e90d --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/context_stubs.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego_locl.h" + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_process_context_token + (OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + gss_ctx_id_t context; + gssspnego_ctx ctx; + OM_uint32 ret; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + context = (gss_ctx_id_t)context_handle; + ctx = (gssspnego_ctx)context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ret = gss_process_context_token(minor_status, + ctx->negotiated_ctx_id, + token_buffer); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + + return _gss_spnego_internal_delete_sec_context(minor_status, + &context, + GSS_C_NO_BUFFER); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_delete_sec_context + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token + ) +{ + gssspnego_ctx ctx; + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + ctx = (gssspnego_ctx)*context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + return _gss_spnego_internal_delete_sec_context(minor_status, + context_handle, + output_token); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_context_time + (OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + OM_uint32 *time_rec + ) +{ + gssspnego_ctx ctx; + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_context_time(minor_status, + ctx->negotiated_ctx_id, + time_rec); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_get_mic + (OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_get_mic(minor_status, ctx->negotiated_ctx_id, + qop_req, message_buffer, message_token); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_verify_mic + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_verify_mic(minor_status, + ctx->negotiated_ctx_id, + message_buffer, + token_buffer, + qop_state); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_wrap(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_unwrap + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_unwrap(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_context ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + gssspnego_ctx ctx; + OM_uint32 maj_stat; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + maj_stat = gss_inquire_context(minor_status, + ctx->negotiated_ctx_id, + src_name, + targ_name, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + open_context); + + if (open_context) + *open_context = gssspnego_ctx_complete_p(ctx); + + return maj_stat; +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap_size_limit ( + OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_wrap_size_limit(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + req_output_size, + max_input_size); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ) +{ + gssspnego_ctx ctx; + OM_uint32 major_status; + + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_NO_CONTEXT; + + ctx = (gssspnego_ctx)*context_handle; + + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + /* + * Partial context export is only supported on the acceptor side, as we + * cannot represent the initiator function pointer state in an exported + * token, and also because it is mostly useful for acceptors which need + * to manage multiple initiator states. + */ + if (ctx->flags.local && !gssspnego_ctx_complete_p(ctx)) { + major_status = GSS_S_NO_CONTEXT; + goto out; + } + + major_status = _gss_spnego_export_sec_context_internal(minor_status, + ctx, + interprocess_token); + +out: + if (major_status == GSS_S_COMPLETE) + major_status = _gss_spnego_internal_delete_sec_context(minor_status, + context_handle, + GSS_C_NO_BUFFER); + else + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + return major_status; +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle + ) +{ + return _gss_spnego_import_sec_context_internal(minor_status, + interprocess_token, + (gssspnego_ctx *)context_handle); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + gss_OID_set mechs, names, n; + OM_uint32 ret, junk; + size_t i, j; + + *name_types = NULL; + + ret = _gss_spnego_indicate_mechs(minor_status, &mechs); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_create_empty_oid_set(minor_status, &names); + if (ret != GSS_S_COMPLETE) + goto out; + + for (i = 0; i < mechs->count; i++) { + ret = gss_inquire_names_for_mech(minor_status, + &mechs->elements[i], + &n); + if (ret) + continue; + + for (j = 0; j < n->count; j++) + gss_add_oid_set_member(minor_status, + &n->elements[j], + &names); + gss_release_oid_set(&junk, &n); + } + + ret = GSS_S_COMPLETE; + *name_types = names; +out: + + gss_release_oid_set(&junk, &mechs); + + return ret; +} + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_wrap_iov(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int * conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + gssspnego_ctx ctx = (gssspnego_ctx)context_handle; + + *minor_status = 0; + + if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return gss_wrap_iov(minor_status, ctx->negotiated_ctx_id, + conf_req_flag, qop_req, conf_state, + iov, iov_count); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + gssspnego_ctx ctx = (gssspnego_ctx)context_handle; + + *minor_status = 0; + + if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return gss_unwrap_iov(minor_status, + ctx->negotiated_ctx_id, + conf_state, qop_state, + iov, iov_count); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_wrap_iov_length(OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + gssspnego_ctx ctx = (gssspnego_ctx)context_handle; + + *minor_status = 0; + + if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return gss_wrap_iov_length(minor_status, ctx->negotiated_ctx_id, + conf_req_flag, qop_req, conf_state, + iov, iov_count); +} + +#if 0 +OM_uint32 GSSAPI_CALLCONV _gss_spnego_complete_auth_token + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + gss_buffer_t input_message_buffer) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_complete_auth_token(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer); +} +#endif + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_sec_context_by_oid + (OM_uint32 * minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_inquire_sec_context_by_oid(minor_status, + ctx->negotiated_ctx_id, + desired_object, + data_set); +} + +OM_uint32 GSSAPI_CALLCONV _gss_spnego_set_sec_context_option + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + /* + * Return GSS_S_UNAVAILABLE with a NULL context handle as at + * present no context options can be set globally on SPNEGO + * itself. Global mechanism context options are set directly + * on the mechanism; per-context context options are set below + * if ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT. + */ + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) + return GSS_S_UNAVAILABLE; + + ctx = (gssspnego_ctx)*context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_set_sec_context_option(minor_status, + &ctx->negotiated_ctx_id, + desired_object, + value); +} + + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return gss_pseudo_random(minor_status, + ctx->negotiated_ctx_id, + prf_key, + prf_in, + desired_output_len, + prf_out); +} diff --git a/third_party/heimdal/lib/gssapi/spnego/external.c b/third_party/heimdal/lib/gssapi/spnego/external.c new file mode 100644 index 0000000..2a5121e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/external.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * Copyright (c) 2018 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego_locl.h" +#include <gssapi_mech.h> + +/* + * RFC2478, SPNEGO: + * The security mechanism of the initial + * negotiation token is identified by the Object Identifier + * iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). + */ +static gss_mo_desc spnego_mo[] = { + { + GSS_C_MA_SASL_MECH_NAME, + GSS_MO_MA, + "SASL mech name", + rk_UNCONST("SPNEGO"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_NAME, + GSS_MO_MA, + "Mechanism name", + rk_UNCONST("SPNEGO"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_DESCRIPTION, + GSS_MO_MA, + "Mechanism description", + rk_UNCONST("Heimdal SPNEGO Mechanism"), + _gss_mo_get_ctx_as_string, + NULL + }, + { + GSS_C_MA_MECH_NEGO, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + }, + { + GSS_C_MA_MECH_PSEUDO, + GSS_MO_MA, + NULL, + NULL, + NULL, + NULL + } +}; + +static gssapi_mech_interface_desc spnego_mech = { + GMI_VERSION, + "spnego", + {6, rk_UNCONST("\x2b\x06\x01\x05\x05\x02") }, + GM_USE_MG_CRED | GM_USE_MG_NAME, + NULL, /* gm_acquire_cred */ + NULL, /* gm_release_cred */ + _gss_spnego_init_sec_context, + _gss_spnego_accept_sec_context, + _gss_spnego_process_context_token, + _gss_spnego_delete_sec_context, + _gss_spnego_context_time, + _gss_spnego_get_mic, + _gss_spnego_verify_mic, + _gss_spnego_wrap, + _gss_spnego_unwrap, + NULL, /* gm_display_status */ + NULL, /* gm_indicate_mechs */ + NULL, /* gm_compare_name */ + NULL, /* gm_display_name */ + NULL, /* gm_import_name */ + NULL, /* gm_export_name */ + NULL, /* gm_release_name */ + NULL, /* gm_inquire_cred */ + _gss_spnego_inquire_context, + _gss_spnego_wrap_size_limit, + NULL, /* gm_add_cred */ + NULL, /* gm_inquire_cred_by_mech */ + _gss_spnego_export_sec_context, + _gss_spnego_import_sec_context, + NULL, /* gm_spnego_inquire_names_for_mech */ + NULL, /* gm_spnego_inquire_mechs_for_name */ + NULL, /* gm_spnego_canonicalize_name */ + NULL, /* gm_spnego_duplicate_name */ + _gss_spnego_inquire_sec_context_by_oid, + NULL, /* gm_inquire_cred_by_oid */ + _gss_spnego_set_sec_context_option, + NULL, /* gm_set_cred_option */ + _gss_spnego_pseudo_random, + _gss_spnego_wrap_iov, + _gss_spnego_unwrap_iov, + _gss_spnego_wrap_iov_length, + NULL, + NULL, /* gm_export_cred */ + NULL, /* gm_import_cred */ + NULL, /* gm_acquire_cred_from */ + NULL, /* gm_acquire_cred_impersonate_name */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + spnego_mo, + sizeof(spnego_mo) / sizeof(spnego_mo[0]), + NULL, /* gm_localname */ + NULL, /* gm_authorize_localname */ + NULL, /* gm_display_name_ext */ + NULL, /* gm_inquire_name */ + NULL, /* gm_get_name_attribute */ + NULL, /* gm_set_name_attribute */ + NULL, /* gm_delete_name_attribute */ + NULL, /* gm_export_name_composite */ + NULL, /* gm_duplicate_cred */ + NULL, /* gm_add_cred_from */ + NULL, /* gm_store_cred_into */ + NULL, /* gm_query_mechanism_info */ + NULL, /* gm_query_meta_data */ + NULL, /* gm_exchange_meta_data */ + NULL, /* gm_store_cred_into2 */ + NULL /* gm_compat */ +}; + +gssapi_mech_interface +__gss_spnego_initialize(void) +{ + return &spnego_mech; +} + diff --git a/third_party/heimdal/lib/gssapi/spnego/init_sec_context.c b/third_party/heimdal/lib/gssapi/spnego/init_sec_context.c new file mode 100644 index 0000000..12ec0ea --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -0,0 +1,841 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego_locl.h" + +#define GSISC(name) \ +static \ +OM_uint32 name(OM_uint32 *, gss_const_cred_id_t, gssspnego_ctx, \ + gss_const_name_t, gss_const_OID, \ + OM_uint32, OM_uint32, const gss_channel_bindings_t, \ + gss_const_buffer_t, gss_buffer_t, \ + OM_uint32 *, OM_uint32 *) + +GSISC(spnego_initial); +GSISC(spnego_reply); +GSISC(wait_server_mic); +GSISC(step_completed); + + + /* + * Is target_name an sane target for `mech´. + */ + +static OM_uint32 +initiator_approved(OM_uint32 *minor_status, + void *userptr, + gss_const_name_t target_name, + gss_const_cred_id_t cred, + gss_OID mech) +{ + OM_uint32 min_stat, maj_stat; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_buffer_desc out; + struct gssspnego_optimistic_ctx *sel = userptr; + gss_OID negotiated_mech_type = GSS_C_NO_OID; + OM_uint32 flags = 0, time_rec = 0; + auth_scheme scheme; + int negoex = 0; + + maj_stat = gss_init_sec_context(&min_stat, + cred, + &ctx, + sel->target_name, + mech, + sel->req_flags, + sel->time_req, + sel->input_chan_bindings, + GSS_C_NO_BUFFER, + &negotiated_mech_type, + &out, + &flags, + &time_rec); + if (GSS_ERROR(maj_stat)) { + gss_mg_collect_error(mech, maj_stat, min_stat); + *minor_status = min_stat; + return maj_stat; + } + + if (gssspi_query_mechanism_info(&min_stat, mech, scheme) == GSS_S_COMPLETE) + negoex = 1; + + if (sel->preferred_mech_type == GSS_C_NO_OID) { + sel->preferred_mech_type = mech; + sel->negotiated_mech_type = negotiated_mech_type; + sel->optimistic_token = out; + sel->optimistic_flags = flags; + sel->optimistic_time_rec = time_rec; + sel->gssctx = ctx; + if (maj_stat == GSS_S_COMPLETE) + sel->complete = 1; + if (negoex) + memcpy(sel->scheme, scheme, GUID_LENGTH); + } else { + gss_release_buffer(&min_stat, &out); + gss_delete_sec_context(&min_stat, &ctx, NULL); + } + + maj_stat = GSS_S_COMPLETE; + + if (negoex) { + maj_stat = _gss_negoex_add_auth_mech(minor_status, sel->spnegoctx, + mech, scheme); + } + + return maj_stat; +} + +/* + * Send a reply. Note that we only need to send a reply if we + * need to send a MIC or a mechanism token. Otherwise, we can + * return an empty buffer. + * + * The return value of this will be returned to the API, so it + * must return GSS_S_CONTINUE_NEEDED if a token was generated. + */ +static OM_uint32 +make_reply(OM_uint32 *minor_status, + gssspnego_ctx ctx, + gss_buffer_t mech_token, + gss_buffer_t output_token) +{ + NegotiationToken nt; + gss_buffer_desc mic_buf; + OM_uint32 ret, minor; + size_t size; + NegStateEnum state; + + memset(&nt, 0, sizeof(nt)); + + nt.element = choice_NegotiationToken_negTokenResp; + + nt.u.negTokenResp.negState = NULL; + nt.u.negTokenResp.supportedMech = NULL; + + output_token->length = 0; + output_token->value = NULL; + + /* figure out our status */ + + if (ctx->flags.open) { + if (ctx->flags.verified_mic == 1 || ctx->flags.require_mic == 0) + state = accept_completed; + else + state = accept_incomplete; + } else { + state = accept_incomplete; + } + + if (mech_token->length == 0) { + nt.u.negTokenResp.responseToken = NULL; + } else { + ALLOC(nt.u.negTokenResp.responseToken, 1); + if (nt.u.negTokenResp.responseToken == NULL) { + free_NegotiationToken(&nt); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + nt.u.negTokenResp.responseToken->length = mech_token->length; + nt.u.negTokenResp.responseToken->data = mech_token->value; + mech_token->length = 0; + mech_token->value = NULL; + } + + /* + * XXX should limit when we send the MIC ? + */ + if (ctx->flags.open && ctx->flags.sent_mic == 0) { + + ctx->flags.sent_mic = 1; + + ret = gss_get_mic(minor_status, + ctx->negotiated_ctx_id, + 0, + &ctx->NegTokenInit_mech_types, + &mic_buf); + if (ret == GSS_S_COMPLETE) { + _gss_spnego_ntlm_reset_crypto(&minor, ctx, FALSE); + + ALLOC(nt.u.negTokenResp.mechListMIC, 1); + if (nt.u.negTokenResp.mechListMIC == NULL) { + gss_release_buffer(minor_status, &mic_buf); + free_NegotiationToken(&nt); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + nt.u.negTokenResp.mechListMIC->length = mic_buf.length; + nt.u.negTokenResp.mechListMIC->data = mic_buf.value; + /* mic_buf free()d with nt */ + } else if (ret == GSS_S_UNAVAILABLE) { + /* lets hope that its ok to not send te mechListMIC for broken mechs */ + nt.u.negTokenResp.mechListMIC = NULL; + ctx->flags.require_mic = 0; + } else { + free_NegotiationToken(&nt); + *minor_status = ENOMEM; + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + ret, *minor_status, + "SPNEGO failed to sign MIC"); + } + } else { + nt.u.negTokenResp.mechListMIC = NULL; + } + + ALLOC(nt.u.negTokenResp.negState, 1); + if (nt.u.negTokenResp.negState == NULL) { + free_NegotiationToken(&nt); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + *nt.u.negTokenResp.negState = state; + + ASN1_MALLOC_ENCODE(NegotiationToken, + output_token->value, output_token->length, + &nt, &size, ret); + free_NegotiationToken(&nt); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (state != accept_completed) + return GSS_S_CONTINUE_NEEDED; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +spnego_initial(OM_uint32 * minor_status, + gss_const_cred_id_t cred, + gssspnego_ctx ctx, + gss_const_name_t target_name, + gss_const_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + gss_const_buffer_t input_token, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + NegotiationToken nt; + int ret; + OM_uint32 sub, minor; + gss_buffer_desc mech_token; + size_t size = 0; + gss_buffer_desc data; + struct gssspnego_optimistic_ctx sel; + + *minor_status = 0; + + memset(&nt, 0, sizeof(nt)); + + if (target_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + sub = gss_duplicate_name(&minor, target_name, &ctx->target_name); + if (GSS_ERROR(sub)) { + *minor_status = minor; + return sub; + } + + nt.element = choice_NegotiationToken_negTokenInit; + + ctx->flags.local = 1; + + memset(&sel, 0, sizeof(sel)); + + sel.spnegoctx = ctx; + sel.target_name = ctx->target_name; + sel.preferred_mech_type = GSS_C_NO_OID; + sel.req_flags = req_flags; + sel.time_req = time_req; + sel.input_chan_bindings = (gss_channel_bindings_t)input_chan_bindings; + + sub = _gss_spnego_indicate_mechtypelist(&minor, + ctx->target_name, + req_flags, + initiator_approved, + &sel, + 0, + cred, + &nt.u.negTokenInit.mechTypes, + &ctx->preferred_mech_type); + if (GSS_ERROR(sub)) { + *minor_status = minor; + return sub; + } + + _gss_spnego_log_mechTypes(&nt.u.negTokenInit.mechTypes); + + nt.u.negTokenInit.reqFlags = NULL; + + if (gss_oid_equal(ctx->preferred_mech_type, GSS_NEGOEX_MECHANISM)) { + struct negoex_auth_mech *mech; + + sub = _gss_negoex_init(&minor, + &sel, + ctx, + (gss_cred_id_t)cred, + req_flags, + time_req, + input_chan_bindings, + GSS_C_NO_BUFFER, + &mech_token); + if (GSS_ERROR(sub)) { + free_NegotiationToken(&nt); + return gss_mg_set_error_string(GSS_C_NO_OID, sub, minor, + "NegoEx could not generate a context token"); + } + mech = _gss_negoex_negotiated_mech(ctx); + ctx->flags.maybe_open = mech && mech->complete; + gss_release_buffer(&minor, &sel.optimistic_token); + } else { + /* optimistic token from selection context */ + mech_token = sel.optimistic_token; + ctx->mech_flags = sel.optimistic_flags; + ctx->mech_time_rec = sel.optimistic_time_rec; + ctx->negotiated_mech_type = sel.negotiated_mech_type; + ctx->negotiated_ctx_id = sel.gssctx; + ctx->flags.maybe_open = sel.complete; + } + + if (ctx->preferred_mech_type == GSS_C_NO_OID) { + free_NegotiationToken(&nt); + *minor_status = 0; + return gss_mg_set_error_string(GSS_C_NO_OID, GSS_S_NO_CONTEXT, 0, + "SPNEGO could not find a preferred mechanism"); + } + + + if (mech_token.length != 0) { + ALLOC(nt.u.negTokenInit.mechToken, 1); + if (nt.u.negTokenInit.mechToken == NULL) { + free_NegotiationToken(&nt); + gss_release_buffer(&minor, &mech_token); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + nt.u.negTokenInit.mechToken->length = mech_token.length; + nt.u.negTokenInit.mechToken->data = malloc(mech_token.length); + if (nt.u.negTokenInit.mechToken->data == NULL && mech_token.length != 0) { + free_NegotiationToken(&nt); + gss_release_buffer(&minor, &mech_token); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(nt.u.negTokenInit.mechToken->data, mech_token.value, mech_token.length); + gss_release_buffer(&minor, &mech_token); + } else + nt.u.negTokenInit.mechToken = NULL; + + nt.u.negTokenInit.mechListMIC = NULL; + + { + MechTypeList mt; + + mt.len = nt.u.negTokenInit.mechTypes.len; + mt.val = nt.u.negTokenInit.mechTypes.val; + + ASN1_MALLOC_ENCODE(MechTypeList, + ctx->NegTokenInit_mech_types.value, + ctx->NegTokenInit_mech_types.length, + &mt, &size, ret); + if (ret) { + *minor_status = ret; + free_NegotiationToken(&nt); + return GSS_S_FAILURE; + } + } + + ASN1_MALLOC_ENCODE(NegotiationToken, data.value, data.length, &nt, &size, ret); + free_NegotiationToken(&nt); + if (ret) { + return GSS_S_FAILURE; + } + if (data.length != size) + abort(); + + sub = gss_encapsulate_token(&data, + GSS_SPNEGO_MECHANISM, + output_token); + free (data.value); + + if (sub) { + return sub; + } + + if (ret_flags) + *ret_flags = ctx->mech_flags; + if (time_rec) + *time_rec = ctx->mech_time_rec; + + ctx->initiator_state = spnego_reply; + + return GSS_S_CONTINUE_NEEDED; +} + +/* + * + */ + +static OM_uint32 +spnego_reply(OM_uint32 * minor_status, + gss_const_cred_id_t cred, + gssspnego_ctx ctx, + gss_const_name_t target_name, + gss_const_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + gss_const_buffer_t input_token, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + OM_uint32 ret, minor; + NegotiationToken resp; + gss_buffer_desc mech_output_token; + NegStateEnum negState; + + *minor_status = 0; + + output_token->length = 0; + output_token->value = NULL; + + mech_output_token.length = 0; + mech_output_token.value = NULL; + + ret = decode_NegotiationToken(input_token->value, input_token->length, + &resp, NULL); + if (ret) + return ret; + + /* The SPNEGO token must be a negTokenResp */ + if (resp.element != choice_NegotiationToken_negTokenResp) { + free_NegotiationToken(&resp); + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + /* + * When negState is absent, the actual state should be inferred from + * the state of the negotiated mechanism context. (RFC 4178 4.2.2.) + */ + if (resp.u.negTokenResp.negState != NULL) + negState = *resp.u.negTokenResp.negState; + else + negState = accept_incomplete; + + /* + * Pick up the mechanism that the acceptor selected, only pick up + * the first selection. + */ + + if (ctx->selected_mech_type == GSS_C_NO_OID && resp.u.negTokenResp.supportedMech) { + gss_OID_desc oid; + size_t len; + + ctx->flags.seen_supported_mech = 1; + + oid.length = (OM_uint32)der_length_oid(resp.u.negTokenResp.supportedMech); + oid.elements = malloc(oid.length); + if (oid.elements == NULL) { + free_NegotiationToken(&resp); + return GSS_S_BAD_MECH; + } + ret = der_put_oid(((uint8_t *)oid.elements) + oid.length - 1, + oid.length, + resp.u.negTokenResp.supportedMech, + &len); + if (ret || len != oid.length) { + free(oid.elements); + free_NegotiationToken(&resp); + return GSS_S_BAD_MECH; + } + + if (gss_oid_equal(GSS_SPNEGO_MECHANISM, &oid)) { + free(oid.elements); + free_NegotiationToken(&resp); + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, (*minor_status = EINVAL), + "SPNEGO acceptor picked SPNEGO??"); + } + + /* check if the acceptor took our optimistic token */ + if (gss_oid_equal(ctx->preferred_mech_type, &oid)) { + ctx->selected_mech_type = ctx->preferred_mech_type; + } else if (gss_oid_equal(ctx->preferred_mech_type, GSS_KRB5_MECHANISM) && + gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) { + /* mis-encoded asn1 type from msft servers */ + ctx->selected_mech_type = ctx->preferred_mech_type; + } else { + /* nope, lets start over */ + gss_delete_sec_context(&minor, &ctx->negotiated_ctx_id, + GSS_C_NO_BUFFER); + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + + if (gss_oid_equal(&oid, GSS_NEGOEX_MECHANISM)) + ctx->selected_mech_type = GSS_NEGOEX_MECHANISM; + else + ctx->selected_mech_type = _gss_mg_support_mechanism(&oid); + + /* XXX check that server pick a mechanism we proposed */ + if (ctx->selected_mech_type == GSS_C_NO_OID) { + free(oid.elements); + free_NegotiationToken(&resp); + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, (*minor_status = EINVAL), + "SPNEGO acceptor sent unsupported supportedMech"); + } + } + + _gss_spnego_log_mech("initiator selected mechanism", ctx->selected_mech_type); + + free(oid.elements); + + } else if (ctx->selected_mech_type == NULL) { + free_NegotiationToken(&resp); + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, (*minor_status = EINVAL), + "SPNEGO acceptor didn't send supportedMech"); + } + + /* if a token (of non zero length) pass to underlaying mech */ + if ((resp.u.negTokenResp.responseToken != NULL && resp.u.negTokenResp.responseToken->length) || + ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + gss_buffer_desc mech_input_token; + + if (resp.u.negTokenResp.responseToken) { + mech_input_token.length = resp.u.negTokenResp.responseToken->length; + mech_input_token.value = resp.u.negTokenResp.responseToken->data; + } else { + mech_input_token.length = 0; + mech_input_token.value = NULL; + } + + /* Fall through as if the negotiated mechanism + was requested explicitly */ + if (gss_oid_equal(ctx->selected_mech_type, GSS_NEGOEX_MECHANISM)) { + ret = _gss_negoex_init(&minor, + NULL, /* no optimistic token */ + ctx, + (gss_cred_id_t)cred, + req_flags, + time_req, + input_chan_bindings, + &mech_input_token, + &mech_output_token); + } else { + ret = gss_init_sec_context(&minor, + cred, + &ctx->negotiated_ctx_id, + ctx->target_name, + ctx->selected_mech_type, + req_flags, + time_req, + input_chan_bindings, + &mech_input_token, + &ctx->negotiated_mech_type, + &mech_output_token, + &ctx->mech_flags, + &ctx->mech_time_rec); + if (GSS_ERROR(ret)) { + gss_mg_collect_error(ctx->selected_mech_type, ret, minor); + } + } + /* + * If the acceptor rejected, we're out even if the inner context is + * now complete. Note that the rejection is not integrity-protected. + */ + if (negState == reject) + ret = GSS_S_BAD_MECH; + if (GSS_ERROR(ret)) { + free_NegotiationToken(&resp); + *minor_status = minor; + return ret; + } + if (ret == GSS_S_COMPLETE) { + ctx->flags.open = 1; + } + } else if (negState == reject) { + free_NegotiationToken(&resp); + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, (*minor_status = EPERM), + "SPNEGO acceptor rejected initiator token"); + } else if (negState == accept_completed) { + /* + * Note that the accept_completed isn't integrity-protected, but + * ctx->maybe_open can only be true if the inner context is fully + * established. + */ + if (ctx->flags.maybe_open) + ctx->flags.open = 1; + + if (!ctx->flags.open) { + free_NegotiationToken(&resp); + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, (*minor_status = EINVAL), + "SPNEGO acceptor sent acceptor complete, " + "but we are not complete yet"); + } + } + + if (negState == request_mic) { + ctx->flags.peer_require_mic = 1; + } + + if (ctx->flags.open && ctx->flags.verified_mic == 0) { + + ctx->flags.require_mic = 1; /* default is to require a MIC */ + ctx->flags.safe_omit = _gss_spnego_safe_omit_mechlist_mic(ctx); + + /* + * If the peer sent mechListMIC, require it to verify ... + */ + if (resp.u.negTokenResp.mechListMIC) { + heim_octet_string *m = resp.u.negTokenResp.mechListMIC; + + /* ...unless its a windows 2000 server that sends the + * responseToken inside the mechListMIC too. We only + * accept this condition if would have been safe to omit + * anyway. */ + + if (ctx->flags.safe_omit + && resp.u.negTokenResp.responseToken + && der_heim_octet_string_cmp(m, resp.u.negTokenResp.responseToken) == 0) + { + ctx->flags.require_mic = 0; + } + } + + } else { + ctx->flags.require_mic = 0; + } + + /* + * If we are supposed to check mic and have it, force checking now. + */ + + if (ctx->flags.require_mic && resp.u.negTokenResp.mechListMIC) { + + ret = _gss_spnego_verify_mechtypes_mic(minor_status, ctx, + resp.u.negTokenResp.mechListMIC); + if (ret) { + free_NegotiationToken(&resp); + return ret; + } + } + + /* + * Now that underlaying mech is open (conncted), we can figure out + * what nexd step to go to. + */ + + if (ctx->flags.open) { + + if (negState == accept_completed && ctx->flags.safe_omit) { + ctx->initiator_state = step_completed; + ret = GSS_S_COMPLETE; + } else if (ctx->flags.require_mic != 0 && ctx->flags.verified_mic == 0) { + ctx->initiator_state = wait_server_mic; + ret = GSS_S_CONTINUE_NEEDED; + } else { + ctx->initiator_state = step_completed; + ret = GSS_S_COMPLETE; + } + } + + if (negState != accept_completed || + ctx->initiator_state != step_completed || + mech_output_token.length) + { + OM_uint32 ret2; + ret2 = make_reply(minor_status, ctx, + &mech_output_token, + output_token); + if (ret2) + ret = ret2; + } + + free_NegotiationToken(&resp); + + gss_release_buffer(&minor, &mech_output_token); + + if (ret_flags) + *ret_flags = ctx->mech_flags; + if (time_rec) + *time_rec = ctx->mech_time_rec; + + return ret; +} + +static OM_uint32 +wait_server_mic(OM_uint32 * minor_status, + gss_const_cred_id_t cred, + gssspnego_ctx ctx, + gss_const_name_t target_name, + gss_const_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + gss_const_buffer_t input_token, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + OM_uint32 major_status; + NegotiationToken resp; + int ret; + + ret = decode_NegotiationToken(input_token->value, input_token->length, &resp, NULL); + if (ret) + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, ret, + "Failed to decode NegotiationToken"); + + if (resp.element != choice_NegotiationToken_negTokenResp + || resp.u.negTokenResp.negState == NULL + || *resp.u.negTokenResp.negState != accept_completed) + { + free_NegotiationToken(&resp); + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, (*minor_status = EINVAL), + "NegToken not accept_completed"); + } + + if (resp.u.negTokenResp.mechListMIC) { + major_status = _gss_spnego_verify_mechtypes_mic(minor_status, ctx, + resp.u.negTokenResp.mechListMIC); + } else if (ctx->flags.safe_omit == 0) { + free_NegotiationToken(&resp); + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_MECH, (*minor_status = EINVAL), + "Waiting for MIC, but its missing in server request"); + } else { + major_status = GSS_S_COMPLETE; + } + + free_NegotiationToken(&resp); + if (major_status != GSS_S_COMPLETE) + return major_status; + + ctx->flags.verified_mic = 1; + ctx->initiator_state = step_completed; + + if (ret_flags) + *ret_flags = ctx->mech_flags; + if (time_rec) + *time_rec = ctx->mech_time_rec; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +step_completed(OM_uint32 * minor_status, + gss_const_cred_id_t cred, + gssspnego_ctx ctx, + gss_const_name_t name, + gss_const_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + gss_const_buffer_t input_token, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + return gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + GSS_S_BAD_STATUS, (*minor_status = EINVAL), + "SPNEGO called got ISC call one too many"); +} + +OM_uint32 GSSAPI_CALLCONV +_gss_spnego_init_sec_context(OM_uint32 * minor_status, + gss_const_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + gss_const_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + gssspnego_ctx ctx; + OM_uint32 ret; + + if (*context_handle == GSS_C_NO_CONTEXT) { + ret = _gss_spnego_alloc_sec_context(minor_status, context_handle); + if (GSS_ERROR(ret)) + return ret; + + ctx = (gssspnego_ctx)*context_handle; + + ctx->initiator_state = spnego_initial; + } else { + ctx = (gssspnego_ctx)*context_handle; + } + + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + do { + ret = ctx->initiator_state(minor_status, initiator_cred_handle, ctx, target_name, + mech_type, req_flags, time_req, input_chan_bindings, input_token, + output_token, ret_flags, time_rec); + + } while (ret == GSS_S_COMPLETE && + ctx->initiator_state != step_completed && + output_token->length == 0); + + /* destroy context in case of error */ + if (GSS_ERROR(ret)) { + OM_uint32 junk; + _gss_spnego_internal_delete_sec_context(&junk, context_handle, GSS_C_NO_BUFFER); + } else { + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (actual_mech_type) + *actual_mech_type = ctx->negotiated_mech_type; + } + + return ret; +} + diff --git a/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c b/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c new file mode 100644 index 0000000..3f8aa5c --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c @@ -0,0 +1,1041 @@ +/* + * Copyright (C) 2011-2021 PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spnego_locl.h" + +/* + * The initial context token emitted by the initiator is a INITIATOR_NEGO + * message followed by zero or more INITIATOR_META_DATA tokens, and zero + * or one AP_REQUEST tokens. + * + * Upon receiving this, the acceptor computes the list of mutually supported + * authentication mechanisms and performs the metadata exchange. The output + * token is ACCEPTOR_NEGO followed by zero or more ACCEPTOR_META_DATA tokens, + * and zero or one CHALLENGE tokens. + * + * Once the metadata exchange is complete and a mechanism is selected, the + * selected mechanism's context token exchange continues with AP_REQUEST and + * CHALLENGE messages. + * + * Once the context token exchange is complete, VERIFY messages are sent to + * authenticate the entire exchange. + */ + +static OM_uint32 +buffer_set_to_crypto(OM_uint32 *minor, + krb5_context context, + gss_buffer_set_t buffers, + krb5_crypto *crypto) +{ + krb5_error_code ret; + krb5_keyblock keyblock; + OM_uint32 tmp; + + /* + * Returned keys must be in two buffers, with the key contents in + * the first and the enctype as a 32-bit little-endian integer in + * the second. + */ + if (buffers->count != 2 || + buffers->elements[1].length != sizeof(tmp)) { + *minor = (OM_uint32)NEGOEX_NO_VERIFY_KEY; + return GSS_S_FAILURE; + } + + if (*crypto != NULL) { + krb5_crypto_destroy(context, *crypto); + *crypto = NULL; + } + + keyblock.keyvalue.data = buffers->elements[0].value; + keyblock.keyvalue.length = buffers->elements[0].length; + _gss_mg_decode_le_uint32(buffers->elements[1].value, &tmp); + keyblock.keytype = tmp; + + ret = krb5_crypto_init(context, &keyblock, 0, crypto); + if (ret) { + *minor = ret; + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; +} + +#define NEGOEX_SIGN_KEY 1 +#define NEGOEX_VERIFY_KEY 2 +#define NEGOEX_BOTH_KEYS (NEGOEX_SIGN_KEY|NEGOEX_VERIFY_KEY) + +static OM_uint32 +get_session_keys(OM_uint32 *minor, + krb5_context context, + OM_uint32 flags, + struct negoex_auth_mech *mech) +{ + OM_uint32 major, tmpMinor; + gss_buffer_set_t buffers = GSS_C_NO_BUFFER_SET; + + if (flags & NEGOEX_SIGN_KEY) { + major = gss_inquire_sec_context_by_oid(&tmpMinor, mech->mech_context, + GSS_C_INQ_NEGOEX_KEY, &buffers); + if (major == GSS_S_COMPLETE) { + major = buffer_set_to_crypto(minor, context, + buffers, &mech->crypto); + _gss_secure_release_buffer_set(&tmpMinor, &buffers); + if (major != GSS_S_COMPLETE) + return major; + } + } + + if (flags & NEGOEX_VERIFY_KEY) { + major = gss_inquire_sec_context_by_oid(&tmpMinor, mech->mech_context, + GSS_C_INQ_NEGOEX_VERIFY_KEY, + &buffers); + if (major == GSS_S_COMPLETE) { + major = buffer_set_to_crypto(minor, context, + buffers, &mech->verify_crypto); + _gss_secure_release_buffer_set(&tmpMinor, &buffers); + if (major != GSS_S_COMPLETE) + return major; + } + } + + return GSS_S_COMPLETE; +} + +static OM_uint32 +emit_initiator_nego(OM_uint32 *minor, gssspnego_ctx ctx) +{ + uint8_t random[32]; + struct negoex_auth_mech *mech; + size_t i = 0; + + krb5_generate_random_block(random, sizeof(random)); + + HEIM_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) + _gss_negoex_log_auth_scheme(ctx->flags.local, ++i, mech->scheme); + + return _gss_negoex_add_nego_message(minor, ctx, INITIATOR_NEGO, random); +} + +static OM_uint32 +process_initiator_nego(OM_uint32 *minor, + gssspnego_ctx ctx, + struct negoex_message *messages, + size_t nmessages) +{ + struct nego_message *msg; + size_t i; + + heim_assert(!ctx->flags.local && ctx->negoex_step == 1, + "NegoEx INITIATOR_NEGO token received after first leg"); + + msg = _gss_negoex_locate_nego_message(messages, nmessages, INITIATOR_NEGO); + if (msg == NULL) { + *minor = (OM_uint32)NEGOEX_MISSING_NEGO_MESSAGE; + return GSS_S_DEFECTIVE_TOKEN; + } + + for (i = 0; i < msg->nschemes; i++) + _gss_negoex_log_auth_scheme(ctx->flags.local, i + 1, &msg->schemes[i * GUID_LENGTH]); + + _gss_negoex_restrict_auth_schemes(ctx, msg->schemes, msg->nschemes); + + return GSS_S_COMPLETE; +} + +static OM_uint32 +emit_acceptor_nego(OM_uint32 *minor, gssspnego_ctx ctx) +{ + uint8_t random[32]; + + krb5_generate_random_block(random, 32); + + return _gss_negoex_add_nego_message(minor, ctx, ACCEPTOR_NEGO, random); +} + +static OM_uint32 +process_acceptor_nego(OM_uint32 *minor, + gssspnego_ctx ctx, + struct negoex_message *messages, + size_t nmessages) +{ + struct nego_message *msg; + + msg = _gss_negoex_locate_nego_message(messages, nmessages, ACCEPTOR_NEGO); + if (msg == NULL) { + *minor = (OM_uint32)NEGOEX_MISSING_NEGO_MESSAGE; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* + * Reorder and prune our mech list to match the acceptor's list (or a + * subset of it). + */ + _gss_negoex_common_auth_schemes(ctx, msg->schemes, msg->nschemes); + + return GSS_S_COMPLETE; +} + +static void +query_meta_data(gssspnego_ctx ctx, + struct gssspnego_optimistic_ctx *opt, + gss_cred_id_t cred, + OM_uint32 req_flags) +{ + OM_uint32 major, minor; + struct negoex_auth_mech *p, *next; + + /* + * Note that if we received an optimistic context token from SPNEGO, + * then we will call QMD after ISC, rather than before. Mechanisms + * must be prepared to handle this and must not assume the context + * will be NULL on entry. + */ + HEIM_TAILQ_FOREACH_SAFE(p, &ctx->negoex_mechs, links, next) { + if (opt != NULL && memcmp(opt->scheme, p->scheme, GUID_LENGTH) == 0) + p->mech_context = opt->gssctx;; + + major = gssspi_query_meta_data(&minor, p->oid, cred, &p->mech_context, + ctx->target_name, req_flags, &p->metadata); + /* GSS_Query_meta_data failure removes mechanism from list. */ + if (major != GSS_S_COMPLETE) + _gss_negoex_delete_auth_mech(ctx, p); + } +} + +static void +exchange_meta_data(gssspnego_ctx ctx, + gss_cred_id_t cred, + OM_uint32 req_flags, + struct negoex_message *messages, + size_t nmessages) +{ + OM_uint32 major, minor; + struct negoex_auth_mech *mech; + enum message_type type; + struct exchange_message *msg; + uint32_t i; + + type = ctx->flags.local ? ACCEPTOR_META_DATA : INITIATOR_META_DATA; + + for (i = 0; i < nmessages; i++) { + if (messages[i].type != type) + continue; + msg = &messages[i].u.e; + + mech = _gss_negoex_locate_auth_scheme(ctx, msg->scheme); + if (mech == NULL) + continue; + + major = gssspi_exchange_meta_data(&minor, mech->oid, cred, + &mech->mech_context, + ctx->target_name, + req_flags, &msg->token); + /* GSS_Exchange_meta_data failure removes mechanism from list. */ + if (major != GSS_S_COMPLETE) + _gss_negoex_delete_auth_mech(ctx, mech); + } +} + +static void +release_mech_crypto(struct negoex_auth_mech *mech) +{ + krb5_context context = NULL; + + if (mech->crypto || mech->verify_crypto) + context = _gss_mg_krb5_context(); + + if (mech->crypto) { + krb5_crypto_destroy(context, mech->crypto); + mech->crypto = NULL; + } + + if (mech->verify_crypto) { + krb5_crypto_destroy(context, mech->verify_crypto); + mech->verify_crypto = NULL; + } + + mech->sent_checksum = FALSE; +} + +/* + * In the initiator, if we are processing the acceptor's first reply, discard + * the optimistic context if the acceptor ignored the optimistic token. If the + * acceptor continued the optimistic mech, discard all other mechs. + */ +static void +check_optimistic_result(gssspnego_ctx ctx, + struct negoex_message *messages, + size_t nmessages) +{ + struct negoex_auth_mech *mech; + OM_uint32 tmpMinor; + + heim_assert(ctx->flags.local && ctx->negoex_step == 2, + "NegoEx optimistic result should only be checked in second leg"); + + /* Do nothing if we didn't make an optimistic context. */ + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + if (mech == NULL || mech->mech_context == GSS_C_NO_CONTEXT) + return; + + /* + * If the acceptor used the optimistic token, it will send an acceptor + * token or a checksum (or both) in its first reply. + */ + if (_gss_negoex_locate_exchange_message(messages, nmessages, + CHALLENGE) != NULL || + _gss_negoex_locate_verify_message(messages, nmessages) != NULL) { + /* + * The acceptor continued the optimistic mech, and metadata exchange + * didn't remove it. Commit to this mechanism. + */ + _gss_negoex_select_auth_mech(ctx, mech); + } else { + /* + * The acceptor ignored the optimistic token. Restart the mech. + */ + gss_delete_sec_context(&tmpMinor, &mech->mech_context, GSS_C_NO_BUFFER); + release_mech_crypto(mech); + mech->complete = FALSE; + } +} + +/* Perform an initiator step of the underlying mechanism exchange. */ +static OM_uint32 +mech_init(OM_uint32 *minor, + struct gssspnego_optimistic_ctx *opt, + gssspnego_ctx ctx, + gss_cred_id_t cred, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + struct negoex_message *messages, + size_t nmessages, + gss_buffer_t output_token, + int *mech_error) +{ + OM_uint32 major, first_major = GSS_S_COMPLETE, first_minor = 0; + struct negoex_auth_mech *mech = NULL; + gss_buffer_t input_token = GSS_C_NO_BUFFER; + struct exchange_message *msg; + int first_mech; + krb5_context context = _gss_mg_krb5_context(); + + output_token->value = NULL; + output_token->length = 0; + + *mech_error = FALSE; + + /* Allow disabling of optimistic token for testing. */ + if (ctx->negoex_step == 1 && + secure_getenv("NEGOEX_NO_OPTIMISTIC_TOKEN") != NULL) + return GSS_S_COMPLETE; + + if (HEIM_TAILQ_EMPTY(&ctx->negoex_mechs)) { + *minor = (OM_uint32)NEGOEX_NO_AVAILABLE_MECHS; + return GSS_S_FAILURE; + } + + /* + * Get the input token. The challenge could be for the optimistic mech, + * which we might have discarded in metadata exchange, so ignore the + * challenge if it doesn't match the first auth mech. + */ + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + msg = _gss_negoex_locate_exchange_message(messages, nmessages, CHALLENGE); + if (msg != NULL && GUID_EQ(msg->scheme, mech->scheme)) + input_token = &msg->token; + + if (mech->complete) + return GSS_S_COMPLETE; + + first_mech = TRUE; + major = GSS_S_BAD_MECH; + + while (!HEIM_TAILQ_EMPTY(&ctx->negoex_mechs)) { + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + + /* + * If SPNEGO generated an optimistic token when probing available + * mechanisms, we can reuse it here. This avoids a potentially + * expensive and redundant call to GSS_Init_sec_context(); + */ + if (opt != NULL && memcmp(opt->scheme, mech->scheme, GUID_LENGTH) == 0) { + heim_assert(ctx->negoex_step == 1, + "SPNEGO optimistic token only valid for NegoEx first leg"); + + major = _gss_copy_buffer(minor, &opt->optimistic_token, output_token); + if (GSS_ERROR(major)) + return major; + + ctx->negotiated_mech_type = opt->negotiated_mech_type; + ctx->mech_flags = opt->optimistic_flags; + ctx->mech_time_rec = opt->optimistic_time_rec; + + mech->mech_context = opt->gssctx; + opt->gssctx = NULL; /* steal it */ + + mech->complete = opt->complete; + major = GSS_S_COMPLETE; + } else { + major = gss_init_sec_context(minor, cred, &mech->mech_context, + ctx->target_name, mech->oid, + req_flags, time_req, + input_chan_bindings, input_token, + &ctx->negotiated_mech_type, output_token, + &ctx->mech_flags, &ctx->mech_time_rec); + if (major == GSS_S_COMPLETE) + mech->complete = 1; + else if (GSS_ERROR(major)) { + gss_mg_collect_error(mech->oid, major, *minor); + *mech_error = TRUE; + } + } + if (!GSS_ERROR(major)) + return get_session_keys(minor, context, NEGOEX_BOTH_KEYS, mech); + + /* Remember the error we got from the first mech. */ + if (first_mech) { + first_major = major; + first_minor = *minor; + } + + /* If we still have multiple mechs to try, move on to the next one. */ + _gss_negoex_delete_auth_mech(ctx, mech); + first_mech = FALSE; + input_token = GSS_C_NO_BUFFER; + } + + if (HEIM_TAILQ_EMPTY(&ctx->negoex_mechs)) { + major = first_major; + *minor = first_minor; + } + + return major; +} + +/* Perform an acceptor step of the underlying mechanism exchange. */ +static OM_uint32 +mech_accept(OM_uint32 *minor, + gssspnego_ctx ctx, + gss_cred_id_t cred, + const gss_channel_bindings_t input_chan_bindings, + struct negoex_message *messages, + size_t nmessages, + gss_buffer_t output_token, + gss_cred_id_t *deleg_cred, + int *mech_error) +{ + OM_uint32 major, tmpMinor; + struct negoex_auth_mech *mech; + struct exchange_message *msg; + krb5_context context = _gss_mg_krb5_context(); + + heim_assert(!ctx->flags.local && !HEIM_TAILQ_EMPTY(&ctx->negoex_mechs), + "Acceptor NegoEx function called in wrong sequence"); + + *mech_error = FALSE; + + msg = _gss_negoex_locate_exchange_message(messages, nmessages, AP_REQUEST); + if (msg == NULL) { + /* + * No input token is okay on the first request or if the mech is + * complete. + */ + if (ctx->negoex_step == 1 || + HEIM_TAILQ_FIRST(&ctx->negoex_mechs)->complete) + return GSS_S_COMPLETE; + *minor = (OM_uint32)NEGOEX_MISSING_AP_REQUEST_MESSAGE; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ctx->negoex_step == 1) { + /* + * Ignore the optimistic token if it isn't for our most preferred + * mech. + */ + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + if (!GUID_EQ(msg->scheme, mech->scheme)) { + _gss_mg_log(10, "negoex ignored optimistic token as not for preferred mech"); + return GSS_S_COMPLETE; + } + } else { + /* The initiator has selected a mech; discard other entries. */ + mech = _gss_negoex_locate_auth_scheme(ctx, msg->scheme); + if (mech == NULL) { + *minor = (OM_uint32)NEGOEX_NO_AVAILABLE_MECHS; + return GSS_S_FAILURE; + } + _gss_negoex_select_auth_mech(ctx, mech); + } + + if (mech->complete) + return GSS_S_COMPLETE; + + if (ctx->mech_src_name != GSS_C_NO_NAME) + gss_release_name(&tmpMinor, &ctx->mech_src_name); + if (deleg_cred && *deleg_cred != GSS_C_NO_CREDENTIAL) + gss_release_cred(&tmpMinor, deleg_cred); + + major = gss_accept_sec_context(minor, &mech->mech_context, cred, + &msg->token, input_chan_bindings, + &ctx->mech_src_name, &ctx->negotiated_mech_type, + output_token, &ctx->mech_flags, + &ctx->mech_time_rec, deleg_cred); + if (major == GSS_S_COMPLETE) + mech->complete = 1; + + if (!GSS_ERROR(major)) { + if (major == GSS_S_COMPLETE && + !gss_oid_equal(ctx->negotiated_mech_type, mech->oid)) + _gss_mg_log(1, "negoex client didn't send the mech they said they would"); + + major = get_session_keys(minor, context, NEGOEX_BOTH_KEYS, mech); + } else if (ctx->negoex_step == 1) { + gss_mg_collect_error(ctx->negotiated_mech_type, major, *minor); + *mech_error = TRUE; + + /* This was an optimistic token; pretend this never happened. */ + major = GSS_S_COMPLETE; + *minor = 0; + gss_release_buffer(&tmpMinor, output_token); + gss_delete_sec_context(&tmpMinor, &mech->mech_context, GSS_C_NO_BUFFER); + } + + return major; +} + +static krb5_keyusage +verify_keyusage(gssspnego_ctx ctx, int make_checksum) +{ + /* Of course, these are the wrong way around in the spec. */ + return (ctx->flags.local ^ !make_checksum) ? + NEGOEX_KEYUSAGE_ACCEPTOR_CHECKSUM : NEGOEX_KEYUSAGE_INITIATOR_CHECKSUM; +} + +static OM_uint32 +verify_key_flags(gssspnego_ctx ctx, int make_checksum) +{ + return (ctx->flags.local ^ make_checksum) ? + NEGOEX_SIGN_KEY : NEGOEX_VERIFY_KEY; +} + +static OM_uint32 +verify_checksum(OM_uint32 *minor, + gssspnego_ctx ctx, + struct negoex_message *messages, + size_t nmessages, + gss_const_buffer_t input_token, + int *send_alert_out) +{ + krb5_error_code ret; + struct negoex_auth_mech *mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + struct verify_message *msg; + krb5_context context = _gss_mg_krb5_context(); + krb5_crypto_iov iov[3]; + krb5_keyusage usage = verify_keyusage(ctx, FALSE); + + *send_alert_out = FALSE; + heim_assert(mech != NULL, "Invalid null mech when verifying NegoEx checksum"); + + /* + * The other party may not be ready to send a verify token yet, or (in the + * first initiator step) may send one for a mechanism we don't support. + */ + msg = _gss_negoex_locate_verify_message(messages, nmessages); + if (msg == NULL || !GUID_EQ(msg->scheme, mech->scheme)) + return GSS_S_COMPLETE; + + /* + * Last chance attempt to obtain session key for imported exported partial + * contexts (which do not carry the session key at the NegoEx layer). + */ + if (mech->verify_crypto == NULL) + get_session_keys(minor, context, verify_key_flags(ctx, FALSE), mech); + + /* + * A recoverable error may cause us to be unable to verify a token from the + * other party. In this case we should send an alert. + */ + if (mech->verify_crypto == NULL) { + *send_alert_out = TRUE; + return GSS_S_COMPLETE; + } + + if (!krb5_checksum_is_keyed(context, msg->cksum_type)) { + *minor = (OM_uint32)NEGOEX_INVALID_CHECKSUM; + return GSS_S_BAD_SIG; + } + + /* + * Verify the checksum over the existing transcript and the portion of the + * input token leading up to the verify message. + */ + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + ret = krb5_storage_to_data(ctx->negoex_transcript, &iov[0].data); + if (ret) { + *minor = ret; + return GSS_S_FAILURE; + } + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data.data = input_token->value; + iov[1].data.length = msg->offset_in_token; + + iov[2].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[2].data.data = (uint8_t *)msg->cksum; + iov[2].data.length = msg->cksum_len; + + ret = krb5_verify_checksum_iov(context, mech->verify_crypto, usage, + iov, sizeof(iov) / sizeof(iov[0]), NULL); + if (ret == 0) + mech->verified_checksum = TRUE; + else + *minor = ret; + + krb5_data_free(&iov[0].data); + + return (ret == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +static OM_uint32 +make_checksum(OM_uint32 *minor, gssspnego_ctx ctx) +{ + krb5_error_code ret; + krb5_context context = _gss_mg_krb5_context(); + krb5_data d; + krb5_keyusage usage = verify_keyusage(ctx, TRUE); + krb5_checksum cksum; + struct negoex_auth_mech *mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + OM_uint32 major; + + heim_assert(mech != NULL, "Invalid null mech when making NegoEx checksum"); + + if (mech->crypto == NULL) { + if (mech->complete) { + /* + * Last chance attempt to obtain session key for imported exported partial + * contexts (which do not carry the session key at the NegoEx layer). + */ + get_session_keys(minor, context, verify_key_flags(ctx, TRUE), mech); + if (mech->crypto == NULL) { + *minor = (OM_uint32)NEGOEX_NO_VERIFY_KEY; + return GSS_S_UNAVAILABLE; + } + } else { + return GSS_S_COMPLETE; + } + } + + ret = krb5_storage_to_data(ctx->negoex_transcript, &d); + if (ret) { + *minor = ret; + return GSS_S_FAILURE; + } + + ret = krb5_create_checksum(context, mech->crypto, + usage, 0, d.data, d.length, &cksum); + krb5_data_free(&d); + if (ret) { + *minor = ret; + return GSS_S_FAILURE; + } + + major = _gss_negoex_add_verify_message(minor, ctx, mech->scheme, + cksum.cksumtype, + cksum.checksum.data, + cksum.checksum.length); + free_Checksum(&cksum); + + if (major == GSS_S_COMPLETE) + mech->sent_checksum = TRUE; + + return major; +} + +/* + * If the other side sent a VERIFY_NO_KEY pulse alert, clear the checksum state + * on the mechanism so that we send another VERIFY message. + */ +static void +process_alerts(gssspnego_ctx ctx, + struct negoex_message *messages, + uint32_t nmessages) +{ + struct alert_message *msg; + struct negoex_auth_mech *mech; + + msg = _gss_negoex_locate_alert_message(messages, nmessages); + if (msg != NULL && msg->verify_no_key) { + mech = _gss_negoex_locate_auth_scheme(ctx, msg->scheme); + if (mech != NULL) + release_mech_crypto(mech); + } +} + +static OM_uint32 +make_output_token(OM_uint32 *minor, + gssspnego_ctx ctx, + gss_buffer_t mech_output_token, + int send_alert, + gss_buffer_t output_token) +{ + OM_uint32 major, tmpMinor; + struct negoex_auth_mech *mech; + enum message_type type; + off_t old_transcript_len; + + output_token->length = 0; + output_token->value = NULL; + + old_transcript_len = krb5_storage_seek(ctx->negoex_transcript, 0, SEEK_CUR); + + /* + * If the mech is complete and we previously sent a checksum, we just + * processed the last leg and don't need to send another token. + */ + if (mech_output_token->length == 0 && + HEIM_TAILQ_FIRST(&ctx->negoex_mechs)->sent_checksum) + return GSS_S_COMPLETE; + + if (ctx->negoex_step == 1) { + if (ctx->flags.local) + major = emit_initiator_nego(minor, ctx); + else + major = emit_acceptor_nego(minor, ctx); + if (major != GSS_S_COMPLETE) + return major; + + type = ctx->flags.local ? INITIATOR_META_DATA : ACCEPTOR_META_DATA; + HEIM_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) { + if (mech->metadata.length > 0) { + major = _gss_negoex_add_exchange_message(minor, ctx, + type, mech->scheme, + &mech->metadata); + if (major != GSS_S_COMPLETE) + return major; + } + } + } + + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + + if (mech_output_token->length > 0) { + type = ctx->flags.local ? AP_REQUEST : CHALLENGE; + major = _gss_negoex_add_exchange_message(minor, ctx, + type, mech->scheme, + mech_output_token); + if (major != GSS_S_COMPLETE) + return major; + } + + if (send_alert) { + major = _gss_negoex_add_verify_no_key_alert(minor, ctx, mech->scheme); + if (major != GSS_S_COMPLETE) + return major; + } + + /* Try to add a VERIFY message if we haven't already done so. */ + if (!mech->sent_checksum) { + major = make_checksum(minor, ctx); + if (major != GSS_S_COMPLETE) + return major; + } + + heim_assert(ctx->negoex_transcript != NULL, "NegoEx context uninitialized"); + + output_token->length = + krb5_storage_seek(ctx->negoex_transcript, 0, SEEK_CUR) - old_transcript_len; + output_token->value = malloc(output_token->length); + if (output_token->value == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + krb5_storage_seek(ctx->negoex_transcript, old_transcript_len, SEEK_SET); + + if (krb5_storage_read(ctx->negoex_transcript, + output_token->value, + output_token->length) != output_token->length) { + *minor = ERANGE; + gss_release_buffer(&tmpMinor, output_token); + return GSS_S_FAILURE; + } + + krb5_storage_seek(ctx->negoex_transcript, 0, SEEK_END); + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gss_negoex_init(OM_uint32 *minor, + struct gssspnego_optimistic_ctx *opt, + gssspnego_ctx ctx, + gss_cred_id_t cred, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + gss_const_buffer_t input_token, + gss_buffer_t output_token) +{ + OM_uint32 major, tmpMinor; + gss_buffer_desc mech_output_token = GSS_C_EMPTY_BUFFER; + struct negoex_message *messages = NULL; + struct negoex_auth_mech *mech; + size_t nmessages = 0; + int send_alert = FALSE, mech_error = FALSE; + + output_token->length = 0; + output_token->value = NULL; + + if (ctx->negoex_step == 0 && input_token != GSS_C_NO_BUFFER && + input_token->length != 0) + return GSS_S_DEFECTIVE_TOKEN; + + major = _gss_negoex_begin(minor, ctx); + if (major != GSS_S_COMPLETE) + goto cleanup; + + ctx->negoex_step++; + + if (input_token != GSS_C_NO_BUFFER && input_token->length > 0) { + major = _gss_negoex_parse_token(minor, ctx, input_token, + &messages, &nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + } + + process_alerts(ctx, messages, nmessages); + + if (ctx->negoex_step == 1) { + /* Choose a random conversation ID. */ + krb5_generate_random_block(ctx->negoex_conv_id, GUID_LENGTH); + + /* Query each mech for its metadata (this may prune the mech list). */ + query_meta_data(ctx, opt, cred, req_flags); + } else if (ctx->negoex_step == 2) { + /* See if the mech processed the optimistic token. */ + check_optimistic_result(ctx, messages, nmessages); + + /* Pass the acceptor metadata to each mech to prune the list. */ + exchange_meta_data(ctx, cred, req_flags, messages, nmessages); + + /* Process the ACCEPTOR_NEGO message. */ + major = process_acceptor_nego(minor, ctx, messages, nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + } + + /* + * Process the input token and/or produce an output token. This may prune + * the mech list, but on success there will be at least one mech entry. + */ + major = mech_init(minor, opt, ctx, cred, req_flags, time_req, + input_chan_bindings, messages, nmessages, + &mech_output_token, &mech_error); + if (major != GSS_S_COMPLETE) + goto cleanup; + heim_assert(!HEIM_TAILQ_EMPTY(&ctx->negoex_mechs), + "Invalid empty NegoEx mechanism list"); + + /* + * At this point in step 2 we have performed the metadata exchange and + * chosen a mech we can use, so discard any fallback mech entries. + */ + if (ctx->negoex_step == 2) + _gss_negoex_select_auth_mech(ctx, HEIM_TAILQ_FIRST(&ctx->negoex_mechs)); + + major = verify_checksum(minor, ctx, messages, nmessages, input_token, + &send_alert); + if (major != GSS_S_COMPLETE) + goto cleanup; + + if (input_token != GSS_C_NO_BUFFER) { + if (krb5_storage_write(ctx->negoex_transcript, + input_token->value, + input_token->length) != input_token->length) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + } + + major = make_output_token(minor, ctx, &mech_output_token, send_alert, + output_token); + if (major != GSS_S_COMPLETE) + goto cleanup; + + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + major = (mech->complete && mech->verified_checksum) ? GSS_S_COMPLETE : + GSS_S_CONTINUE_NEEDED; + +cleanup: + free(messages); + gss_release_buffer(&tmpMinor, &mech_output_token); + _gss_negoex_end(ctx); + + if (GSS_ERROR(major)) { + if (!mech_error) { + krb5_context context = _gss_mg_krb5_context(); + const char *emsg = krb5_get_error_message(context, *minor); + + gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + major, *minor, + "NegoEx failed to initialize security context: %s", + emsg); + krb5_free_error_message(context, emsg); + } + + _gss_negoex_release_context(ctx); + } + + return major; +} + +OM_uint32 +_gss_negoex_accept(OM_uint32 *minor, + gssspnego_ctx ctx, + gss_cred_id_t cred, + gss_const_buffer_t input_token, + const gss_channel_bindings_t input_chan_bindings, + gss_buffer_t output_token, + gss_cred_id_t *deleg_cred) +{ + OM_uint32 major, tmpMinor; + gss_buffer_desc mech_output_token = GSS_C_EMPTY_BUFFER; + struct negoex_message *messages = NULL; + struct negoex_auth_mech *mech; + size_t nmessages; + int send_alert = FALSE, mech_error = FALSE; + + output_token->length = 0; + output_token->value = NULL; + if (deleg_cred) + *deleg_cred = GSS_C_NO_CREDENTIAL; + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + major = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + major = _gss_negoex_begin(minor, ctx); + if (major != GSS_S_COMPLETE) + goto cleanup; + + ctx->negoex_step++; + + major = _gss_negoex_parse_token(minor, ctx, input_token, + &messages, &nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + + process_alerts(ctx, messages, nmessages); + + if (ctx->negoex_step == 1) { + /* + * Read the INITIATOR_NEGO message to prune the candidate mech list. + */ + major = process_initiator_nego(minor, ctx, messages, nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + + /* + * Pass the initiator metadata to each mech to prune the list, and + * query each mech for its acceptor metadata (which may also prune the + * list). + */ + exchange_meta_data(ctx, cred, 0, messages, nmessages); + query_meta_data(ctx, NULL, cred, 0); + + if (HEIM_TAILQ_EMPTY(&ctx->negoex_mechs)) { + *minor = (OM_uint32)NEGOEX_NO_AVAILABLE_MECHS; + major = GSS_S_FAILURE; + goto cleanup; + } + } + + /* + * Process the input token and possibly produce an output token. This may + * prune the list to a single mech. Continue on error if an output token + * is generated, so that we send the token to the initiator. + */ + major = mech_accept(minor, ctx, cred, input_chan_bindings, + messages, nmessages, &mech_output_token, + deleg_cred, &mech_error); + if (major != GSS_S_COMPLETE && mech_output_token.length == 0) + goto cleanup; + + if (major == GSS_S_COMPLETE) { + major = verify_checksum(minor, ctx, messages, nmessages, input_token, + &send_alert); + if (major != GSS_S_COMPLETE) + goto cleanup; + } + + if (krb5_storage_write(ctx->negoex_transcript, + input_token->value, + input_token->length) != input_token->length) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + + major = make_output_token(minor, ctx, &mech_output_token, send_alert, + output_token); + if (major != GSS_S_COMPLETE) + goto cleanup; + + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + major = (mech->complete && mech->verified_checksum) ? GSS_S_COMPLETE : + GSS_S_CONTINUE_NEEDED; + +cleanup: + free(messages); + gss_release_buffer(&tmpMinor, &mech_output_token); + _gss_negoex_end(ctx); + + if (GSS_ERROR(major)) { + if (!mech_error) { + krb5_context context = _gss_mg_krb5_context(); + const char *emsg = krb5_get_error_message(context, *minor); + + gss_mg_set_error_string(GSS_SPNEGO_MECHANISM, + major, *minor, + "NegoEx failed to accept security context: %s", + emsg); + krb5_free_error_message(context, emsg); + } + + _gss_negoex_release_context(ctx); + } + + return major; +} diff --git a/third_party/heimdal/lib/gssapi/spnego/negoex_err.et b/third_party/heimdal/lib/gssapi/spnego/negoex_err.et new file mode 100644 index 0000000..99a8a2e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/negoex_err.et @@ -0,0 +1,25 @@ +# +# NegoEx error messages +# + +id "$Id$" + +error_table ngex + +prefix NEGOEX + +error_code INVALID_MESSAGE_SIGNATURE, "Invalid NegoEx signature" +error_code INVALID_MESSAGE_TYPE, "Invalid NegoEx message type" +error_code INVALID_MESSAGE_SIZE, "Invalid NegoEx message size" +error_code INVALID_CONVERSATION_ID, "Invalid NegoEx conversation ID" +error_code AUTH_SCHEME_NOT_FOUND, "NegoEx authentication scheme not found" +error_code MISSING_NEGO_MESSAGE, "Missing NegoEx negotiate message" +error_code MISSING_AP_REQUEST_MESSAGE, "Missing NegoEx authentication protocol request message" +error_code NO_AVAILABLE_MECHS, "No mutually supported NegoEx authentication schemes" +error_code NO_VERIFY_KEY, "No NegoEx verify key" +error_code UNKNOWN_CHECKSUM_SCHEME, "Unknown NegoEx checksum scheme" +error_code INVALID_CHECKSUM, "Invalid NegoEx checksum" +error_code UNSUPPORTED_CRITICAL_EXTENSION, "Unsupported critical NegoEx extension" +error_code UNSUPPORTED_VERSION, "Unsupported NegoEx version" +error_code MESSAGE_OUT_OF_SEQUENCE, "NegoEx message out of sequence" + diff --git a/third_party/heimdal/lib/gssapi/spnego/negoex_locl.h b/third_party/heimdal/lib/gssapi/spnego/negoex_locl.h new file mode 100644 index 0000000..3e0d29a --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/negoex_locl.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2011-2019 PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NEGOEX_LOCL_H +#define NEGOEX_LOCL_H + +#include <negoex_err.h> + +struct gssspnego_ctx_desc; + +#define MESSAGE_SIGNATURE 0x535458454F47454EULL + +#define EXTENSION_LENGTH 12 + +#define EXTENSION_FLAG_CRITICAL 0x80000000 + +#define CHECKSUM_SCHEME_RFC3961 1 + +#define NEGOEX_KEYUSAGE_INITIATOR_CHECKSUM 23 +#define NEGOEX_KEYUSAGE_ACCEPTOR_CHECKSUM 25 + +#define CHECKSUM_HEADER_LENGTH 20 + +#define GUID_LENGTH 16 + +typedef uint8_t auth_scheme[GUID_LENGTH]; +typedef uint8_t conversation_id[GUID_LENGTH]; +#define GUID_EQ(a, b) (memcmp(a, b, GUID_LENGTH) == 0) + +#define NEGO_MESSAGE_HEADER_LENGTH 96 +#define EXCHANGE_MESSAGE_HEADER_LENGTH 64 +#define VERIFY_MESSAGE_HEADER_LENGTH 80 +#define ALERT_MESSAGE_HEADER_LENGTH 72 +#define ALERT_LENGTH 12 +#define ALERT_PULSE_LENGTH 8 + +#define ALERT_TYPE_PULSE 1 +#define ALERT_VERIFY_NO_KEY 1 + +enum message_type { + INITIATOR_NEGO = 0, /* NEGO_MESSAGE */ + ACCEPTOR_NEGO, /* NEGO_MESSAGE */ + INITIATOR_META_DATA, /* EXCHANGE_MESSAGE */ + ACCEPTOR_META_DATA, /* EXCHANGE_MESSAGE */ + CHALLENGE, /* EXCHANGE_MESSAGE */ + AP_REQUEST, /* EXCHANGE_MESSAGE */ + VERIFY, /* VERIFY_MESSAGE */ + ALERT, /* ALERT */ +}; + +struct nego_message { + uint8_t random[32]; + const uint8_t *schemes; + uint16_t nschemes; +}; + +struct exchange_message { + auth_scheme scheme; + gss_buffer_desc token; +}; + +struct verify_message { + auth_scheme scheme; + uint32_t cksum_type; + const uint8_t *cksum; + size_t cksum_len; + size_t offset_in_token; +}; + +struct alert_message { + auth_scheme scheme; + int verify_no_key; +}; + +struct negoex_message { + uint32_t type; + union { + struct nego_message n; + struct exchange_message e; + struct verify_message v; + struct alert_message a; + } u; +}; + +struct negoex_auth_mech { + HEIM_TAILQ_ENTRY(negoex_auth_mech) links; + gss_OID oid; + auth_scheme scheme; + gss_ctx_id_t mech_context; + gss_buffer_desc metadata; + krb5_crypto crypto; + krb5_crypto verify_crypto; + int complete; + int sent_checksum; + int verified_checksum; +}; + +#define NEGOEX_LOG_LEVEL 10 + +#endif /* NEGOEX_LOCL_H */ diff --git a/third_party/heimdal/lib/gssapi/spnego/negoex_util.c b/third_party/heimdal/lib/gssapi/spnego/negoex_util.c new file mode 100644 index 0000000..aac09d4 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/negoex_util.c @@ -0,0 +1,1042 @@ +/* + * Copyright (C) 2011-2019 PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spnego_locl.h" + +/* + * SPNEGO expects to find the active mech context in ctx->negotiated_ctx_id, + * but the metadata exchange APIs force us to have one mech context per mech + * entry. To address this mismatch, move the active mech context (if we have + * one) to ctx->negotiated_ctx_id at the end of NegoEx processing. + */ +void +_gss_negoex_end(gssspnego_ctx ctx) +{ + struct negoex_auth_mech *mech; + + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + if (mech == NULL || mech->mech_context == GSS_C_NO_CONTEXT) + return; + + heim_assert(ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT, + "SPNEGO/NegoEx context mismatch"); + ctx->negotiated_ctx_id = mech->mech_context; + mech->mech_context = GSS_C_NO_CONTEXT; +} + +OM_uint32 +_gss_negoex_begin(OM_uint32 *minor, gssspnego_ctx ctx) +{ + struct negoex_auth_mech *mech; + + if (ctx->negoex_transcript != NULL) { + /* + * The context is already initialized for NegoEx; undo what + * _gss_negoex_end() did, if applicable. + */ + if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { + mech = HEIM_TAILQ_FIRST(&ctx->negoex_mechs); + heim_assert(mech != NULL && mech->mech_context == GSS_C_NO_CONTEXT, + "NegoEx/SPNEGO context mismatch"); + mech->mech_context = ctx->negotiated_ctx_id; + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + } + return GSS_S_COMPLETE; + } + + ctx->negoex_transcript = krb5_storage_emem(); + if (ctx->negoex_transcript == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + krb5_storage_set_byteorder(ctx->negoex_transcript, + KRB5_STORAGE_BYTEORDER_LE); + + return GSS_S_COMPLETE; +} + +static void +release_all_mechs(gssspnego_ctx ctx, krb5_context context) +{ + struct negoex_auth_mech *mech, *next; + + HEIM_TAILQ_FOREACH_SAFE(mech, &ctx->negoex_mechs, links, next) { + _gss_negoex_release_auth_mech(context, mech); + } + + HEIM_TAILQ_INIT(&ctx->negoex_mechs); +} + +void +_gss_negoex_release_context(gssspnego_ctx ctx) +{ + krb5_context context = _gss_mg_krb5_context(); + + if (ctx->negoex_transcript != NULL) { + krb5_storage_free(ctx->negoex_transcript); + ctx->negoex_transcript = NULL; + } + + release_all_mechs(ctx, context); +} + +static int +guid_to_string(const uint8_t guid[16], char *buffer, size_t bufsiz) +{ + uint32_t data1; + uint16_t data2, data3; + + _gss_mg_decode_le_uint32(&guid[0], &data1); + _gss_mg_decode_le_uint16(&guid[4], &data2); + _gss_mg_decode_le_uint16(&guid[6], &data3); + + return snprintf(buffer, bufsiz, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + data1, data2, data3, guid[8], guid[9], guid[10], guid[11], + guid[12], guid[13], guid[14], guid[15]); +} + +void +_gss_negoex_log_auth_scheme(int initiator, + int index, + const auth_scheme scheme) +{ + char scheme_str[37]; + + guid_to_string(scheme, scheme_str, sizeof(scheme_str)); + + _gss_mg_log(NEGOEX_LOG_LEVEL, + "negoex: %s authentication scheme %d %s", + initiator ? "proposing" : "received", index, scheme_str); +} + +void +_gss_negoex_log_message(int direction, + enum message_type type, + const conversation_id conv_id, + unsigned int seqnum, + unsigned int header_len, + unsigned int msg_len) +{ + char conv_str[37]; + char *typestr; + + if (type == INITIATOR_NEGO) + typestr = "INITIATOR_NEGO"; + else if (type == ACCEPTOR_NEGO) + typestr = "ACCEPTOR_NEGO"; + else if (type == INITIATOR_META_DATA) + typestr = "INITIATOR_META_DATA"; + else if (type == ACCEPTOR_META_DATA) + typestr = "ACCEPTOR_META_DATA"; + else if (type == CHALLENGE) + typestr = "CHALLENGE"; + else if (type == AP_REQUEST) + typestr = "AP_REQUEST"; + else if (type == VERIFY) + typestr = "VERIFY"; + else if (type == ALERT) + typestr = "ALERT"; + else + typestr = "UNKNOWN"; + + guid_to_string(conv_id, conv_str, sizeof(conv_str)); + _gss_mg_log(NEGOEX_LOG_LEVEL, + "negoex: %s (%d)%s conversation %s", + direction ? "received" : "sending", + seqnum, typestr, conv_str); +} + +/* + * Check that the described vector lies within the message, and return a + * pointer to its first element. + */ +static inline const uint8_t * +vector_base(size_t offset, size_t count, size_t width, + const uint8_t *msg_base, size_t msg_len) +{ + if (offset > msg_len || count > (msg_len - offset) / width) + return NULL; + return msg_base + offset; +} + +static OM_uint32 +parse_nego_message(OM_uint32 *minor, krb5_storage *sp, + const uint8_t *msg_base, size_t msg_len, + struct nego_message *msg) +{ + krb5_error_code ret; + const uint8_t *p; + uint64_t protocol_version; + uint32_t extension_type, offset; + uint16_t count; + size_t i; + + if (krb5_storage_read(sp, msg->random, + sizeof(msg->random)) != sizeof(msg->random)) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + ret = krb5_ret_uint64(sp, &protocol_version); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (protocol_version != 0) { + *minor = (OM_uint32)NEGOEX_UNSUPPORTED_VERSION; + return GSS_S_UNAVAILABLE; + } + + ret = krb5_ret_uint32(sp, &offset); + if (ret == 0) + ret = krb5_ret_uint16(sp, &count); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + msg->schemes = vector_base(offset, count, GUID_LENGTH, msg_base, msg_len); + msg->nschemes = count; + if (msg->schemes == NULL) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + ret = krb5_ret_uint32(sp, &offset); + if (ret == 0) + ret = krb5_ret_uint16(sp, &count); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + p = vector_base(offset, count, EXTENSION_LENGTH, msg_base, msg_len); + for (i = 0; i < count; i++) { + _gss_mg_decode_le_uint32(p + i * EXTENSION_LENGTH, &extension_type); + if (extension_type & EXTENSION_FLAG_CRITICAL) { + *minor = (OM_uint32)NEGOEX_UNSUPPORTED_CRITICAL_EXTENSION; + return GSS_S_UNAVAILABLE; + } + } + + return GSS_S_COMPLETE; +} + +static OM_uint32 +parse_exchange_message(OM_uint32 *minor, krb5_storage *sp, + const uint8_t *msg_base, size_t msg_len, + struct exchange_message *msg) +{ + krb5_error_code ret; + const uint8_t *p; + uint32_t offset; + uint16_t len; + + if (krb5_storage_read(sp, msg->scheme, GUID_LENGTH) != GUID_LENGTH) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + ret = krb5_ret_uint32(sp, &offset); + if (ret == 0) + ret = krb5_ret_uint16(sp, &len); + if (ret) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + p = vector_base(offset, len, 1, msg_base, msg_len); + if (p == NULL) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + msg->token.value = (void *)p; + msg->token.length = len; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +parse_verify_message(OM_uint32 *minor, krb5_storage *sp, + const uint8_t *msg_base, size_t msg_len, + size_t token_offset, struct verify_message *msg) +{ + krb5_error_code ret; + uint32_t hdrlen, cksum_scheme; + uint32_t offset, len; + + if (krb5_storage_read(sp, msg->scheme, GUID_LENGTH) == GUID_LENGTH) + ret = 0; + else + ret = NEGOEX_INVALID_MESSAGE_SIZE; + if (ret == 0) + ret = krb5_ret_uint32(sp, &hdrlen); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (hdrlen != CHECKSUM_HEADER_LENGTH) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + ret = krb5_ret_uint32(sp, &cksum_scheme); + if (ret == 0) + ret = krb5_ret_uint32(sp, &msg->cksum_type); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (cksum_scheme != CHECKSUM_SCHEME_RFC3961) { + *minor = (OM_uint32)NEGOEX_UNKNOWN_CHECKSUM_SCHEME; + return GSS_S_UNAVAILABLE; + } + + ret = krb5_ret_uint32(sp, &offset); + if (ret == 0) + ret = krb5_ret_uint32(sp, &len); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + msg->cksum = vector_base(offset, len, 1, msg_base, msg_len); + msg->cksum_len = len; + if (msg->cksum == NULL) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + msg->offset_in_token = token_offset; + return GSS_S_COMPLETE; +} + +static OM_uint32 +storage_from_memory(OM_uint32 *minor, + const uint8_t *data, + size_t length, + krb5_storage **sp) +{ + *sp = krb5_storage_from_readonly_mem(data, length); + if (sp == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + krb5_storage_set_byteorder(*sp, KRB5_STORAGE_BYTEORDER_LE); + krb5_storage_set_eof_code(*sp, NEGOEX_INVALID_MESSAGE_SIZE); + + return 0; +} + +static OM_uint32 +parse_alert_message(OM_uint32 *minor, krb5_storage *sp, + const uint8_t *msg_base, size_t msg_len, + struct alert_message *msg) +{ + OM_uint32 major; + krb5_error_code ret; + const uint8_t *p; + uint32_t error_code, atype; + uint32_t alerts_offset, nalerts, value_offset, value_len; + size_t i; + krb5_storage *alerts; + + if (krb5_storage_read(sp, msg->scheme, GUID_LENGTH) == GUID_LENGTH) + ret = 0; + else + ret = NEGOEX_INVALID_MESSAGE_SIZE; + if (ret == 0) + ret = krb5_ret_uint32(sp, &error_code); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + ret = krb5_ret_uint32(sp, &alerts_offset); + if (ret == 0) + ret = krb5_ret_uint32(sp, &nalerts); + if (ret) { + *minor = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + p = vector_base(alerts_offset, nalerts, ALERT_LENGTH, msg_base, msg_len); + if (p == NULL) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Look for a VERIFY_NO_KEY pulse alert in the alerts vector. */ + msg->verify_no_key = FALSE; + + major = storage_from_memory(minor, p, nalerts * ALERT_LENGTH, &alerts); + if (major != GSS_S_COMPLETE) + return major; + + for (i = 0; i < nalerts; i++) { + ret = krb5_ret_uint32(alerts, &atype); + if (ret == 0) + ret = krb5_ret_uint32(alerts, &value_offset); + if (ret == 0) + ret = krb5_ret_uint32(alerts, &value_len); + if (ret) { + *minor = ret; + major = GSS_S_DEFECTIVE_TOKEN; + break; + } + + p = vector_base(value_offset, value_len, 1, msg_base, msg_len); + if (p == NULL) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + major = GSS_S_DEFECTIVE_TOKEN; + break; + } + + if (atype == ALERT_TYPE_PULSE && value_len >= ALERT_PULSE_LENGTH) { + krb5_storage *pulse; + uint32_t hdrlen, reason; + + major = storage_from_memory(minor, p, value_len, &pulse); + if (major != GSS_S_COMPLETE) + break; + + ret = krb5_ret_uint32(pulse, &hdrlen); + if (ret == 0) + ret = krb5_ret_uint32(pulse, &reason); + krb5_storage_free(pulse); + if (ret) { + *minor = ret; + major = GSS_S_DEFECTIVE_TOKEN; + break; + } + + if (reason == ALERT_VERIFY_NO_KEY) + msg->verify_no_key = TRUE; + } + } + + krb5_storage_free(alerts); + + return major; +} + +static OM_uint32 +parse_message(OM_uint32 *minor, + gssspnego_ctx ctx, + gss_const_buffer_t token, + size_t *token_offset, + struct negoex_message *msg) +{ + OM_uint32 major; + krb5_error_code ret; + krb5_storage *sp; + uint64_t signature; + uint32_t header_len, msg_len; + uint32_t type, seqnum; + conversation_id conv_id; + size_t token_remaining = token->length - *token_offset; + const uint8_t *msg_base = (uint8_t *)token->value + *token_offset; + + major = storage_from_memory(minor, msg_base, token_remaining, &sp); + if (major != GSS_S_COMPLETE) + return major; + + major = GSS_S_DEFECTIVE_TOKEN; + + ret = krb5_ret_uint64(sp, &signature); + if (ret == 0) + ret = krb5_ret_uint32(sp, &type); + if (ret == 0) + ret = krb5_ret_uint32(sp, &seqnum); + if (ret == 0) + ret = krb5_ret_uint32(sp, &header_len); + if (ret == 0) + ret = krb5_ret_uint32(sp, &msg_len); + if (ret == 0) { + if (krb5_storage_read(sp, conv_id, GUID_LENGTH) != GUID_LENGTH) + ret = NEGOEX_INVALID_MESSAGE_SIZE; + } + if (ret) { + *minor = ret; + goto cleanup; + } + + if (msg_len > token_remaining || header_len > msg_len) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + goto cleanup; + } + if (signature != MESSAGE_SIGNATURE) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIGNATURE; + goto cleanup; + } + if (seqnum != ctx->negoex_seqnum) { + *minor = (OM_uint32)NEGOEX_MESSAGE_OUT_OF_SEQUENCE; + goto cleanup; + } + if (seqnum == 0) { + memcpy(ctx->negoex_conv_id, conv_id, GUID_LENGTH); + } else if (!GUID_EQ(conv_id, ctx->negoex_conv_id)) { + *minor = (OM_uint32)NEGOEX_INVALID_CONVERSATION_ID; + goto cleanup; + } + + krb5_storage_truncate(sp, msg_len); + + msg->type = type; + if (type == INITIATOR_NEGO || type == ACCEPTOR_NEGO) { + major = parse_nego_message(minor, sp, msg_base, msg_len, &msg->u.n); + } else if (type == INITIATOR_META_DATA || type == ACCEPTOR_META_DATA || + type == CHALLENGE || type == AP_REQUEST) { + major = parse_exchange_message(minor, sp, msg_base, msg_len, + &msg->u.e); + } else if (type == VERIFY) { + major = parse_verify_message(minor, sp, msg_base, msg_len, + msg_base - (uint8_t *)token->value, + &msg->u.v); + } else if (type == ALERT) { + major = parse_alert_message(minor, sp, msg_base, msg_len, &msg->u.a); + } else { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_TYPE; + goto cleanup; + } + +cleanup: + krb5_storage_free(sp); + + if (major == GSS_S_COMPLETE) { + _gss_negoex_log_message(1, msg->type, + ctx->negoex_conv_id, ctx->negoex_seqnum, + header_len, msg_len); + ctx->negoex_seqnum++; + *token_offset += msg_len; + } + + return major; +} + +/* + * Parse token into an array of negoex_message structures. All pointer fields + * within the parsed messages are aliases into token, so the result can be + * freed with free(). An unknown protocol version, a critical extension, or an + * unknown checksum scheme will cause a parsing failure. Increment the + * sequence number in ctx for each message, and record and check the + * conversation ID in ctx as appropriate. + */ +OM_uint32 +_gss_negoex_parse_token(OM_uint32 *minor, + gssspnego_ctx ctx, + gss_const_buffer_t token, + struct negoex_message **messages_out, + size_t *count_out) +{ + OM_uint32 major = GSS_S_DEFECTIVE_TOKEN; + size_t count = 0; + size_t token_offset = 0; + struct negoex_message *messages = NULL, *newptr; + + *messages_out = NULL; + *count_out = 0; + heim_assert(token != GSS_C_NO_BUFFER, "Invalid null NegoEx input token"); + + while (token_offset < token->length) { + newptr = realloc(messages, (count + 1) * sizeof(*newptr)); + if (newptr == NULL) { + free(messages); + *minor = ENOMEM; + return GSS_S_FAILURE; + } + messages = newptr; + + major = parse_message(minor, ctx, token, &token_offset, + &messages[count]); + if (major != GSS_S_COMPLETE) + break; + + count++; + } + + if (token_offset != token->length) { + *minor = (OM_uint32)NEGOEX_INVALID_MESSAGE_SIZE; + major = GSS_S_DEFECTIVE_TOKEN; + } + if (major != GSS_S_COMPLETE) { + free(messages); + return major; + } + + *messages_out = messages; + *count_out = count; + return GSS_S_COMPLETE; +} + +static struct negoex_message * +locate_message(struct negoex_message *messages, size_t nmessages, + enum message_type type) +{ + uint32_t i; + + for (i = 0; i < nmessages; i++) { + if (messages[i].type == type) + return &messages[i]; + } + + return NULL; +} + +struct nego_message * +_gss_negoex_locate_nego_message(struct negoex_message *messages, + size_t nmessages, + enum message_type type) +{ + struct negoex_message *msg = locate_message(messages, nmessages, type); + + return (msg == NULL) ? NULL : &msg->u.n; +} + +struct exchange_message * +_gss_negoex_locate_exchange_message(struct negoex_message *messages, + size_t nmessages, + enum message_type type) +{ + struct negoex_message *msg = locate_message(messages, nmessages, type); + + return (msg == NULL) ? NULL : &msg->u.e; +} + +struct verify_message * +_gss_negoex_locate_verify_message(struct negoex_message *messages, + size_t nmessages) +{ + struct negoex_message *msg = locate_message(messages, nmessages, VERIFY); + + return (msg == NULL) ? NULL : &msg->u.v; +} + +struct alert_message * +_gss_negoex_locate_alert_message(struct negoex_message *messages, + size_t nmessages) +{ + struct negoex_message *msg = locate_message(messages, nmessages, ALERT); + + return (msg == NULL) ? NULL : &msg->u.a; +} + +/* + * Add the encoding of a MESSAGE_HEADER structure to buf, given the number of + * bytes of the payload following the full header. Increment the sequence + * number in ctx. Set *payload_start_out to the position of the payload within + * the message. + */ +static OM_uint32 +put_message_header(OM_uint32 *minor, gssspnego_ctx ctx, + enum message_type type, uint32_t payload_len, + uint32_t *payload_start_out) +{ + krb5_error_code ret; + size_t header_len = 0; + + if (type == INITIATOR_NEGO || type == ACCEPTOR_NEGO) + header_len = NEGO_MESSAGE_HEADER_LENGTH; + else if (type == INITIATOR_META_DATA || type == ACCEPTOR_META_DATA || + type == CHALLENGE || type == AP_REQUEST) + header_len = EXCHANGE_MESSAGE_HEADER_LENGTH; + else if (type == VERIFY) + header_len = VERIFY_MESSAGE_HEADER_LENGTH; + else if (type == ALERT) + header_len = ALERT_MESSAGE_HEADER_LENGTH; + else + heim_assert(0, "Invalid NegoEx message type"); + + /* Signature */ + CHECK(ret, krb5_store_uint64(ctx->negoex_transcript, MESSAGE_SIGNATURE)); + /* MessageType */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, type)); + /* SequenceNum */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, ctx->negoex_seqnum)); + /* cbHeaderLength */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, header_len)); + /* cbMessageLength */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, header_len + payload_len)); + /* ConversationId */ + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, ctx->negoex_conv_id, GUID_LENGTH)); + + _gss_negoex_log_message(0, type, + ctx->negoex_conv_id, ctx->negoex_seqnum, + header_len, + header_len + payload_len); + + ctx->negoex_seqnum++; + + *payload_start_out = header_len; + return GSS_S_COMPLETE; + +fail: + *minor = ret; + return GSS_S_FAILURE; +} + +OM_uint32 +_gss_negoex_add_nego_message(OM_uint32 *minor, + gssspnego_ctx ctx, + enum message_type type, + uint8_t random[32]) +{ + OM_uint32 major; + krb5_error_code ret; + struct negoex_auth_mech *mech; + uint32_t payload_start; + uint16_t nschemes; + + nschemes = 0; + HEIM_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) + nschemes++; + + major = put_message_header(minor, ctx, type, + nschemes * GUID_LENGTH, &payload_start); + if (major != GSS_S_COMPLETE) + return major; + + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, random, 32)); + /* ProtocolVersion */ + CHECK(ret, krb5_store_uint64(ctx->negoex_transcript, 0)); + /* AuthSchemes vector */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, payload_start)); + CHECK(ret, krb5_store_uint16(ctx->negoex_transcript, nschemes)); + /* Extensions vector */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, payload_start)); + CHECK(ret, krb5_store_uint16(ctx->negoex_transcript, 0)); + /* Four bytes of padding to reach a multiple of 8 bytes. */ + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, "\0\0\0\0", 4)); + + /* Payload (auth schemes) */ + HEIM_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) { + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, mech->scheme, GUID_LENGTH)); + } + + return GSS_S_COMPLETE; + +fail: + *minor = ret; + return GSS_S_FAILURE; +} + +OM_uint32 +_gss_negoex_add_exchange_message(OM_uint32 *minor, + gssspnego_ctx ctx, + enum message_type type, + const auth_scheme scheme, + gss_buffer_t token) +{ + OM_uint32 major; + krb5_error_code ret; + uint32_t payload_start; + + major = put_message_header(minor, ctx, type, token->length, &payload_start); + if (major != GSS_S_COMPLETE) + return major; + + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, scheme, GUID_LENGTH)); + /* Exchange byte vector */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, payload_start)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, token->length)); + /* Payload (token) */ + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, token->value, token->length)); + + return GSS_S_COMPLETE; + +fail: + *minor = ret; + return GSS_S_FAILURE; +} + +OM_uint32 +_gss_negoex_add_verify_message(OM_uint32 *minor, + gssspnego_ctx ctx, + const auth_scheme scheme, + uint32_t cksum_type, + const uint8_t *cksum, + uint32_t cksum_len) +{ + OM_uint32 major; + krb5_error_code ret; + uint32_t payload_start; + + major = put_message_header(minor, ctx, VERIFY, cksum_len, &payload_start); + if (major != GSS_S_COMPLETE) + return major; + + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, scheme, GUID_LENGTH)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, CHECKSUM_HEADER_LENGTH)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, CHECKSUM_SCHEME_RFC3961)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, cksum_type)); + /* ChecksumValue vector */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, payload_start)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, cksum_len)); + /* Four bytes of padding to reach a multiple of 8 bytes. */ + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, "\0\0\0\0", 4)); + /* Payload (checksum contents) */ + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, cksum, cksum_len)); + + return GSS_S_COMPLETE; + +fail: + *minor = ret; + return GSS_S_FAILURE; +} + +/* + * Add an ALERT_MESSAGE containing a single ALERT_TYPE_PULSE alert with the + * reason ALERT_VERIFY_NO_KEY. + */ +OM_uint32 +_gss_negoex_add_verify_no_key_alert(OM_uint32 *minor, + gssspnego_ctx ctx, + const auth_scheme scheme) +{ + OM_uint32 major; + krb5_error_code ret; + uint32_t payload_start; + + major = put_message_header(minor, ctx, + ALERT, ALERT_LENGTH + ALERT_PULSE_LENGTH, + &payload_start); + if (major != GSS_S_COMPLETE) + return major; + + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, scheme, GUID_LENGTH)); + /* ErrorCode */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, 0)); + /* Alerts vector */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, payload_start)); + CHECK(ret, krb5_store_uint16(ctx->negoex_transcript, 1)); + /* Six bytes of padding to reach a multiple of 8 bytes. */ + CHECK(ret, krb5_store_bytes(ctx->negoex_transcript, "\0\0\0\0\0\0", 6)); + /* Payload part 1: a single ALERT element */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, ALERT_TYPE_PULSE)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, + payload_start + ALERT_LENGTH)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, ALERT_PULSE_LENGTH)); + /* Payload part 2: ALERT_PULSE */ + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, ALERT_PULSE_LENGTH)); + CHECK(ret, krb5_store_uint32(ctx->negoex_transcript, ALERT_VERIFY_NO_KEY)); + + return GSS_S_COMPLETE; + +fail: + *minor = ret; + return GSS_S_FAILURE; +} + + +void +_gss_negoex_release_auth_mech(krb5_context context, + struct negoex_auth_mech *mech) +{ + OM_uint32 tmpmin; + + if (mech == NULL) + return; + + gss_delete_sec_context(&tmpmin, &mech->mech_context, NULL); + gss_release_oid(&tmpmin, &mech->oid); + gss_release_buffer(&tmpmin, &mech->metadata); + if (mech->crypto) + krb5_crypto_destroy(context, mech->crypto); + if (mech->verify_crypto) + krb5_crypto_destroy(context, mech->verify_crypto); + + free(mech); +} + +void +_gss_negoex_delete_auth_mech(gssspnego_ctx ctx, + struct negoex_auth_mech *mech) +{ + krb5_context context = _gss_mg_krb5_context(); + + HEIM_TAILQ_REMOVE(&ctx->negoex_mechs, mech, links); + _gss_negoex_release_auth_mech(context, mech); +} + +/* Remove all auth mech entries except for mech from ctx->mechs. */ +void +_gss_negoex_select_auth_mech(gssspnego_ctx ctx, + struct negoex_auth_mech *mech) +{ + krb5_context context = _gss_mg_krb5_context(); + + heim_assert(mech != NULL, "Invalid null NegoEx mech"); + HEIM_TAILQ_REMOVE(&ctx->negoex_mechs, mech, links); + release_all_mechs(ctx, context); + HEIM_TAILQ_INSERT_HEAD(&ctx->negoex_mechs, mech, links); +} + +OM_uint32 +_gss_negoex_add_auth_mech(OM_uint32 *minor, + gssspnego_ctx ctx, + gss_const_OID oid, + auth_scheme scheme) +{ + OM_uint32 major; + struct negoex_auth_mech *mech; + + mech = calloc(1, sizeof(*mech)); + if (mech == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + major = gss_duplicate_oid(minor, (gss_OID)oid, &mech->oid); + if (major != GSS_S_COMPLETE) { + free(mech); + return major; + } + + memcpy(mech->scheme, scheme, GUID_LENGTH); + + HEIM_TAILQ_INSERT_TAIL(&ctx->negoex_mechs, mech, links); + + *minor = 0; + return GSS_S_COMPLETE; +} + +struct negoex_auth_mech * +_gss_negoex_locate_auth_scheme(gssspnego_ctx ctx, + const auth_scheme scheme) +{ + struct negoex_auth_mech *mech; + + HEIM_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) { + if (GUID_EQ(mech->scheme, scheme)) + return mech; + } + + return NULL; +} + +/* + * Prune ctx->mechs to the schemes present in schemes, and reorder them to + * match its order. + */ +void +_gss_negoex_common_auth_schemes(gssspnego_ctx ctx, + const uint8_t *schemes, + uint16_t nschemes) +{ + struct negoex_mech_list list; + struct negoex_auth_mech *mech; + uint16_t i; + krb5_context context = _gss_mg_krb5_context(); + + /* Construct a new list in the order of schemes. */ + HEIM_TAILQ_INIT(&list); + for (i = 0; i < nschemes; i++) { + mech = _gss_negoex_locate_auth_scheme(ctx, schemes + i * GUID_LENGTH); + if (mech == NULL) + continue; + HEIM_TAILQ_REMOVE(&ctx->negoex_mechs, mech, links); + HEIM_TAILQ_INSERT_TAIL(&list, mech, links); + } + + /* Release any leftover entries and replace the context list. */ + release_all_mechs(ctx, context); + HEIM_TAILQ_CONCAT(&ctx->negoex_mechs, &list, links); +} + +/* + * Prune ctx->mechs to the schemes present in schemes, but do not change + * their order. + */ +void +_gss_negoex_restrict_auth_schemes(gssspnego_ctx ctx, + const uint8_t *schemes, + uint16_t nschemes) +{ + struct negoex_auth_mech *mech, *next; + uint16_t i; + int found; + + HEIM_TAILQ_FOREACH_SAFE(mech, &ctx->negoex_mechs, links, next) { + found = FALSE; + for (i = 0; i < nschemes && !found; i++) { + if (GUID_EQ(mech->scheme, schemes + i * GUID_LENGTH)) + found = TRUE; + } + + if (!found) + _gss_negoex_delete_auth_mech(ctx, mech); + } +} + +/* + * Return the OID of the current NegoEx mechanism. + */ +struct negoex_auth_mech * +_gss_negoex_negotiated_mech(gssspnego_ctx ctx) +{ + return HEIM_TAILQ_FIRST(&ctx->negoex_mechs); +} + +/* + * Returns TRUE if mechanism can be negotiated by both NegoEx and SPNEGO + */ + +int +_gss_negoex_and_spnego_mech_p(gss_const_OID mech) +{ + OM_uint32 major, minor; + gss_OID_set attrs = GSS_C_NO_OID_SET; + int negoex_and_spnego = FALSE; + + major = gss_inquire_attrs_for_mech(&minor, mech, &attrs, NULL); + if (major == GSS_S_COMPLETE) { + gss_test_oid_set_member(&minor, GSS_C_MA_NEGOEX_AND_SPNEGO, + attrs, &negoex_and_spnego); + gss_release_oid_set(&minor, &attrs); + } + + return negoex_and_spnego; +} + +int +_gss_negoex_mech_p(gss_const_OID mech) +{ + OM_uint32 minor; + auth_scheme scheme; + + return gssspi_query_mechanism_info(&minor, mech, + scheme) == GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/spnego/spnego.asn1 b/third_party/heimdal/lib/gssapi/spnego/spnego.asn1 new file mode 100644 index 0000000..bd69a05 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -0,0 +1,66 @@ +-- $Id$ + +SPNEGO DEFINITIONS ::= +BEGIN + +MechType::= OBJECT IDENTIFIER + +MechTypeList ::= SEQUENCE OF MechType + +ContextFlags ::= BIT STRING { + delegFlag (0), + mutualFlag (1), + replayFlag (2), + sequenceFlag (3), + anonFlag (4), + confFlag (5), + integFlag (6) +} + +NegHints ::= SEQUENCE { + hintName [0] GeneralString OPTIONAL, + hintAddress [1] OCTET STRING OPTIONAL +} + +NegTokenInit2 ::= SEQUENCE { + mechTypes [0] MechTypeList, + reqFlags [1] ContextFlags OPTIONAL, + mechToken [2] OCTET STRING OPTIONAL, + negHints [3] NegHints OPTIONAL +} + +NegTokenInit ::= SEQUENCE { + mechTypes [0] MechTypeList, + reqFlags [1] ContextFlags OPTIONAL, + mechToken [2] OCTET STRING OPTIONAL, + mechListMIC [3] OCTET STRING OPTIONAL, + ... +} + +NegStateEnum ::= ENUMERATED { + accept-completed(0), + accept-incomplete(1), + reject(2), + request-mic(3) +} + +-- NB: negState is not OPTIONAL in the new SPNEGO spec but +-- Windows clients do not always send it +NegTokenResp ::= SEQUENCE { + negState [0] NegStateEnum OPTIONAL, + supportedMech [1] MechType OPTIONAL, + responseToken [2] OCTET STRING OPTIONAL, + mechListMIC [3] OCTET STRING OPTIONAL, + ... +} + +NegotiationToken ::= CHOICE { + negTokenInit[0] NegTokenInit, + negTokenResp[1] NegTokenResp +} + +NegotiationToken2 ::= CHOICE { + negTokenInit[0] NegTokenInit2 +} + +END diff --git a/third_party/heimdal/lib/gssapi/spnego/spnego.opt b/third_party/heimdal/lib/gssapi/spnego/spnego.opt new file mode 100644 index 0000000..cbf2f23 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/spnego.opt @@ -0,0 +1 @@ +--sequence=MechTypeList diff --git a/third_party/heimdal/lib/gssapi/spnego/spnego_locl.h b/third_party/heimdal/lib/gssapi/spnego/spnego_locl.h new file mode 100644 index 0000000..e3434f2 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef SPNEGO_LOCL_H +#define SPNEGO_LOCL_H + +#include <config.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#include <roken.h> + +#ifdef HAVE_PTHREAD_H +#include <pthread.h> +#endif + +#include <krb5.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <heim_threads.h> +#include <heimqueue.h> +#include <asn1_err.h> + +#include <gssapi_mech.h> + +#include "spnego_asn1.h" +#include "negoex_locl.h" +#include "utils.h" +#include <der.h> + +#include <heimbase.h> + +#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) + +#define CHECK(ret, x) do { (ret) = (x); if (ret) goto fail; } while (0) + +struct gssspnego_ctx_desc; +typedef struct gssspnego_ctx_desc *gssspnego_ctx; + +typedef OM_uint32 +(*gssspnego_initiator_state)(OM_uint32 * minor_status, + gss_const_cred_id_t cred, + gssspnego_ctx ctx, + gss_const_name_t name, + gss_const_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + gss_const_buffer_t input_token, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec); + +struct gssspnego_ctx_desc { + gss_buffer_desc NegTokenInit_mech_types; + gss_OID preferred_mech_type; + gss_OID selected_mech_type; + gss_OID negotiated_mech_type; + gss_ctx_id_t negotiated_ctx_id; + OM_uint32 mech_flags; + OM_uint32 mech_time_rec; + gss_name_t mech_src_name; + struct spnego_flags { + unsigned int open : 1; + unsigned int local : 1; + unsigned int require_mic : 1; + unsigned int peer_require_mic : 1; + unsigned int sent_mic : 1; + unsigned int verified_mic : 1; + unsigned int safe_omit : 1; + unsigned int maybe_open : 1; + unsigned int seen_supported_mech : 1; + } flags; + HEIMDAL_MUTEX ctx_id_mutex; + + gss_name_t target_name; + gssspnego_initiator_state initiator_state; + + uint8_t negoex_step; + krb5_storage *negoex_transcript; + uint32_t negoex_seqnum; + conversation_id negoex_conv_id; + HEIM_TAILQ_HEAD(negoex_mech_list, negoex_auth_mech) negoex_mechs; +}; + +extern gss_OID_desc _gss_spnego_mskrb_mechanism_oid_desc; + +struct gssspnego_optimistic_ctx { + gssspnego_ctx spnegoctx; + OM_uint32 req_flags; + gss_name_t target_name; + OM_uint32 time_req; + gss_channel_bindings_t input_chan_bindings; + /* out */ + gss_OID preferred_mech_type; + gss_OID negotiated_mech_type; + gss_buffer_desc optimistic_token; + OM_uint32 optimistic_flags, optimistic_time_rec; + gss_ctx_id_t gssctx; + int complete; + auth_scheme scheme; +}; + +#include "spnego-private.h" + +static inline int +gssspnego_ctx_complete_p(gssspnego_ctx ctx) +{ + return ctx->flags.open && + (ctx->flags.safe_omit || (ctx->flags.sent_mic && ctx->flags.verified_mic)); +} + +#endif /* SPNEGO_LOCL_H */ diff --git a/third_party/heimdal/lib/gssapi/test_acquire_cred.c b/third_party/heimdal/lib/gssapi/test_acquire_cred.c new file mode 100644 index 0000000..ef49311 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_acquire_cred.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2003-2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <err.h> +#include <getarg.h> + +#include "test_common.h" + +static void +print_time(OM_uint32 time_rec) +{ + if (time_rec == GSS_C_INDEFINITE) { + printf("cred never expire\n"); + } else { + time_t t = time_rec + time(NULL); + printf("expiration time: %s", ctime(&t)); + } +} + +#if 0 + +static void +test_add(gss_cred_id_t cred_handle) +{ + OM_uint32 major_status, minor_status; + gss_cred_id_t copy_cred; + OM_uint32 time_rec; + + major_status = gss_add_cred (&minor_status, + cred_handle, + GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, + GSS_C_INITIATE, + 0, + 0, + ©_cred, + NULL, + &time_rec, + NULL); + + if (GSS_ERROR(major_status)) + errx(1, "add_cred failed"); + + print_time(time_rec); + + major_status = gss_release_cred(&minor_status, + ©_cred); + if (GSS_ERROR(major_status)) + errx(1, "release_cred failed"); +} + +static void +copy_cred(void) +{ + OM_uint32 major_status, minor_status; + gss_cred_id_t cred_handle; + OM_uint32 time_rec; + + major_status = gss_acquire_cred(&minor_status, + GSS_C_NO_NAME, + 0, + NULL, + GSS_C_INITIATE, + &cred_handle, + NULL, + &time_rec); + if (GSS_ERROR(major_status)) + errx(1, "acquire_cred failed"); + + print_time(time_rec); + + test_add(cred_handle); + test_add(cred_handle); + test_add(cred_handle); + + major_status = gss_release_cred(&minor_status, + &cred_handle); + if (GSS_ERROR(major_status)) + errx(1, "release_cred failed"); +} +#endif + +static gss_cred_id_t +acquire_cred_service(const char *service, + gss_OID nametype, + gss_OID_set oidset, + gss_cred_usage_t usage, + gss_const_key_value_set_t cred_store) +{ + OM_uint32 major_status, minor_status; + gss_cred_id_t cred_handle; + OM_uint32 time_rec; + gss_buffer_desc name_buffer; + gss_name_t name = GSS_C_NO_NAME; + + if (service) { + name_buffer.value = rk_UNCONST(service); + name_buffer.length = strlen(service); + + major_status = gss_import_name(&minor_status, + &name_buffer, + nametype, + &name); + if (GSS_ERROR(major_status)) + errx(1, "import_name failed"); + } + + major_status = gss_acquire_cred_from(&minor_status, + name, + 0, + oidset, + usage, + cred_store, + &cred_handle, + NULL, + &time_rec); + if (GSS_ERROR(major_status)) { + warnx("acquire_cred failed: %s", + gssapi_err(major_status, minor_status, GSS_C_NO_OID)); + } else { + print_time(time_rec); + gss_release_cred(&minor_status, &cred_handle); + } + + if (name != GSS_C_NO_NAME) + gss_release_name(&minor_status, &name); + + if (GSS_ERROR(major_status)) + exit(1); + + return cred_handle; +} + +static int version_flag = 0; +static int help_flag = 0; +static int kerberos_flag = 0; +static int enctype = 0; +static char *acquire_name; +static char *acquire_type; +static char *target_name; +static char *name_type; +static char *ccache; +static char *client_keytab; +static int num_loops = 1; + +static struct getargs args[] = { + {"acquire-name", 0, arg_string, &acquire_name, "name", NULL }, + {"acquire-type", 0, arg_string, &acquire_type, "type", NULL }, + {"enctype", 0, arg_integer, &enctype, "enctype-num", NULL }, + {"loops", 0, arg_integer, &num_loops, "num-loops", NULL }, + {"kerberos", 0, arg_flag, &kerberos_flag, NULL, NULL }, + {"target-name", 0, arg_string, &target_name, "name", NULL }, + {"ccache", 0, arg_string, &ccache, "name", NULL }, + {"client-keytab", 0,arg_string, &client_keytab, "name", NULL }, + {"name-type", 0, arg_string, &name_type, "type", NULL }, + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), NULL, ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + gss_OID_set oidset = GSS_C_NULL_OID_SET; + gss_OID mechoid = GSS_C_NO_OID; + OM_uint32 maj_stat, min_stat; + gss_cred_id_t cred; + gss_name_t target = GSS_C_NO_NAME; + int i, optidx = 0; + gss_cred_usage_t cred_usage = GSS_C_BOTH; + gss_OID type = GSS_C_NT_HOSTBASED_SERVICE; + gss_key_value_set_desc store, *storep = GSS_C_NO_CRED_STORE; + gss_key_value_element_desc elements[2]; + + store.count = 0; + store.elements = elements; + + setprogname(argv[0]); + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc != 0) + usage(1); + + if (acquire_type) { + if (strcasecmp(acquire_type, "both") == 0) + cred_usage = GSS_C_BOTH; + else if (strcasecmp(acquire_type, "accept") == 0) + cred_usage = GSS_C_ACCEPT; + else if (strcasecmp(acquire_type, "initiate") == 0) + cred_usage = GSS_C_INITIATE; + else + errx(1, "unknown type %s", acquire_type); + } + + if (name_type) { + if (strcasecmp("hostbased-service", name_type) == 0) + type = GSS_C_NT_HOSTBASED_SERVICE; + else if (strcasecmp("user-name", name_type) == 0) + type = GSS_C_NT_USER_NAME; + else + errx(1, "unknown name type %s", name_type); + } + + if (ccache) { + store.elements[store.count].key = "ccache"; + store.elements[store.count].value = ccache; + store.count++; + } + if (client_keytab) { + store.elements[store.count].key = "client_keytab"; + store.elements[store.count].value = client_keytab; + store.count++; + } + + if (store.count) + storep = &store; + + if (kerberos_flag) { + mechoid = GSS_KRB5_MECHANISM; + + maj_stat = gss_create_empty_oid_set(&min_stat, &oidset); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_create_empty_oid_set: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + + maj_stat = gss_add_oid_set_member(&min_stat, GSS_KRB5_MECHANISM, &oidset); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_add_oid_set_member: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } + + if (target_name) { + gss_buffer_desc name; + + name.value = target_name; + name.length = strlen(target_name); + maj_stat = gss_import_name(&min_stat, &name, + GSS_C_NT_HOSTBASED_SERVICE, &target); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_import_name: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } + + for (i = 0; i < num_loops; i++) { + + cred = acquire_cred_service(acquire_name, type, oidset, cred_usage, storep); + + if (enctype) { + int32_t enctypelist = enctype; + + maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred, + 1, &enctypelist); + if (maj_stat) + errx(1, "gss_krb5_set_allowable_enctypes: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } + + if (target) { + gss_ctx_id_t context = GSS_C_NO_CONTEXT; + gss_buffer_desc out; + + out.length = 0; + out.value = NULL; + + maj_stat = gss_init_sec_context(&min_stat, + cred, &context, + target, mechoid, + GSS_C_MUTUAL_FLAG, 0, NULL, + GSS_C_NO_BUFFER, NULL, + &out, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) + errx(1, "init_sec_context failed: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + + gss_release_buffer(&min_stat, &out); + gss_delete_sec_context(&min_stat, &context, NULL); + } + gss_release_cred(&min_stat, &cred); + } + gss_release_oid_set(&min_stat, &oidset); + gss_release_name(&min_stat, &target); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/test_add_store_cred.c b/third_party/heimdal/lib/gssapi/test_add_store_cred.c new file mode 100644 index 0000000..03c3dc9 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_add_store_cred.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2015 Cryptonector LLC. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name Cryptonector LLC may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <gssapi.h> +#include <err.h> +#include <getarg.h> + +static void +print_gss_err(OM_uint32 stat, int status_type, gss_OID mech) +{ + gss_buffer_desc str; + OM_uint32 maj; + OM_uint32 min; + OM_uint32 msg_ctx = 0; + int first = 1; + + do { + maj = gss_display_status(&min, stat, status_type, mech, &msg_ctx, + &str); + if (maj != GSS_S_COMPLETE) { + fprintf(stderr, "Error displaying GSS %s error (%lu): %lu, %lu", + status_type == GSS_C_GSS_CODE ? "major" : "minor", + (unsigned long)stat, (unsigned long)maj, + (unsigned long)min); + return; + } + if (first) { + fprintf(stderr, "GSS %s error: %.*s\n", + status_type == GSS_C_GSS_CODE ? "major" : "minor", + (int)str.length, (char *)str.value); + first = 0; + } else { + fprintf(stderr, "\t%.*s\n", (int)str.length, (char *)str.value); + } + gss_release_buffer(&min, &str); + } while (msg_ctx != 0); +} + +static void +print_gss_errs(OM_uint32 major, OM_uint32 minor, gss_OID mech) +{ + print_gss_err(major, GSS_C_GSS_CODE, GSS_C_NO_OID); + print_gss_err(major, GSS_C_MECH_CODE, mech); +} + +static void +gss_err(int exitval, OM_uint32 major, OM_uint32 minor, gss_OID mech, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vwarnx(fmt, args); + va_end(args); + print_gss_errs(major, minor, mech); + exit(exitval); +} + +static int version_flag = 0; +static int help_flag = 0; +static int env_flag = 0; +static int def_flag = 0; +static int overwrite_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL }, + {"env", 'e', arg_flag, &env_flag, + "output env settings", NULL }, + {"default", 0, arg_flag, &def_flag, + "switch credential store default principal", NULL }, + {"overwrite", 0, arg_flag, &overwrite_flag, + "overwrite matching credential", NULL }, +}; + +static void +usage(int ret) +{ + arg_printusage(args, sizeof(args)/sizeof(*args), + NULL, "from_ccache to_ccache"); + exit(ret); +} + +int +main(int argc, char **argv) +{ + OM_uint32 major, minor; + gss_cred_id_t from_cred = GSS_C_NO_CREDENTIAL; + gss_cred_id_t to_cred = GSS_C_NO_CREDENTIAL; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_key_value_element_desc from_elements, to_elements; + gss_key_value_set_desc from, to; + gss_buffer_set_t env = GSS_C_NO_BUFFER_SET; + OM_uint32 store_flags = 0; + int optidx = 0; + + setprogname(argv[0]); + if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if (version_flag){ + print_version(NULL); + exit(0); + } + + if (def_flag) + store_flags |= GSS_C_STORE_CRED_DEFAULT; + if (overwrite_flag) + store_flags |= GSS_C_STORE_CRED_OVERWRITE; + + argc -= optidx; + argv += optidx; + + if (argc < 2) + errx(1, "required arguments missing"); + if (argc > 2) + errx(1, "too many arguments"); + + from_elements.key = "ccache"; + from_elements.value = argv[0]; + from.count = 1; + from.elements = &from_elements; + + to_elements.key = "ccache"; + to_elements.value = argv[1]; + to.count = 1; + to.elements = &to_elements; + + major = gss_add_cred_from(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, GSS_C_INITIATE, + GSS_C_INDEFINITE, GSS_C_INDEFINITE, + &from, &from_cred, NULL, NULL, NULL); + if (major != GSS_S_COMPLETE) + gss_err(1, major, minor, GSS_KRB5_MECHANISM, + "failed to acquire creds from %s", argv[0]); + + major = gss_store_cred_into2(&minor, from_cred, GSS_C_INITIATE, + GSS_KRB5_MECHANISM, store_flags, &to, NULL, + NULL, env_flag ? &env : NULL); + if (major != GSS_S_COMPLETE) + gss_err(1, major, minor, GSS_KRB5_MECHANISM, + "failed to store creds into %s", argv[1]); + + if (env_flag) { + size_t i; + int got_krb5ccname = 0; + + if (env == GSS_C_NO_BUFFER_SET) + warnx("No environment settings"); + + for (i = 0; env != GSS_C_NO_BUFFER_SET && i < env->count; i++) { + got_krb5ccname = got_krb5ccname || + (env->elements[i].length > sizeof("KRB5CCNAME=") && + strncmp((const char *)env->elements[i].value, "KRB5CCNAME=", + sizeof("KRB5CCNAME=") - 1) == 0); + printf("%.*s\n", (int)env->elements[i].length, + (const char *)env->elements[i].value); + } + (void) gss_release_buffer_set(&minor, &env); + + if (!got_krb5ccname) + errx(1, "KRB5CCNAME environment variable not set by " + "gss_store_cred_into2()"); + } + + (void) gss_release_cred(&minor, &from_cred); + (void) gss_release_cred(&minor, &to_cred); + + major = gss_add_cred(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, + GSS_KRB5_MECHANISM, GSS_C_INITIATE, GSS_C_INDEFINITE, + GSS_C_INDEFINITE, &cred, NULL, NULL, NULL); + if (major != GSS_S_COMPLETE) + gss_err(1, major, minor, GSS_KRB5_MECHANISM, + "failed to acquire creds from %s", argv[1]); + (void) gss_release_cred(&minor, &cred); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/test_common.c b/third_party/heimdal/lib/gssapi/test_common.c new file mode 100644 index 0000000..ebdcd71 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_common.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" +#include <err.h> +#include "test_common.h" + +char * +gssapi_err(OM_uint32 maj_stat, OM_uint32 min_stat, gss_OID mech) +{ + OM_uint32 disp_min_stat; + gss_buffer_desc maj_error_message; + gss_buffer_desc min_error_message; + OM_uint32 msg_ctx = 0; + + char *ret = NULL; + + maj_error_message.length = 0; + maj_error_message.value = NULL; + min_error_message.length = 0; + min_error_message.value = NULL; + + (void) gss_display_status(&disp_min_stat, maj_stat, GSS_C_GSS_CODE, + mech, &msg_ctx, &maj_error_message); + (void) gss_display_status(&disp_min_stat, min_stat, GSS_C_MECH_CODE, + mech, &msg_ctx, &min_error_message); + if (asprintf(&ret, "gss-code: %lu %.*s -- mech-code: %lu %.*s", + (unsigned long)maj_stat, + (int)maj_error_message.length, + (char *)maj_error_message.value, + (unsigned long)min_stat, + (int)min_error_message.length, + (char *)min_error_message.value) < 0 || ret == NULL) + errx(1, "malloc"); + + gss_release_buffer(&disp_min_stat, &maj_error_message); + gss_release_buffer(&disp_min_stat, &min_error_message); + + return ret; +} + diff --git a/third_party/heimdal/lib/gssapi/test_common.h b/third_party/heimdal/lib/gssapi/test_common.h new file mode 100644 index 0000000..fda2949 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_common.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +char * gssapi_err(OM_uint32, OM_uint32, gss_OID); diff --git a/third_party/heimdal/lib/gssapi/test_context.c b/third_party/heimdal/lib/gssapi/test_context.c new file mode 100644 index 0000000..7446d15 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_context.c @@ -0,0 +1,1610 @@ +/* + * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" +#include <err.h> +#include <getarg.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <gssapi_ntlm.h> +#include "test_common.h" + +#ifdef NOTYET +/* + * export/import of sec contexts on the initiator side + * don't work properly, yet. + */ +#define DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT 1 +#endif + +static char *type_string; +static char *mech_string; +static char *mechs_string; +static char *ret_mech_string; +static char *localname_string; +static char *client_name; +static char *client_password; +static char *localname_string; +static char *on_behalf_of_string; +static int dns_canon_flag = -1; +static int mutual_auth_flag = 0; +static int dce_style_flag = 0; +static int wrapunwrap_flag = 0; +static int iov_flag = 0; +static int aead_flag = 0; +static int getverifymic_flag = 0; +static int deleg_flag = 0; +static int anon_flag = 0; +static int policy_deleg_flag = 0; +static int server_no_deleg_flag = 0; +static int ei_cred_flag = 0; +static int ei_ctx_flag = 0; +static char *client_ccache = NULL; +static char *client_keytab = NULL; +static char *gsskrb5_acceptor_identity = NULL; +static char *session_enctype_string = NULL; +static int client_time_offset = 0; +static int server_time_offset = 0; +static int max_loops = 0; +static char *limit_enctype_string = NULL; +static int token_split = 0; +static int version_flag = 0; +static int verbose_flag = 0; +static int help_flag = 0; +static char *i_channel_bindings = NULL; +static char *a_channel_bindings = NULL; + +static krb5_context context; +static krb5_enctype limit_enctype = 0; + +static gss_OID +string_to_oid(const char *name) +{ + gss_OID oid = gss_name_to_oid(name); + + if (oid == GSS_C_NO_OID) + errx(1, "name '%s' not known", name); + + return oid; +} + +static void +string_to_oids(gss_OID_set *oidsetp, char *names) +{ + OM_uint32 maj_stat, min_stat; + char *name; + char *s; + + if (names[0] == '\0') { + *oidsetp = GSS_C_NO_OID_SET; + return; + } + + if (strcasecmp(names, "all") == 0) { + maj_stat = gss_indicate_mechs(&min_stat, oidsetp); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_indicate_mechs: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } else { + maj_stat = gss_create_empty_oid_set(&min_stat, oidsetp); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_create_empty_oid_set: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + + for (name = strtok_r(names, ", ", &s); + name != NULL; + name = strtok_r(NULL, ", ", &s)) { + gss_OID oid = string_to_oid(name); + + maj_stat = gss_add_oid_set_member(&min_stat, oid, oidsetp); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_add_oid_set_member: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } + } +} + +static void +show_pac_client_info(gss_name_t n) +{ + gss_buffer_desc dv = GSS_C_EMPTY_BUFFER; + gss_buffer_desc v = GSS_C_EMPTY_BUFFER; + gss_buffer_desc a; + OM_uint32 maj, min; + int authenticated, complete, more, name_is_MN, found; + gss_OID MN_mech; + gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; + size_t i; + + krb5_error_code ret; + krb5_storage *sp = NULL; + uint16_t len = 0, *s; + uint64_t tmp; + char *logon_string = NULL; + + maj = gss_inquire_name(&min, n, &name_is_MN, &MN_mech, &attrs); + if (maj != GSS_S_COMPLETE) + errx(1, "gss_inquire_name: %s", + gssapi_err(maj, min, GSS_KRB5_MECHANISM)); + + a.value = "urn:mspac:client-info"; + a.length = sizeof("urn:mspac:client-info") - 1; + + for (found = 0, i = 0; i < attrs->count; i++) { + gss_buffer_t attr = &attrs->elements[i]; + + if (attr->length == a.length && + memcmp(attr->value, a.value, a.length) == 0) { + found++; + break; + } + } + + gss_release_buffer_set(&min, &attrs); + + if (!found) + errx(1, "gss_inquire_name: attribute %.*s not enumerated", + (int)a.length, (char *)a.value); + + more = 0; + maj = gss_get_name_attribute(&min, n, &a, &authenticated, &complete, &v, + &dv, &more); + if (maj != GSS_S_COMPLETE) + errx(1, "gss_get_name_attribute: %s", + gssapi_err(maj, min, GSS_KRB5_MECHANISM)); + + + sp = krb5_storage_from_readonly_mem(v.value, v.length); + if (sp == NULL) + errx(1, "show_pac_client_info: out of memory"); + + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + ret = krb5_ret_uint64(sp, &tmp); /* skip over time */ + if (ret == 0) + ret = krb5_ret_uint16(sp, &len); + if (ret || len == 0) + errx(1, "show_pac_client_info: invalid PAC logon info length"); + + s = malloc(len); + ret = krb5_storage_read(sp, s, len); + if (ret != len) + errx(1, "show_pac_client_info:, failed to read PAC logon name"); + + krb5_storage_free(sp); + + { + size_t ucs2len = len / 2; + uint16_t *ucs2; + size_t u8len; + unsigned int flags = WIND_RW_LE; + + ucs2 = malloc(sizeof(ucs2[0]) * ucs2len); + if (ucs2 == NULL) + errx(1, "show_pac_client_info: out of memory"); + + ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len); + free(s); + if (ret) + errx(1, "failed to convert string to UCS-2"); + + ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len); + if (ret) + errx(1, "failed to count length of UCS-2 string"); + + u8len += 1; /* Add space for NUL */ + logon_string = malloc(u8len); + if (logon_string == NULL) + errx(1, "show_pac_client_info: out of memory"); + + ret = wind_ucs2utf8(ucs2, ucs2len, logon_string, &u8len); + free(ucs2); + if (ret) + errx(1, "failed to convert to UTF-8"); + } + + printf("logon name: %s\n", logon_string); + free(logon_string); + + gss_release_buffer(&min, &dv); + gss_release_buffer(&min, &v); +} + +static void +loop(gss_OID mechoid, + gss_OID nameoid, const char *target, + gss_cred_id_t init_cred, + gss_ctx_id_t *sctx, gss_ctx_id_t *cctx, + gss_OID *actual_mech, + gss_cred_id_t *deleg_cred) +{ + int server_done = 0, client_done = 0; + int num_loops = 0; + OM_uint32 maj_stat, min_stat; + gss_name_t gss_target_name, src_name = GSS_C_NO_NAME; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; +#ifdef DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT + gss_buffer_desc cctx_tok = GSS_C_EMPTY_BUFFER; +#endif + gss_buffer_desc sctx_tok = GSS_C_EMPTY_BUFFER; + OM_uint32 flags = 0, ret_cflags = 0, ret_sflags = 0; + gss_OID actual_mech_client = GSS_C_NO_OID; + gss_OID actual_mech_server = GSS_C_NO_OID; + struct gss_channel_bindings_struct i_channel_bindings_data; + struct gss_channel_bindings_struct a_channel_bindings_data; + gss_channel_bindings_t i_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS; + gss_channel_bindings_t a_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS; + size_t offset = 0; + + memset(&i_channel_bindings_data, 0, sizeof(i_channel_bindings_data)); + memset(&a_channel_bindings_data, 0, sizeof(a_channel_bindings_data)); + + *actual_mech = GSS_C_NO_OID; + + flags |= GSS_C_REPLAY_FLAG; + flags |= GSS_C_INTEG_FLAG; + flags |= GSS_C_CONF_FLAG; + + if (mutual_auth_flag) + flags |= GSS_C_MUTUAL_FLAG; + if (anon_flag) + flags |= GSS_C_ANON_FLAG; + if (dce_style_flag) + flags |= GSS_C_DCE_STYLE; + if (deleg_flag) + flags |= GSS_C_DELEG_FLAG; + if (policy_deleg_flag) + flags |= GSS_C_DELEG_POLICY_FLAG; + + input_token.value = rk_UNCONST(target); + input_token.length = strlen(target); + + maj_stat = gss_import_name(&min_stat, + &input_token, + nameoid, + &gss_target_name); + if (GSS_ERROR(maj_stat)) + err(1, "import name creds failed with: %d", maj_stat); + + if (on_behalf_of_string) { + AuthorizationDataElement e; + gss_buffer_desc attr, value; + int32_t kret; + size_t sz; + + memset(&e, 0, sizeof(e)); + e.ad_type = KRB5_AUTHDATA_ON_BEHALF_OF; + e.ad_data.length = strlen(on_behalf_of_string); + e.ad_data.data = on_behalf_of_string; + ASN1_MALLOC_ENCODE(AuthorizationDataElement, value.value, value.length, + &e, &sz, kret); + if (kret) + errx(1, "Could not encode AD-ON-BEHALF-OF AuthorizationDataElement"); + attr.value = + GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data"; + attr.length = + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data") - 1; + maj_stat = gss_set_name_attribute(&min_stat, gss_target_name, 1, &attr, + &value); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_set_name_attribute() failed with: %s", + gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM)); + free(value.value); + } + + input_token.length = 0; + input_token.value = NULL; + + if (i_channel_bindings) { + i_channel_bindings_data.application_data.length = strlen(i_channel_bindings); + i_channel_bindings_data.application_data.value = i_channel_bindings; + i_channel_bindings_p = &i_channel_bindings_data; + } + if (a_channel_bindings) { + a_channel_bindings_data.application_data.length = strlen(a_channel_bindings); + a_channel_bindings_data.application_data.value = a_channel_bindings; + a_channel_bindings_p = &a_channel_bindings_data; + } + + /* + * This loop simulates both the initiator and acceptor sides of + * a GSS conversation. We also simulate tokens that are broken + * into pieces before handed to gss_accept_sec_context(). Each + * iteration of the loop optionally calls gss_init_sec_context() + * then optionally calls gss_accept_sec_context(). + */ + + while (!server_done || !client_done) { + num_loops++; + if (verbose_flag) + printf("loop #%d: input_token.length=%zu client_done=%d\n", + num_loops, input_token.length, client_done); + + /* + * First, we need to call gss_import_sec_context() if we are + * running through the loop the first time, or if we have been + * given a token (input_token) by gss_accept_sec_context(). + * We aren't going to be called every time because when we are + * using split tokens, we may need to call gss_accept_sec_context() + * multiple times because it receives an entire token. + */ + if ((num_loops == 1 || input_token.length > 0) && !client_done) { + gsskrb5_set_time_offset(client_time_offset); +#ifdef DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT + if (ei_ctx_flag && cctx_tok.length > 0) { + maj_stat = gss_import_sec_context(&min_stat, &cctx_tok, cctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import client context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + gss_release_buffer(&min_stat, &cctx_tok); + } +#endif + + maj_stat = gss_init_sec_context(&min_stat, init_cred, cctx, + gss_target_name, mechoid, + flags, 0, i_channel_bindings_p, + &input_token, &actual_mech_client, + &output_token, &ret_cflags, NULL); + if (GSS_ERROR(maj_stat)) + errx(1, "init_sec_context: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + client_done = !(maj_stat & GSS_S_CONTINUE_NEEDED); + + gss_release_buffer(&min_stat, &input_token); + input_token.length = 0; + input_token.value = NULL; + +#if DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT + if (!client_done && ei_ctx_flag) { + maj_stat = gss_export_sec_context(&min_stat, cctx, &cctx_tok); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "export server context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + if (*cctx != GSS_C_NO_CONTEXT) + errx(1, "export client context did not release it"); + } +#endif + + if (verbose_flag) + printf("loop #%d: output_token.length=%zu\n", num_loops, + output_token.length); + + offset = 0; + } + + /* + * We now call gss_accept_sec_context(). To support split + * tokens, we keep track of the offset into the token that + * we have used and keep handing in chunks until we're done. + */ + + if (offset < output_token.length && !server_done) { + gss_buffer_desc tmp; + + gsskrb5_get_time_offset(&client_time_offset); + gsskrb5_set_time_offset(server_time_offset); + + if (output_token.length && ((uint8_t *)output_token.value)[0] == 0x60) { + tmp.length = output_token.length - offset; + if (token_split && tmp.length > token_split) + tmp.length = token_split; + tmp.value = (char *)output_token.value + offset; + } else + tmp = output_token; + + if (verbose_flag) + printf("loop #%d: accept offset=%zu len=%zu\n", num_loops, + offset, tmp.length); + + if (ei_ctx_flag && sctx_tok.length > 0) { + maj_stat = gss_import_sec_context(&min_stat, &sctx_tok, sctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import server context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + gss_release_buffer(&min_stat, &sctx_tok); + } + + maj_stat = gss_accept_sec_context(&min_stat, sctx, + GSS_C_NO_CREDENTIAL, &tmp, + a_channel_bindings_p, &src_name, + &actual_mech_server, + &input_token, &ret_sflags, + NULL, deleg_cred); + if (GSS_ERROR(maj_stat)) + errx(1, "accept_sec_context: %s", + gssapi_err(maj_stat, min_stat, actual_mech_server)); + offset += tmp.length; + if (maj_stat & GSS_S_CONTINUE_NEEDED) + gss_release_name(&min_stat, &src_name); + else + server_done = 1; + + if (ei_ctx_flag && !server_done) { + maj_stat = gss_export_sec_context(&min_stat, sctx, &sctx_tok); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "export server context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + if (*sctx != GSS_C_NO_CONTEXT) + errx(1, "export server context did not release it"); + } + + gsskrb5_get_time_offset(&server_time_offset); + + if (output_token.length == offset) + gss_release_buffer(&min_stat, &output_token); + } + if (verbose_flag) + printf("loop #%d: end\n", num_loops); + } + if (output_token.length != 0) + gss_release_buffer(&min_stat, &output_token); + if (input_token.length != 0) + gss_release_buffer(&min_stat, &input_token); + gss_release_name(&min_stat, &gss_target_name); + + if (deleg_flag || policy_deleg_flag) { + if (server_no_deleg_flag) { + if (*deleg_cred != GSS_C_NO_CREDENTIAL) + errx(1, "got delegated cred but didn't expect one"); + } else if (*deleg_cred == GSS_C_NO_CREDENTIAL) + errx(1, "asked for delegarated cred but did get one"); + } else if (*deleg_cred != GSS_C_NO_CREDENTIAL) + errx(1, "got deleg_cred cred but didn't ask"); + + if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0) + errx(1, "mech mismatch"); + *actual_mech = actual_mech_server; + + if (on_behalf_of_string) { + gss_buffer_desc attr, value; + + attr.value = + GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580"; + attr.length = + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580") - 1; + maj_stat = gss_get_name_attribute(&min_stat, src_name, &attr, NULL, + NULL, &value, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_get_name_attribute(authz-data#580) failed with %s", + gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM)); + + if (value.length != strlen(on_behalf_of_string) || + strncmp(value.value, on_behalf_of_string, + strlen(on_behalf_of_string)) != 0) + errx(1, "AD-ON-BEHALF-OF did not match"); + (void) gss_release_buffer(&min_stat, &value); + } + if (localname_string) { + gss_buffer_desc lname; + + maj_stat = gss_localname(&min_stat, src_name, GSS_C_NO_OID, &lname); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "localname: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + if (verbose_flag) + printf("localname: %.*s\n", (int)lname.length, + (char *)lname.value); + if (lname.length != strlen(localname_string) || + strncmp(localname_string, lname.value, lname.length) != 0) + errx(1, "localname: expected \"%s\", got \"%.*s\" (1)", + localname_string, (int)lname.length, (char *)lname.value); + gss_release_buffer(&min_stat, &lname); + maj_stat = gss_localname(&min_stat, src_name, actual_mech_server, + &lname); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "localname: %s", + gssapi_err(maj_stat, min_stat, actual_mech_server)); + if (lname.length != strlen(localname_string) || + strncmp(localname_string, lname.value, lname.length) != 0) + errx(1, "localname: expected \"%s\", got \"%.*s\" (2)", + localname_string, (int)lname.length, (char *)lname.value); + gss_release_buffer(&min_stat, &lname); + + if (!gss_userok(src_name, localname_string)) + errx(1, "localname is not userok"); + if (gss_userok(src_name, "nosuchuser:no")) + errx(1, "gss_userok() appears broken"); + } + if (verbose_flag) { + gss_buffer_desc iname; + + maj_stat = gss_display_name(&min_stat, src_name, &iname, NULL); + if (maj_stat == GSS_S_COMPLETE) { + printf("client name: %.*s\n", (int)iname.length, + (char *)iname.value); + gss_release_buffer(&min_stat, &iname); + } else + warnx("display_name: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + if (!anon_flag && + gss_oid_equal(actual_mech_server, GSS_KRB5_MECHANISM)) + show_pac_client_info(src_name); + } + gss_release_name(&min_stat, &src_name); + + if (max_loops && num_loops > max_loops) + errx(1, "num loops %d was lager then max loops %d", + num_loops, max_loops); + + if (verbose_flag) { + printf("server time offset: %d\n", server_time_offset); + printf("client time offset: %d\n", client_time_offset); + printf("num loops %d\n", num_loops); + printf("cflags: "); + if (ret_cflags & GSS_C_DELEG_FLAG) + printf("deleg "); + if (ret_cflags & GSS_C_MUTUAL_FLAG) + printf("mutual "); + if (ret_cflags & GSS_C_REPLAY_FLAG) + printf("replay "); + if (ret_cflags & GSS_C_SEQUENCE_FLAG) + printf("sequence "); + if (ret_cflags & GSS_C_CONF_FLAG) + printf("conf "); + if (ret_cflags & GSS_C_INTEG_FLAG) + printf("integ "); + if (ret_cflags & GSS_C_ANON_FLAG) + printf("anon "); + if (ret_cflags & GSS_C_PROT_READY_FLAG) + printf("prot-ready "); + if (ret_cflags & GSS_C_TRANS_FLAG) + printf("trans "); + if (ret_cflags & GSS_C_DCE_STYLE) + printf("dce-style "); + if (ret_cflags & GSS_C_IDENTIFY_FLAG) + printf("identify " ); + if (ret_cflags & GSS_C_EXTENDED_ERROR_FLAG) + printf("extended-error " ); + if (ret_cflags & GSS_C_DELEG_POLICY_FLAG) + printf("deleg-policy " ); + printf("\n"); + printf("sflags: "); + if (ret_sflags & GSS_C_CHANNEL_BOUND_FLAG) + printf("channel-bound " ); + printf("\n"); + } +} + +static void +wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) +{ + gss_buffer_desc input_token, output_token, output_token2; + OM_uint32 min_stat, maj_stat; + gss_qop_t qop_state; + int conf_state; + + input_token.value = "foo"; + input_token.length = 3; + + maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token, + &conf_state, &output_token); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_wrap failed: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + + maj_stat = gss_unwrap(&min_stat, sctx, &output_token, + &output_token2, &conf_state, &qop_state); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_unwrap failed: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + + gss_release_buffer(&min_stat, &output_token); + gss_release_buffer(&min_stat, &output_token2); + +#if 0 /* doesn't work for NTLM yet */ + if (!!conf_state != !!flags) + errx(1, "conf_state mismatch"); +#endif +} + +#define USE_CONF 1 +#define USE_HEADER_ONLY 2 +#define USE_SIGN_ONLY 4 +#define FORCE_IOV 8 +/* NO_DATA comes from <netdb.h>; we don't use it here; we appropriate it */ +#ifdef NO_DATA +#undef NO_DATA +#endif +#define NO_DATA 16 + +static void +wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) +{ + krb5_data token, header, trailer; + OM_uint32 min_stat, maj_stat; + gss_qop_t qop_state; + int conf_state, conf_state2; + gss_iov_buffer_desc iov[6]; + unsigned char *p; + int iov_len; + char header_data[9] = "ABCheader"; + char trailer_data[10] = "trailerXYZ"; + + char token_data[16] = "0123456789abcdef"; + + memset(&iov, 0, sizeof(iov)); + + if (flags & USE_SIGN_ONLY) { + header.data = header_data; + header.length = 9; + trailer.data = trailer_data; + trailer.length = 10; + } else { + header.data = NULL; + header.length = 0; + trailer.data = NULL; + trailer.length = 0; + } + + token.data = token_data; + token.length = 16; + + iov_len = sizeof(iov)/sizeof(iov[0]); + + memset(iov, 0, sizeof(iov)); + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + + if (header.length != 0) { + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[1].buffer.length = header.length; + iov[1].buffer.value = header.data; + } else { + iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY; + iov[1].buffer.length = 0; + iov[1].buffer.value = NULL; + } + iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; + if (flags & NO_DATA) { + iov[2].buffer.length = 0; + } else { + iov[2].buffer.length = token.length; + } + iov[2].buffer.value = token.data; + if (trailer.length != 0) { + iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[3].buffer.length = trailer.length; + iov[3].buffer.value = trailer.data; + } else { + iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY; + iov[3].buffer.length = 0; + iov[3].buffer.value = NULL; + } + if (dce_style_flag) { + iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY; + } else { + iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE; + } + iov[4].buffer.length = 0; + iov[4].buffer.value = 0; + if (dce_style_flag) { + iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; + } else if (flags & USE_HEADER_ONLY) { + iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; + } else { + iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + } + iov[5].buffer.length = 0; + iov[5].buffer.value = 0; + + maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state, + iov, iov_len); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_wrap_iov failed"); + + token.length = + iov[0].buffer.length + + iov[1].buffer.length + + iov[2].buffer.length + + iov[3].buffer.length + + iov[4].buffer.length + + iov[5].buffer.length; + token.data = emalloc(token.length); + + p = token.data; + memcpy(p, iov[0].buffer.value, iov[0].buffer.length); + p += iov[0].buffer.length; + memcpy(p, iov[1].buffer.value, iov[1].buffer.length); + p += iov[1].buffer.length; + memcpy(p, iov[2].buffer.value, iov[2].buffer.length); + p += iov[2].buffer.length; + memcpy(p, iov[3].buffer.value, iov[3].buffer.length); + p += iov[3].buffer.length; + memcpy(p, iov[4].buffer.value, iov[4].buffer.length); + p += iov[4].buffer.length; + memcpy(p, iov[5].buffer.value, iov[5].buffer.length); + p += iov[5].buffer.length; + + assert(p - ((unsigned char *)token.data) == token.length); + + if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { + gss_buffer_desc input, output; + + input.value = token.data; + input.length = token.length; + + maj_stat = gss_unwrap(&min_stat, sctx, &input, + &output, &conf_state2, &qop_state); + + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_unwrap from gss_wrap_iov failed: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + + gss_release_buffer(&min_stat, &output); + } else { + maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state, + iov, iov_len); + + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_unwrap_iov failed: %x %s", flags, + gssapi_err(maj_stat, min_stat, mechoid)); + + } + if (conf_state2 != conf_state) + errx(1, "conf state wrong for iov: %x", flags); + + gss_release_iov_buffer(&min_stat, iov, iov_len); + + free(token.data); +} + +static void +wrapunwrap_aead(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) +{ + gss_buffer_desc token, assoc, message = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output; + OM_uint32 min_stat, maj_stat; + gss_qop_t qop_state; + int conf_state, conf_state2; + char assoc_data[9] = "ABCheader"; + char token_data[16] = "0123456789abcdef"; + + if (flags & USE_SIGN_ONLY) { + assoc.value = assoc_data; + assoc.length = 9; + } else { + assoc.value = NULL; + assoc.length = 0; + } + + token.value = token_data; + token.length = 16; + + maj_stat = gss_wrap_aead(&min_stat, cctx, dce_style_flag || flags & USE_CONF, + GSS_C_QOP_DEFAULT, &assoc, &token, + &conf_state, &message); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_wrap_aead failed"); + + if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { + maj_stat = gss_unwrap(&min_stat, sctx, &message, + &output, &conf_state2, &qop_state); + + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_unwrap from gss_wrap_aead failed: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + } else { + maj_stat = gss_unwrap_aead(&min_stat, sctx, &message, &assoc, + &output, &conf_state2, &qop_state); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_unwrap_aead failed: %x %s", flags, + gssapi_err(maj_stat, min_stat, mechoid)); + } + + if (output.length != token.length) + errx(1, "plaintext length wrong for aead"); + else if (memcmp(output.value, token.value, token.length) != 0) + errx(1, "plaintext wrong for aead"); + if (conf_state2 != conf_state) + errx(1, "conf state wrong for aead: %x", flags); + + gss_release_buffer(&min_stat, &message); + gss_release_buffer(&min_stat, &output); +} + +static void +getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid) +{ + gss_buffer_desc input_token, output_token; + OM_uint32 min_stat, maj_stat; + gss_qop_t qop_state; + + input_token.value = "bar"; + input_token.length = 3; + + maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token, + &output_token); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_get_mic failed: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + + maj_stat = gss_verify_mic(&min_stat, sctx, &input_token, + &output_token, &qop_state); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_verify_mic failed: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + + gss_release_buffer(&min_stat, &output_token); +} + +static void +empty_release(void) +{ + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_name_t name = GSS_C_NO_NAME; + gss_OID_set oidset = GSS_C_NO_OID_SET; + OM_uint32 junk; + + gss_delete_sec_context(&junk, &ctx, NULL); + gss_release_cred(&junk, &cred); + gss_release_name(&junk, &name); + gss_release_oid_set(&junk, &oidset); +} + +/* + * + */ + +static struct getargs args[] = { + {"name-type",0, arg_string, &type_string, "type of name", NULL }, + {"mech-type",0, arg_string, &mech_string, "mech type (name)", NULL }, + {"mech-types",0, arg_string, &mechs_string, "mech types (names)", NULL }, + {"ret-mech-type",0, arg_string, &ret_mech_string, + "type of return mech", NULL }, + {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag, + "use dns to canonicalize", NULL }, + {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL }, + {"client-ccache",0, arg_string, &client_ccache, "client credentials cache", NULL }, + {"client-keytab",0, arg_string, &client_keytab, "client keytab", NULL }, + {"client-name", 0, arg_string, &client_name, "client name", NULL }, + {"client-password", 0, arg_string, &client_password, "client password", NULL }, + {"anonymous", 0, arg_flag, &anon_flag, "anonymous auth", NULL }, + {"i-channel-bindings", 0, arg_string, &i_channel_bindings, "initiator channel binding data", NULL }, + {"a-channel-bindings", 0, arg_string, &a_channel_bindings, "acceptor channel binding data", NULL }, + {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, + {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL }, + {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL }, + {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL }, + {"aead", 0, arg_flag, &aead_flag, "wrap/unwrap aead", NULL }, + {"getverifymic",0, arg_flag, &getverifymic_flag, + "get and verify mic", NULL }, + {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL }, + {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL }, + {"server-no-delegate",0, arg_flag, &server_no_deleg_flag, + "server should get a credential", NULL }, + {"export-import-context",0, arg_flag, &ei_ctx_flag, "test export/import context", NULL }, + {"export-import-cred",0, arg_flag, &ei_cred_flag, "test export/import cred", NULL }, + {"localname",0, arg_string, &localname_string, "expected localname for client", "USERNAME"}, + {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL }, + {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL }, + {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL }, + {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL }, + {"max-loops", 0, arg_integer, &max_loops, "time", NULL }, + {"token-split", 0, arg_integer, &token_split, "bytes", NULL }, + {"on-behalf-of", 0, arg_string, &on_behalf_of_string, "principal", + "send authenticator authz-data AD-ON-BEHALF-OF" }, + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, "service@host"); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int optidx = 0; + OM_uint32 min_stat, maj_stat; + gss_ctx_id_t cctx, sctx; + void *ctx; + gss_OID nameoid, mechoid, actual_mech, actual_mech2; + gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; + gss_name_t cname = GSS_C_NO_NAME; + gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER; + gss_OID_desc oids[7]; + gss_OID_set_desc mechoid_descs; + gss_OID_set mechoids = GSS_C_NO_OID_SET; + gss_key_value_element_desc client_cred_elements[2]; + gss_key_value_set_desc client_cred_store; + gss_OID_set actual_mechs = GSS_C_NO_OID_SET; + + setprogname(argv[0]); + + if (krb5_init_context(&context)) + errx(1, "krb5_init_context"); + + cctx = sctx = GSS_C_NO_CONTEXT; + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc != 1) + usage(1); + + if (dns_canon_flag != -1) + gsskrb5_set_dns_canonicalize(dns_canon_flag); + + if (type_string == NULL) + nameoid = GSS_C_NT_HOSTBASED_SERVICE; + else if (strcmp(type_string, "hostbased-service") == 0) + nameoid = GSS_C_NT_HOSTBASED_SERVICE; + else if (strcmp(type_string, "krb5-principal-name") == 0) + nameoid = GSS_KRB5_NT_PRINCIPAL_NAME; + else + errx(1, "%s not supported", type_string); + + if (mech_string == NULL) + mechoid = GSS_KRB5_MECHANISM; + else + mechoid = string_to_oid(mech_string); + + if (mechs_string == NULL) { + /* + * We ought to be able to use the OID set of the one mechanism + * OID given. But there's some breakage that conspires to make + * that fail though it should succeed: + * + * - the NTLM gss_acquire_cred() refuses to work with + * desired_name == GSS_C_NO_NAME + * - gss_acquire_cred() with desired_mechs == GSS_C_NO_OID_SET + * does work here because we happen to have Kerberos + * credentials in check-ntlm, and the subsequent + * gss_init_sec_context() call finds no cred element for NTLM + * but plows on anyways, surprisingly enough, and then the + * NTLM gss_init_sec_context() just works. + * + * In summary, there's some breakage in gss_init_sec_context() + * and some breakage in NTLM that conspires against us here. + * + * We work around this in check-ntlm and check-spnego by adding + * --client-name=user1@${R} to the invocations of this test + * program that require it. + */ + oids[0] = *mechoid; + mechoid_descs.elements = &oids[0]; + mechoid_descs.count = 1; + mechoids = &mechoid_descs; + } else { + string_to_oids(&mechoids, mechs_string); + } + + if (gsskrb5_acceptor_identity) { + /* XXX replace this with cred store, but test suites will need work */ + maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); + if (maj_stat) + errx(1, "gsskrb5_acceptor_identity: %s", + gssapi_err(maj_stat, 0, GSS_C_NO_OID)); + } + + if (client_password && (client_ccache || client_keytab)) { + errx(1, "password option mutually exclusive with ccache or keytab option"); + } + + if (client_password) { + credential_data.value = client_password; + credential_data.length = strlen(client_password); + } + + client_cred_store.count = 0; + client_cred_store.elements = client_cred_elements; + + if (client_ccache) { + client_cred_store.elements[client_cred_store.count].key = "ccache"; + client_cred_store.elements[client_cred_store.count].value = client_ccache; + + client_cred_store.count++; + } + + if (client_keytab) { + client_cred_store.elements[client_cred_store.count].key = "client_keytab"; + client_cred_store.elements[client_cred_store.count].value = client_keytab; + + client_cred_store.count++; + } + + if (client_name) { + gss_buffer_desc cn; + + cn.value = client_name; + cn.length = strlen(client_name); + + maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); + if (maj_stat) + errx(1, "gss_import_name: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } + + if (client_password) { + maj_stat = gss_acquire_cred_with_password(&min_stat, + cname, + &credential_data, + GSS_C_INDEFINITE, + mechoids, + GSS_C_INITIATE, + &client_cred, + &actual_mechs, + NULL); + if (GSS_ERROR(maj_stat)) { + if (mechoids != GSS_C_NO_OID_SET && mechoids->count == 1) + mechoid = &mechoids->elements[0]; + else + mechoid = GSS_C_NO_OID; + errx(1, "gss_acquire_cred_with_password: %s", + gssapi_err(maj_stat, min_stat, mechoid)); + } + } else { + maj_stat = gss_acquire_cred_from(&min_stat, + cname, + GSS_C_INDEFINITE, + mechoids, + GSS_C_INITIATE, + client_cred_store.count ? &client_cred_store + : GSS_C_NO_CRED_STORE, + &client_cred, + &actual_mechs, + NULL); + if (GSS_ERROR(maj_stat) && !anon_flag) + errx(1, "gss_acquire_cred: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } + + gss_release_name(&min_stat, &cname); + + if (verbose_flag) { + size_t i; + + printf("cred mechs:"); + for (i = 0; i < actual_mechs->count; i++) + printf(" %s", gss_oid_to_name(&actual_mechs->elements[i])); + printf("\n"); + } + + if (gss_oid_equal(mechoid, GSS_SPNEGO_MECHANISM) && mechs_string) { + maj_stat = gss_set_neg_mechs(&min_stat, client_cred, mechoids); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_set_neg_mechs: %s", + gssapi_err(maj_stat, min_stat, GSS_SPNEGO_MECHANISM)); + + mechoid_descs.elements = GSS_SPNEGO_MECHANISM; + mechoid_descs.count = 1; + mechoids = &mechoid_descs; + } + + if (ei_cred_flag) { + gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; + gss_buffer_desc cb; + + maj_stat = gss_export_cred(&min_stat, client_cred, &cb); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "export cred failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + maj_stat = gss_import_cred(&min_stat, &cb, &cred2); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import cred failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + gss_release_buffer(&min_stat, &cb); + gss_release_cred(&min_stat, &client_cred); + client_cred = cred2; + } + + if (limit_enctype_string) { + krb5_error_code ret; + + ret = krb5_string_to_enctype(context, + limit_enctype_string, + &limit_enctype); + if (ret) + krb5_err(context, 1, ret, "krb5_string_to_enctype"); + } + + + if (limit_enctype) { + if (client_cred == NULL) + errx(1, "client_cred missing"); + + maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred, + 1, &limit_enctype); + if (maj_stat) + errx(1, "gss_krb5_set_allowable_enctypes: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + } + + loop(mechoid, nameoid, argv[0], client_cred, + &sctx, &cctx, &actual_mech, &deleg_cred); + + if (verbose_flag) + printf("resulting mech: %s\n", gss_oid_to_name(actual_mech)); + + if (ret_mech_string) { + gss_OID retoid; + + retoid = string_to_oid(ret_mech_string); + + if (gss_oid_equal(retoid, actual_mech) == 0) + errx(1, "actual_mech mech is not the expected type %s", + ret_mech_string); + } + + /* XXX should be actual_mech */ + if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) { + time_t sc_time; + gss_buffer_desc authz_data; + gss_buffer_desc in, out1, out2; + krb5_keyblock *keyblock, *keyblock2; + krb5_timestamp now; + krb5_error_code ret; + + ret = krb5_timeofday(context, &now); + if (ret) + errx(1, "krb5_timeofday failed"); + + /* client */ + maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, + &cctx, + 1, /* version */ + &ctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_export_lucid_sec_context failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + + maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_free_lucid_sec_context failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + /* server */ + maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, + &sctx, + 1, /* version */ + &ctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_export_lucid_sec_context failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_free_lucid_sec_context failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, + sctx, + &sc_time); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + if (sc_time > now) + errx(1, "gsskrb5_extract_authtime_from_sec_context failed: " + "time authtime is before now: %ld %ld", + (long)sc_time, (long)now); + + maj_stat = gsskrb5_extract_service_keyblock(&min_stat, + sctx, + &keyblock); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gsskrb5_export_service_keyblock failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + krb5_free_keyblock(context, keyblock); + + maj_stat = gsskrb5_get_subkey(&min_stat, + sctx, + &keyblock); + if (maj_stat != GSS_S_COMPLETE + && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) + errx(1, "gsskrb5_get_subkey server failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + if (maj_stat != GSS_S_COMPLETE) + keyblock = NULL; + else if (limit_enctype && keyblock->keytype != limit_enctype) + errx(1, "gsskrb5_get_subkey wrong enctype"); + + maj_stat = gsskrb5_get_subkey(&min_stat, + cctx, + &keyblock2); + if (maj_stat != GSS_S_COMPLETE + && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) + errx(1, "gsskrb5_get_subkey client failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + if (maj_stat != GSS_S_COMPLETE) + keyblock2 = NULL; + else if (limit_enctype && keyblock && keyblock->keytype != limit_enctype) + errx(1, "gsskrb5_get_subkey wrong enctype"); + + if (keyblock || keyblock2) { + if (keyblock == NULL) + errx(1, "server missing token keyblock"); + if (keyblock2 == NULL) + errx(1, "client missing token keyblock"); + + if (keyblock->keytype != keyblock2->keytype) + errx(1, "enctype mismatch"); + if (keyblock->keyvalue.length != keyblock2->keyvalue.length) + errx(1, "key length mismatch"); + if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data, + keyblock2->keyvalue.length) != 0) + errx(1, "key data mismatch"); + } + + if (session_enctype_string) { + krb5_enctype enctype; + + ret = krb5_string_to_enctype(context, + session_enctype_string, + &enctype); + + if (ret) + krb5_err(context, 1, ret, "krb5_string_to_enctype"); + + if (keyblock && enctype != keyblock->keytype) + errx(1, "keytype is not the expected %d != %d", + (int)enctype, (int)keyblock2->keytype); + } + + if (keyblock) + krb5_free_keyblock(context, keyblock); + if (keyblock2) + krb5_free_keyblock(context, keyblock2); + + maj_stat = gsskrb5_get_initiator_subkey(&min_stat, + sctx, + &keyblock); + if (maj_stat != GSS_S_COMPLETE + && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) + errx(1, "gsskrb5_get_initiator_subkey failed: %s", + gssapi_err(maj_stat, min_stat, actual_mech)); + + if (maj_stat == GSS_S_COMPLETE) { + + if (limit_enctype && keyblock->keytype != limit_enctype) + errx(1, "gsskrb5_get_initiator_subkey wrong enctype"); + krb5_free_keyblock(context, keyblock); + } + + maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, + sctx, + 128, + &authz_data); + if (maj_stat == GSS_S_COMPLETE) + gss_release_buffer(&min_stat, &authz_data); + + + memset(&out1, 0, sizeof(out1)); + memset(&out2, 0, sizeof(out2)); + + in.value = "foo"; + in.length = 3; + + gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, + 100, &out1); + gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in, + 100, &out2); + + if (out1.length != out2.length) + errx(1, "prf len mismatch"); + if (memcmp(out1.value, out2.value, out1.length) != 0) + errx(1, "prf data mismatch"); + + gss_release_buffer(&min_stat, &out1); + + gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, + 100, &out1); + + if (out1.length != out2.length) + errx(1, "prf len mismatch"); + if (memcmp(out1.value, out2.value, out1.length) != 0) + errx(1, "prf data mismatch"); + + gss_release_buffer(&min_stat, &out1); + gss_release_buffer(&min_stat, &out2); + + in.value = "bar"; + in.length = 3; + + gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in, + 100, &out1); + gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in, + 100, &out2); + + if (out1.length != out2.length) + errx(1, "prf len mismatch"); + if (memcmp(out1.value, out2.value, out1.length) != 0) + errx(1, "prf data mismatch"); + + gss_release_buffer(&min_stat, &out1); + gss_release_buffer(&min_stat, &out2); + + wrapunwrap_flag = 1; + getverifymic_flag = 1; + } + + if (ei_ctx_flag) { + gss_buffer_desc ctx_token = GSS_C_EMPTY_BUFFER; + + maj_stat = gss_export_sec_context(&min_stat, &cctx, &ctx_token); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "export client context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + if (cctx != GSS_C_NO_CONTEXT) + errx(1, "export client context did not release it"); + + maj_stat = gss_import_sec_context(&min_stat, &ctx_token, &cctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import client context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + gss_release_buffer(&min_stat, &ctx_token); + + maj_stat = gss_export_sec_context(&min_stat, &sctx, &ctx_token); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "export server context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + if (sctx != GSS_C_NO_CONTEXT) + errx(1, "export server context did not release it"); + + maj_stat = gss_import_sec_context(&min_stat, &ctx_token, &sctx); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import server context failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + gss_release_buffer(&min_stat, &ctx_token); + } + + if (wrapunwrap_flag) { + wrapunwrap(cctx, sctx, 0, actual_mech); + wrapunwrap(cctx, sctx, 1, actual_mech); + wrapunwrap(sctx, cctx, 0, actual_mech); + wrapunwrap(sctx, cctx, 1, actual_mech); + } + + if (iov_flag) { + wrapunwrap_iov(cctx, sctx, 0, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); + + wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + +/* works */ + wrapunwrap_iov(cctx, sctx, 0, actual_mech); + wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + + /* works */ + wrapunwrap_iov(cctx, sctx, NO_DATA, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_SIGN_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_SIGN_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY, actual_mech); + wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); + } + + if (aead_flag) { + wrapunwrap_aead(cctx, sctx, 0, actual_mech); + wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech); + + wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech); + wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); + + wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); + wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_aead(cctx, sctx, 0, actual_mech); + wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech); + + wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech); + wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); + + wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY, actual_mech); + wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); + + wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); + wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); + } + + if (getverifymic_flag) { + getverifymic(cctx, sctx, actual_mech); + getverifymic(cctx, sctx, actual_mech); + getverifymic(sctx, cctx, actual_mech); + getverifymic(sctx, cctx, actual_mech); + } + + gss_delete_sec_context(&min_stat, &cctx, NULL); + gss_delete_sec_context(&min_stat, &sctx, NULL); + + if (deleg_cred != GSS_C_NO_CREDENTIAL) { + gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; + gss_buffer_desc cb; + + if (verbose_flag) + printf("checking actual mech (%s) on delegated cred\n", + gss_oid_to_name(actual_mech)); + loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2); + + gss_delete_sec_context(&min_stat, &cctx, NULL); + gss_delete_sec_context(&min_stat, &sctx, NULL); + + gss_release_cred(&min_stat, &cred2); + +#if 0 + /* + * XXX We can't do this. Delegated credentials only work with + * the actual_mech. We could gss_store_cred the delegated + * credentials *then* gss_add/acquire_cred() with SPNEGO, then + * we could try loop() with those credentials. + */ + /* try again using SPNEGO */ + if (verbose_flag) + printf("checking spnego on delegated cred\n"); + loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx, + &actual_mech2, &cred2); + + gss_delete_sec_context(&min_stat, &cctx, NULL); + gss_delete_sec_context(&min_stat, &sctx, NULL); + + gss_release_cred(&min_stat, &cred2); +#endif + + /* check export/import */ + if (ei_cred_flag) { + + maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "export cred failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + maj_stat = gss_import_cred(&min_stat, &cb, &cred2); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import cred failed: %s", + gssapi_err(maj_stat, min_stat, NULL)); + + gss_release_buffer(&min_stat, &cb); + gss_release_cred(&min_stat, &deleg_cred); + + if (verbose_flag) + printf("checking actual mech (%s) on export/imported cred\n", + gss_oid_to_name(actual_mech)); + loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx, + &actual_mech2, &deleg_cred); + + gss_release_cred(&min_stat, &deleg_cred); + + gss_delete_sec_context(&min_stat, &cctx, NULL); + gss_delete_sec_context(&min_stat, &sctx, NULL); + +#if 0 + /* XXX See above */ + /* try again using SPNEGO */ + if (verbose_flag) + printf("checking SPNEGO on export/imported cred\n"); + loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx, + &actual_mech2, &deleg_cred); + + gss_release_cred(&min_stat, &deleg_cred); + + gss_delete_sec_context(&min_stat, &cctx, NULL); + gss_delete_sec_context(&min_stat, &sctx, NULL); +#endif + + gss_release_cred(&min_stat, &cred2); + + } else { + gss_release_cred(&min_stat, &deleg_cred); + } + + } + + gss_release_cred(&min_stat, &client_cred); + gss_release_oid_set(&min_stat, &actual_mechs); + if (mechoids != GSS_C_NO_OID_SET && mechoids != &mechoid_descs) + gss_release_oid_set(&min_stat, &mechoids); + empty_release(); + + krb5_free_context(context); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/test_cred.c b/third_party/heimdal/lib/gssapi/test_cred.c new file mode 100644 index 0000000..9eaabda --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_cred.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2003-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <err.h> +#include <getarg.h> + +static int anon_flag = 0; + +static void +gss_print_errors (int min_stat) +{ + OM_uint32 new_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + OM_uint32 ret; + + do { + ret = gss_display_status (&new_stat, + min_stat, + GSS_C_MECH_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if (!GSS_ERROR(ret)) { + fprintf (stderr, "%.*s\n", (int)status_string.length, + (char *)status_string.value); + gss_release_buffer (&new_stat, &status_string); + } + } while (!GSS_ERROR(ret) && msg_ctx != 0); +} + +static void +gss_err(int exitval, int status, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vwarnx (fmt, args); + gss_print_errors (status); + va_end(args); + exit (exitval); +} + +static void +acquire_release_loop(gss_name_t name, int counter, gss_cred_usage_t usage) +{ + OM_uint32 maj_stat, min_stat; + gss_cred_id_t cred; + int i; + + for (i = 0; i < counter; i++) { + maj_stat = gss_acquire_cred(&min_stat, name, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + usage, + &cred, + NULL, + NULL); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "aquire %d %d != GSS_S_COMPLETE", + i, (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release %d %d != GSS_S_COMPLETE", + i, (int)maj_stat); + } +} + + +static void +acquire_add_release_add(gss_name_t name, gss_cred_usage_t usage) +{ + OM_uint32 maj_stat, min_stat; + gss_cred_id_t cred, cred2, cred3; + gss_OID mech_oid = anon_flag ? GSS_SANON_X25519_MECHANISM : GSS_KRB5_MECHANISM; + + maj_stat = gss_acquire_cred(&min_stat, name, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + usage, + &cred, + NULL, + NULL); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "aquire %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_add_cred(&min_stat, + cred, + GSS_C_NO_NAME, + mech_oid, + usage, + GSS_C_INDEFINITE, + GSS_C_INDEFINITE, + &cred2, + NULL, + NULL, + NULL); + + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "add_cred %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_add_cred(&min_stat, + cred2, + GSS_C_NO_NAME, + mech_oid, + GSS_C_BOTH, + GSS_C_INDEFINITE, + GSS_C_INDEFINITE, + &cred3, + NULL, + NULL, + NULL); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "add_cred 2 %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred2); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat); + + maj_stat = gss_release_cred(&min_stat, &cred3); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, min_stat, "release 3 %d != GSS_S_COMPLETE", (int)maj_stat); +} + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"anonymous", 0, arg_flag, &anon_flag, "try anonymous creds", NULL }, + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, "service@host"); + exit (ret); +} + + +int +main(int argc, char **argv) +{ + struct gss_buffer_desc_struct name_buffer; + OM_uint32 maj_stat, min_stat; + gss_name_t name; + int optidx = 0; + + setprogname(argv[0]); + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc < 1) + errx(1, "argc < 1"); + + name_buffer.value = argv[0]; + name_buffer.length = strlen(argv[0]); + + maj_stat = gss_import_name(&min_stat, &name_buffer, + GSS_C_NT_HOSTBASED_SERVICE, + &name); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "import name error"); + + acquire_release_loop(name, 100, GSS_C_ACCEPT); + acquire_release_loop(name, 100, GSS_C_INITIATE); + acquire_release_loop(name, 100, GSS_C_BOTH); + + acquire_add_release_add(name, GSS_C_ACCEPT); + acquire_add_release_add(name, GSS_C_INITIATE); + acquire_add_release_add(name, GSS_C_BOTH); + + gss_release_name(&min_stat, &name); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/test_kcred.c b/third_party/heimdal/lib/gssapi/test_kcred.c new file mode 100644 index 0000000..abfe390 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_kcred.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2003-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <krb5.h> +#include <err.h> +#include <getarg.h> + +static int version_flag = 0; +static int help_flag = 0; + +static void +copy_import(void) +{ + gss_cred_id_t cred1, cred2; + OM_uint32 maj_stat, min_stat; + gss_name_t name1, name2; + OM_uint32 lifetime1, lifetime2; + gss_cred_usage_t usage1, usage2; + gss_OID_set mechs1, mechs2; + krb5_ccache id; + krb5_error_code ret; + krb5_context context; + int equal; + + maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_INITIATE, + &cred1, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_acquire_cred"); + + maj_stat = gss_inquire_cred(&min_stat, cred1, &name1, &lifetime1, + &usage1, &mechs1); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_inquire_cred"); + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_init_context"); + + ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_new_unique"); + + maj_stat = gss_krb5_copy_ccache(&min_stat, cred1, id); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_copy_ccache"); + + maj_stat = gss_krb5_import_cred(&min_stat, id, NULL, NULL, &cred2); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_krb5_import_cred"); + + maj_stat = gss_inquire_cred(&min_stat, cred2, &name2, &lifetime2, + &usage2, &mechs2); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_inquire_cred 2"); + + maj_stat = gss_compare_name(&min_stat, name1, name2, &equal); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_compare_name"); + if (!equal) + errx(1, "names not equal"); + + /* + * This check is racy! It tends to fail when run with valgrind. + * + * make check-valgrind sets TESTS_ENVIRONMENT in the environment... + */ + if (getenv("TESTS_ENVIRONMENT") == NULL && lifetime1 != lifetime2) + errx(1, "lifetime not equal %lu != %lu", + (unsigned long)lifetime1, (unsigned long)lifetime2); + if (lifetime1 != lifetime2) + warnx("lifetime not equal %lu != %lu", + (unsigned long)lifetime1, (unsigned long)lifetime2); + + if (usage1 != usage2) { + /* as long any of them is both are everything it ok */ + if (usage1 != GSS_C_BOTH && usage2 != GSS_C_BOTH) + errx(1, "usages disjoined"); + } + + gss_release_name(&min_stat, &name2); + gss_release_oid_set(&min_stat, &mechs2); + + maj_stat = gss_inquire_cred(&min_stat, cred2, &name2, &lifetime2, + &usage2, &mechs2); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_inquire_cred"); + + maj_stat = gss_compare_name(&min_stat, name1, name2, &equal); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_compare_name"); + if (!equal) + errx(1, "names not equal"); + + /* This check is racy! */ + if (getenv("TESTS_ENVIRONMENT") == NULL && lifetime1 != lifetime2) + errx(1, "lifetime not equal %lu != %lu", + (unsigned long)lifetime1, (unsigned long)lifetime2); + if (lifetime1 != lifetime2) + warnx("lifetime not equal %lu != %lu", + (unsigned long)lifetime1, (unsigned long)lifetime2); + + gss_release_cred(&min_stat, &cred1); + gss_release_cred(&min_stat, &cred2); + + gss_release_name(&min_stat, &name1); + gss_release_name(&min_stat, &name2); + +#if 0 + compare(mechs1, mechs2); +#endif + + gss_release_oid_set(&min_stat, &mechs1); + gss_release_oid_set(&min_stat, &mechs2); + + krb5_cc_destroy(context, id); + krb5_free_context(context); +} + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int optidx = 0; + + setprogname(argv[0]); + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + copy_import(); + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/test_names.c b/third_party/heimdal/lib/gssapi/test_names.c new file mode 100644 index 0000000..933635e --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_names.c @@ -0,0 +1,675 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <krb5_asn1.h> +#include <err.h> +#include <getarg.h> + +static void make_composite_name(CompositePrincipal *, gss_name_t *); +static void assert_attr(gss_name_t, const char *, OM_uint32, gss_buffer_t, + const char *, int, int, int); +static void assert_attr_unavail(gss_name_t, const char *); +static void assert_attr_set(gss_name_t, gss_buffer_set_t); + +static void +gss_print_errors(OM_uint32 stat, gss_OID mech) +{ + OM_uint32 junk; + OM_uint32 more = 0; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + OM_uint32 ret; + + if (mech) { + junk = gss_oid_to_str(&junk, mech, &buf); + if (junk == GSS_S_COMPLETE) + fprintf(stderr, "mech = %.*s\n", (int)buf.length, (char *)buf.value); + gss_release_buffer(&junk, &buf); + } + do { + ret = gss_display_status(&junk, + stat, + mech ? GSS_C_MECH_CODE : GSS_C_GSS_CODE, + mech, + &more, + &buf); + if (ret != GSS_S_COMPLETE) + errx(1, "gss_display_status() failed"); + fprintf(stderr, "%.*s\n", (int)buf.length, (char *)buf.value); + gss_release_buffer(&junk, &buf); + } while (more); +} + +static void + __attribute__ ((__format__ (__printf__, 5, 6))) +gss_err(int exitval, + OM_uint32 maj, + OM_uint32 min, + gss_OID mech, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vwarnx(fmt, args); + va_end(args); + gss_print_errors(maj, GSS_C_NO_OID); + if (mech) + gss_print_errors(min, mech); + exit(exitval); +} + +#define MAKE_URN(tail) \ + { sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail) - 1, \ + GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail } + +/* + * Test RFC6680 name attributes for Kerberos. + */ +static void +check_name_attrs(void) +{ + CompositePrincipal p; + EncTicketPart *t; + gss_buffer_desc v = GSS_C_EMPTY_BUFFER; + gss_name_t n; + OM_uint32 maj, min; + int32_t ret; + gss_buffer_desc attrs[] = { + MAKE_URN("realm"), + MAKE_URN("name-ncomp"), + MAKE_URN("name-ncomp#0"), + MAKE_URN("peer-realm"), + MAKE_URN("ticket-authz-data"), + MAKE_URN("transit-path"), + MAKE_URN("canonical-name"), + }; /* Set of attributes we expect to see indicated */ + gss_buffer_set_desc attr_set; + size_t i, sz; + + memset(&p, 0, sizeof(p)); + attr_set.elements = attrs; + /* + * attr_set.count is set in each of the following sections to ever more + * items. + */ + + /* + * Testing name attributes is pretty tricky. + * + * Our approach is to construct a composite name, construct an exported + * composite name token for it, import it, then test the gss_inquire_name() + * and gss_get_name_attribute() accessors, and then gss_display_name_ext(). + * + * Ideally we'd test the accessors on names imported from query forms with + * gss_import_name(), and on names from established contexts. However, + * that belongs in the test_context program. + * + * TODO: Implement and test gss_set_name_attribute() and + * gss_delete_name_attribute(). + */ + + /* First construct and test an unauthenticated name */ + p.realm = estrdup("TEST.H5L.SE"); + p.name.name_type = KRB5_NT_PRINCIPAL; + p.name.name_string.val = ecalloc(1, sizeof(p.name.name_string.val[0])); + p.name.name_string.len = 1; + p.name.name_string.val[0] = estrdup("someuser"); + p.nameattrs = NULL; + make_composite_name(&p, &n); + + /* Test the attributes we expect it to have */ + v.length = sizeof("TEST.H5L.SE") - 1; + v.value = "TEST.H5L.SE"; + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE, + &v, "TEST.H5L.SE", 0, 1, 0); + + i = 1; + v.length = sizeof(size_t); + v.value = &i; + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp", + GSS_S_COMPLETE, &v, "1", 0, 1, 0); + + v.length = sizeof("someuser") - 1; + v.value = "someuser"; + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0", + GSS_S_COMPLETE, &v, "someuser", 0, 1, 0); + + attr_set.count = 3; + assert_attr_set(n, &attr_set); + + /* Check that it does not have prefixed attributes */ + assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "realm"); + assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "name-ncomp"); + assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "name-ncomp#0"); + assert_attr_unavail(n, "what ever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "name-ncomp#0"); + + /* Check that it does not have various other supported attributes */ + assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm"); + assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#1"); + assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name"); + assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "ticket-authz-data#pac"); + assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "ticket-authz-data"); + assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "transit-path"); + + /* Exercise URN parser */ + assert_attr_unavail(n, "urn:whatever"); + assert_attr_unavail(n, "urn:whatever#"); + assert_attr_unavail(n, "urn:what#ever"); + assert_attr_unavail(n, "#"); + assert_attr_unavail(n, "#whatever"); + assert_attr_unavail(n, "whatever"); + assert_attr_unavail(n, "what ever"); + assert_attr_unavail(n, "what ever#"); + + /* Now test an authenticated name */ + gss_release_name(&min, &n); + p.nameattrs = ecalloc(1, sizeof(p.nameattrs[0])); + p.nameattrs->authenticated = 1; + make_composite_name(&p, &n); + + v.length = sizeof("TEST.H5L.SE") - 1; + v.value = "TEST.H5L.SE"; + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE, + &v, "TEST.H5L.SE", 1, 1, 0); + + i = 1; + v.length = sizeof(size_t); + v.value = &i; + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp", + GSS_S_COMPLETE, &v, "1", 1, 1, 0); + + v.length = sizeof("someuser") - 1; + v.value = "someuser"; + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0", + GSS_S_COMPLETE, &v, "someuser", 1, 1, 0); + + assert_attr_set(n, &attr_set); + + /* Now add a peer realm */ + gss_release_name(&min, &n); + p.nameattrs->peer_realm = ecalloc(1, sizeof(p.nameattrs->peer_realm[0])); + p.nameattrs->peer_realm[0] = estrdup("FOO.TEST.H5L.SE"); + make_composite_name(&p, &n); + + v.length = sizeof("FOO.TEST.H5L.SE") - 1; + v.value = "FOO.TEST.H5L.SE"; + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm", + GSS_S_COMPLETE, &v, "FOO.TEST.H5L.SE", 1, 1, 0); + attr_set.count = 4; + assert_attr_set(n, &attr_set); + + /* Now add canonical name and an authz-data element */ + gss_release_name(&min, &n); + p.nameattrs->source = ecalloc(1, sizeof(p.nameattrs->source[0])); + p.nameattrs->source->element = choice_PrincipalNameAttrSrc_enc_ticket_part; + + t = &p.nameattrs->source->u.enc_ticket_part; + t->cname.name_type = KRB5_NT_PRINCIPAL; + t->cname.name_string.val = ecalloc(1, sizeof(t->cname.name_string.val[0])); + t->crealm = estrdup("TEST.H5L.SE"); + t->cname.name_string.len = 1; + t->cname.name_string.val[0] = estrdup("realusername"); + t->authorization_data = ecalloc(1, sizeof(t->authorization_data[0])); + t->authorization_data->val = + ecalloc(1, sizeof(t->authorization_data->val[0])); + t->authorization_data->len = 1; + t->authorization_data->val[0].ad_type = + KRB5_AUTHDATA_ON_BEHALF_OF; /* whatever */ + t->authorization_data->val[0].ad_data.data = + estrdup("foobar@TEST.H5L.SE"); + t->authorization_data->val[0].ad_data.length = + sizeof("foobar@TEST.H5L.SE") - 1; + make_composite_name(&p, &n); + + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name", + GSS_S_COMPLETE, GSS_C_NO_BUFFER, "realusername@TEST.H5L.SE", 1, + 1, 0); + + ASN1_MALLOC_ENCODE(AuthorizationData, v.value, v.length, + t->authorization_data, &sz, ret); + if (ret) + errx(1, "Failed to encode AuthorizationData"); + + assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "ticket-authz-data", + GSS_S_COMPLETE, &v, NULL, 0, 1, 0); + free(v.value); + + attr_set.count = 7; + assert_attr_set(n, &attr_set); + + gss_release_name(&min, &n); + free_CompositePrincipal(&p); + + /* + * Test gss_display_name_ext() with a host-based service principal + * "host/somehost.test.h5l.se@TEST.H5L.SE". + * + * Where gss_display_name() would display this as a Kerberos principal + * name, gss_display_name_ext() with GSS_C_NT_HOSTBASED_SERVICE should + * display it as "host@somehost.test.h5l.se". + */ + p.realm = estrdup("TEST.H5L.SE"); + p.name.name_type = KRB5_NT_SRV_HST; + p.name.name_string.val = ecalloc(2, sizeof(p.name.name_string.val[0])); + p.name.name_string.len = 2; + p.name.name_string.val[0] = estrdup("host"); + p.name.name_string.val[1] = estrdup("somehost.test.h5l.se"); + p.nameattrs = NULL; + make_composite_name(&p, &n); + + maj = gss_display_name_ext(&min, n, GSS_C_NT_HOSTBASED_SERVICE, &v); + if (maj) + gss_err(1, maj, min, GSS_KRB5_MECHANISM, "display name ext"); + if (v.length != sizeof("host@somehost.test.h5l.se") - 1 || + strncmp(v.value, "host@somehost.test.h5l.se", v.length) != 0) + errx(1, "display name ext"); + gss_release_buffer(&min, &v); + gss_release_name(&min, &n); + free_CompositePrincipal(&p); + + /* + * TODO: + * + * - test URN fragments for access to specific authorization data element + * types + * - test GSS_C_ATTR_LOCAL_LOGIN_USER support (requires configuration or + * that we register a plugin here) + */ +} + +static int version_flag = 0; +static int help_flag = 0; +static int anon_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"anonymous", 0, arg_flag, &anon_flag, "test anonymous names", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, "service@host"); + exit (ret); +} + + +int +main(int argc, char **argv) +{ + gss_buffer_desc name_buffer; + OM_uint32 maj_stat, min_stat; + gss_name_t name, MNname, MNname2; + int optidx = 0; + char *str; + int len, equal; + gss_OID mech_oid; + + setprogname(argv[0]); + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + gsskrb5_set_default_realm("MIT.EDU"); + + /* + * test import/export + */ + + str = NULL; + len = asprintf(&str, anon_flag ? + "WELLKNOWN@ANONYMOUS" : "ftp@freeze-arrow.mit.edu"); + if (len < 0 || str == NULL) + errx(1, "asprintf"); + + name_buffer.value = str; + name_buffer.length = len; + + maj_stat = gss_import_name(&min_stat, &name_buffer, + GSS_C_NT_HOSTBASED_SERVICE, + &name); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, GSS_C_NO_OID, "import name error"); + free(str); + + if (anon_flag) + mech_oid = GSS_SANON_X25519_MECHANISM; + else + mech_oid = GSS_KRB5_MECHANISM; + + maj_stat = gss_canonicalize_name (&min_stat, + name, + mech_oid, + &MNname); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, mech_oid, "canonicalize name error"); + + maj_stat = gss_export_name(&min_stat, + MNname, + &name_buffer); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, mech_oid, "export name error"); + + /* + * Import the exported name and compare + */ + + maj_stat = gss_import_name(&min_stat, &name_buffer, + GSS_C_NT_EXPORT_NAME, + &MNname2); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, mech_oid, "export name error"); + + + maj_stat = gss_compare_name(&min_stat, MNname, MNname2, &equal); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, mech_oid, "compare name error"); + if (equal && anon_flag) + errx(1, "names %s equal", anon_flag ? "incorrectly" : "not"); + + gss_release_name(&min_stat, &MNname2); + gss_release_buffer(&min_stat, &name_buffer); + gss_release_name(&min_stat, &MNname); + gss_release_name(&min_stat, &name); + + /* + * Import oid less name and compare to mech name. + * Dovecot SASL lib does this. + */ + + str = NULL; + len = asprintf(&str, "lha"); + if (len < 0 || str == NULL) + errx(1, "asprintf"); + + name_buffer.value = str; + name_buffer.length = len; + + maj_stat = gss_import_name(&min_stat, &name_buffer, + GSS_C_NO_OID, + &name); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, NULL, "import (no oid) name error"); + + maj_stat = gss_import_name(&min_stat, &name_buffer, + GSS_KRB5_NT_USER_NAME, + &MNname); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, NULL, "import (krb5 mn) name error"); + + free(str); + + maj_stat = gss_compare_name(&min_stat, name, MNname, &equal); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_compare_name"); + if (!equal) + errx(1, "names not equal"); + + gss_release_name(&min_stat, &MNname); + gss_release_name(&min_stat, &name); + +#if 0 + maj_stat = gss_canonicalize_name (&min_stat, + name, + GSS_SPNEGO_MECHANISM, + &MNname); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM, + "canonicalize name error"); + + + maj_stat = gss_export_name(&maj_stat, + MNname, + &name_buffer); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM, + "export name error (SPNEGO)"); + + gss_release_name(&min_stat, &MNname); + gss_release_buffer(&min_stat, &name_buffer); +#endif + + if (anon_flag) { + /* check anonymous name canonicalizes to well known name */ + gss_OID name_type; + + name_buffer.length = 0; + name_buffer.value = NULL; + + maj_stat = gss_import_name(&min_stat, &name_buffer, + GSS_C_NT_ANONYMOUS, &name); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, GSS_C_NO_OID, + "import (anon) name error"); + + maj_stat = gss_canonicalize_name(&min_stat, name, + GSS_SANON_X25519_MECHANISM, + &MNname); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM, + "canonicalize (anon) name error"); + + maj_stat = gss_display_name(&min_stat, MNname, + &name_buffer, &name_type); + if (maj_stat != GSS_S_COMPLETE) + gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM, + "display_name (anon) name error"); + + if (!gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)) + errx(1, "display name type not anonymous"); + if (memcmp(name_buffer.value, "WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS", + sizeof("WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS") - 1) != 0) + errx(1, "display name string not well known anonymous name"); + + gss_release_name(&min_stat, &MNname); + gss_release_name(&min_stat, &name); + gss_release_buffer(&min_stat, &name_buffer); + } + + check_name_attrs(); + return 0; +} + +/* Copied from _gsskrb5_export_name_composite() */ +static void +export_name_composite(CompositePrincipal *name, gss_buffer_t exported_name) +{ + gss_buffer_desc inner = GSS_C_EMPTY_BUFFER; + unsigned char *buf; + int32_t ret; + size_t sz; + + ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length, + (void *)name, &sz, ret); + if (ret) + errx(1, "Failed to encode exported composite name token"); + + exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length; + exported_name->value = malloc(exported_name->length); + if (exported_name->value == NULL) + errx(1, "Failed to allocate exported composite name token"); + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + buf = exported_name->value; + buf[0] = 0x04; + buf[1] = 0x02; + buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; + buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; + buf[4] = 0x06; + buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF; + + memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + buf += 6 + GSS_KRB5_MECHANISM->length; + + buf[0] = (inner.length >> 24) & 0xff; + buf[1] = (inner.length >> 16) & 0xff; + buf[2] = (inner.length >> 8) & 0xff; + buf[3] = (inner.length) & 0xff; + buf += 4; + + memcpy(buf, inner.value, inner.length); + free(inner.value); +} + +static void +make_composite_name(CompositePrincipal *princ, gss_name_t *n) +{ + gss_buffer_desc token, exported; + OM_uint32 maj, min; + + export_name_composite(princ, &token); + maj = gss_import_name(&min, &token, GSS_C_NT_COMPOSITE_EXPORT, n); + if (maj) + gss_err(1, maj, min, GSS_KRB5_MECHANISM, "import composite name"); + maj = gss_export_name_composite(&min, *n, &exported); + if (maj) + gss_err(1, maj, min, GSS_KRB5_MECHANISM, "export composite name"); + if (token.length != exported.length || + memcmp(token.value, exported.value, token.length) != 0) + errx(1, "import/export composite token disagreement"); + gss_release_buffer(&min, &exported); + free(token.value); /* Use free because we allocated this one */ +} + +static void +assert_attr(gss_name_t n, + const char *aname, + OM_uint32 exp_maj, + gss_buffer_t exp_v, + const char *exp_dv, + int exp_authenticated, + int exp_complete, + int exp_multivalued) +{ + gss_buffer_desc dv = GSS_C_EMPTY_BUFFER; + gss_buffer_desc v = GSS_C_EMPTY_BUFFER; + gss_buffer_desc a; + OM_uint32 maj, min; + int authenticated, complete, more; + + a.value = (void*)(uintptr_t)aname; + a.length = strlen(aname); + more = 0; + maj = gss_get_name_attribute(&min, n, &a, &authenticated, &complete, &v, + &dv, &more); + if (maj != GSS_S_COMPLETE && maj != exp_maj) + gss_err(1, maj, min, GSS_KRB5_MECHANISM, + "import composite name error"); + if (maj == GSS_S_COMPLETE && maj != exp_maj) + errx(1, "unexpected name attribute %s", aname); + if (maj == GSS_S_COMPLETE) { + if (exp_v && + (v.length != exp_v->length || + memcmp(v.value, exp_v->value, exp_v->length) != 0)) + errx(1, "import composite name: wrong %s value", aname); + if (exp_dv && + (dv.length != strlen(exp_dv) || + strncmp(dv.value, exp_dv, dv.length) != 0)) + errx(1, "import composite name: wrong %s display value " + "(wanted %s, got %.*s)", aname, exp_dv, + (int)dv.length, (char *)dv.value); + if (authenticated != exp_authenticated) + errx(1, "import composite name: %s incorrectly marked " + "%sauthenticated", aname, authenticated ? "" : "un"); + if (complete != exp_complete) + errx(1, "import composite name: %s incorrectly marked " + "%scomplete", aname, complete ? "" : "in"); + if (more != exp_multivalued) + errx(1, "import composite name: %s incorrectly marked " + "%s-valued", aname, more ? "multi" : "single"); + } + gss_release_buffer(&min, &dv); + gss_release_buffer(&min, &v); +} + +static void +assert_attr_unavail(gss_name_t n, const char *aname) +{ + assert_attr(n, aname, GSS_S_UNAVAILABLE, GSS_C_NO_BUFFER, NULL, 0, 0, 0); +} + +static void +assert_attr_set(gss_name_t n, gss_buffer_set_t exp_as) +{ + OM_uint32 maj, min; + gss_buffer_set_t as = NULL; + gss_OID MN_mech = GSS_C_NO_OID; + size_t i; + int name_is_MN = 0; + + maj = gss_inquire_name(&min, n, &name_is_MN, &MN_mech, &as); + if (maj) + gss_err(1, maj, min, MN_mech, "inquire name"); + for (i = 0; i < as->count && i < exp_as->count; i++) { + if (as->elements[i].length != exp_as->elements[i].length || + memcmp(as->elements[i].value, exp_as->elements[i].value, + as->elements[i].length) != 0) + errx(1, "attribute sets differ"); + } + if (i < as->count) + errx(1, "more attributes indicated than expected"); + if (i < exp_as->count) + errx(1, "fewer attributes indicated than expected"); + gss_release_buffer_set(&min, &as); +} diff --git a/third_party/heimdal/lib/gssapi/test_negoex_mech.c b/third_party/heimdal/lib/gssapi/test_negoex_mech.c new file mode 100644 index 0000000..559c5de --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_negoex_mech.c @@ -0,0 +1,592 @@ +/* + * Copyright (C) 2019 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include <krb5.h> +#include <der.h> +#include <gssapi_asn1.h> + +#include <gssapi/gssapi.h> +#include <gssapi/gssapi_spnego.h> + +struct test_context { + int initiator; + uint8_t hops; /* hops remaining; 0 means established */ +}; + +OM_uint32 GSSAPI_CALLCONV +gss_init_sec_context(OM_uint32 *minor_status, + gss_const_cred_id_t claimant_cred_handle, + gss_ctx_id_t *context_handle, gss_const_name_t target_name, + const gss_OID mech_type, OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, gss_OID *actual_mech, + gss_buffer_t output_token, OM_uint32 *ret_flags, + OM_uint32 *time_rec) +{ + struct test_context *ctx = (struct test_context *)*context_handle; + OM_uint32 major; + gss_buffer_desc tok; + const char *envstr; + uint8_t hops, mech_last_octet; + + if (actual_mech) + *actual_mech = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + + major = gss_duplicate_oid(minor_status, mech_type, actual_mech); + if (major != GSS_S_COMPLETE) + return major; + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + envstr = getenv("HOPS"); + hops = (envstr != NULL) ? atoi(envstr) : 1; + assert(hops > 0); + } else if (input_token->length == 4 && + memcmp(input_token->value, "fail", 4) == 0) { + *minor_status = 12345; + return GSS_S_FAILURE; + } else { + hops = ((uint8_t *)input_token->value)[0]; + } + + mech_last_octet = ((uint8_t *)mech_type->elements)[mech_type->length - 1]; + envstr = getenv("INIT_FAIL"); + if (envstr != NULL && atoi(envstr) == mech_last_octet) + return GSS_S_FAILURE; + + if (ctx == NULL) { + ctx = malloc(sizeof(*ctx)); + assert(ctx != NULL); + ctx->initiator = 1; + ctx->hops = hops; + *context_handle = (gss_ctx_id_t)ctx; + } else if (ctx != NULL) { + assert(ctx->initiator); + ctx->hops--; + assert(ctx->hops == hops); + } + + if (ctx->hops > 0) { + /* Generate a token containing the remaining hop count. */ + ctx->hops--; + tok.value = &ctx->hops; + tok.length = 1; + major = gss_encapsulate_token(&tok, mech_type, output_token); + assert(major == GSS_S_COMPLETE); + } + + return (ctx->hops > 0) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, + gss_const_cred_id_t verifier_cred_handle, + const gss_buffer_t input_token, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, gss_OID *mech_type, + gss_buffer_t output_token, OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle) +{ + struct test_context *ctx = (struct test_context *)*context_handle; + uint8_t hops, mech_last_octet; + const char *envstr; + unsigned char mechbuf[64]; + GSSAPIContextToken ct; + gss_OID_desc oid; + int ret; + size_t mech_len; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (mech_type) + *mech_type = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + ret = decode_GSSAPIContextToken(input_token->value, input_token->length, + &ct, NULL); + if (ret == 0) { + ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, + sizeof(mechbuf), + &ct.thisMech, + &mech_len); + free_GSSAPIContextToken(&ct); + } + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + oid.length = (OM_uint32)mech_len; + oid.elements = mechbuf + sizeof(mechbuf) - mech_len; + + if (mech_type) + gss_duplicate_oid(minor_status, &oid, mech_type); + + /* + * The unwrapped token sits at the end and is just one byte giving the + * remaining number of hops. The final octet of the mech encoding should + * be just prior to it. + */ + assert(input_token->length >= 2); + hops = ((uint8_t *)input_token->value)[input_token->length - 1]; + mech_last_octet = ((uint8_t *)input_token->value)[input_token->length - 2]; + + envstr = getenv("ACCEPT_FAIL"); + if (envstr != NULL && atoi(envstr) == mech_last_octet) { + output_token->value = strdup("fail"); + assert(output_token->value != NULL); + output_token->length = 4; + return GSS_S_FAILURE; + } + + if (*context_handle == GSS_C_NO_CONTEXT) { + ctx = malloc(sizeof(*ctx)); + assert(ctx != NULL); + ctx->initiator = 0; + ctx->hops = hops; + *context_handle = (gss_ctx_id_t)ctx; + } else { + assert(!ctx->initiator); + ctx->hops--; + assert(ctx->hops == hops); + } + + if (ctx->hops > 0) { + /* Generate a token containing the remaining hop count. */ + ctx->hops--; + output_token->value = malloc(1); + assert(output_token->value != NULL); + memcpy(output_token->value, &ctx->hops, 1); + output_token->length = 1; + } + + return (ctx->hops > 0) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gss_delete_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, + gss_buffer_t output_token) +{ + free(*context_handle); + *context_handle = GSS_C_NO_CONTEXT; + return GSS_S_COMPLETE; +} + +static int dummy_cred; + +OM_uint32 GSSAPI_CALLCONV +gss_acquire_cred(OM_uint32 *minor_status, gss_const_name_t desired_name, + OM_uint32 time_req, const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + *minor_status = 0; + *output_cred_handle = (gss_cred_id_t)&dummy_cred; + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gss_acquire_cred_with_password(OM_uint32 *minor_status, + gss_const_name_t desired_name, + const gss_buffer_t password, OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, OM_uint32 *time_rec) +{ + *minor_status = 0; + *output_cred_handle = (gss_cred_id_t)&dummy_cred; + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) +{ + return GSS_S_COMPLETE; +} + +static int dummy_name; + +OM_uint32 GSSAPI_CALLCONV +gss_import_name(OM_uint32 *minor_status, gss_buffer_t input_name_buffer, + gss_OID input_name_type, gss_name_t *output_name) +{ + /* + * We don't need to remember anything about names, but we do need to + * distinguish them from GSS_C_NO_NAME (to determine the direction of + * gss_query_meta_data() and gss_exchange_meta_data()), so assign an + * arbitrary data pointer. + */ + *output_name = (gss_name_t)&dummy_name; + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name) +{ + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value, + int status_type, gss_OID mech_type, + OM_uint32 *message_context, gss_buffer_t status_string) +{ + if (status_type == GSS_C_MECH_CODE && status_value == 12345) { + status_string->value = strdup("failure from acceptor"); + assert(status_string->value != NULL); + status_string->length = strlen(status_string->value); + return GSS_S_COMPLETE; + } + return GSS_S_BAD_STATUS; +} + +OM_uint32 GSSAPI_CALLCONV +gssspi_query_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid, + gss_cred_id_t cred_handle, gss_ctx_id_t *context_handle, + gss_const_name_t targ_name, OM_uint32 req_flags, + gss_buffer_t meta_data) +{ + const char *envstr; + uint8_t mech_last_octet; + int initiator = (targ_name != GSS_C_NO_NAME); + + mech_last_octet = ((uint8_t *)mech_oid->elements)[mech_oid->length - 1]; + envstr = getenv(initiator ? "INIT_QUERY_FAIL" : "ACCEPT_QUERY_FAIL"); + if (envstr != NULL && atoi(envstr) == mech_last_octet) + return GSS_S_FAILURE; + envstr = getenv(initiator ? "INIT_QUERY_NONE" : "ACCEPT_QUERY_NONE"); + if (envstr != NULL && atoi(envstr) == mech_last_octet) + return GSS_S_COMPLETE; + + meta_data->value = strdup("X"); + meta_data->length = 1; + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gssspi_exchange_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *context_handle, + gss_const_name_t targ_name, OM_uint32 req_flags, + gss_const_buffer_t meta_data) +{ + const char *envstr; + uint8_t mech_last_octet; + int initiator = (targ_name != GSS_C_NO_NAME); + + mech_last_octet = ((uint8_t *)mech_oid->elements)[mech_oid->length - 1]; + envstr = getenv(initiator ? "INIT_EXCHANGE_FAIL" : "ACCEPT_EXCHANGE_FAIL"); + if (envstr != NULL && atoi(envstr) == mech_last_octet) + return GSS_S_FAILURE; + + assert(meta_data->length == 1 && memcmp(meta_data->value, "X", 1) == 0); + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gssspi_query_mechanism_info(OM_uint32 *minor_status, gss_const_OID mech_oid, + unsigned char auth_scheme[16]) +{ + /* Copy the mech OID encoding and right-pad it with zeros. */ + memset(auth_scheme, 0, 16); + assert(mech_oid->length <= 16); + memcpy(auth_scheme, mech_oid->elements, mech_oid->length); + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_CALLCONV +gss_inquire_sec_context_by_oid(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + struct test_context *ctx = (struct test_context *)context_handle; + OM_uint32 major; + uint8_t keybytes[32] = { 0 }; + uint8_t typebytes[4]; + gss_buffer_desc key, type; + const char *envstr; + int ask_verify; + + if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY)) + ask_verify = 0; + else if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY)) + ask_verify = 1; + else + return GSS_S_UNAVAILABLE; + + /* + * By default, make a key available only if the context is established. + * This can be overridden to "always", "init-always", "accept-always", + * or "never". + */ + envstr = getenv("KEY"); + if (envstr != NULL && strcmp(envstr, "never") == 0) { + return GSS_S_UNAVAILABLE; + } else if (ctx->hops > 0) { + if (envstr == NULL) + return GSS_S_UNAVAILABLE; + else if (strcmp(envstr, "init-always") == 0 && !ctx->initiator) + return GSS_S_UNAVAILABLE; + else if (strcmp(envstr, "accept-always") == 0 && ctx->initiator) + return GSS_S_UNAVAILABLE; + } + + /* Perturb the key so that each side's verifier key is equal to the other's + * checksum key. */ + keybytes[0] = ask_verify ^ ctx->initiator; + + /* Supply an all-zeros aes256-sha1 negoex key. */ + if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY) || + gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY)) { + OM_uint32 n = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + + typebytes[0] = (n >> 0 ) & 0xFF; + typebytes[1] = (n >> 8 ) & 0xFF; + typebytes[2] = (n >> 16) & 0xFF; + typebytes[3] = (n >> 24) & 0xFF; + + key.value = keybytes; + key.length = sizeof(keybytes); + type.value = typebytes; + type.length = sizeof(typebytes); + major = gss_add_buffer_set_member(minor_status, &key, data_set); + if (major != GSS_S_COMPLETE) + return major; + return gss_add_buffer_set_member(minor_status, &type, data_set); + } + + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_process_context_token(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t token_buffer) +{ + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_context_time(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + OM_uint32 *time_rec) +{ + *time_rec = 0; + return GSS_S_COMPLETE; +} + +/* + * We also need to supply a fake MIC in case SPNEGO test negotiates + * as non-default mechanism + */ +#define FAKE_MIC "negoex-fake-mic" +#define FAKE_MIC_LEN (sizeof(FAKE_MIC) - 1) + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_get_mic(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + message_token->value = strdup(FAKE_MIC); + message_token->length = FAKE_MIC_LEN; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_verify_mic(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + *minor_status = 0; + if (token_buffer->length == FAKE_MIC_LEN && + memcmp(token_buffer->value, FAKE_MIC, FAKE_MIC_LEN) == 0) + return GSS_S_COMPLETE; + else + return GSS_S_BAD_MIC; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_unwrap(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_compare_name(OM_uint32 *minor_status, + gss_const_name_t name1_arg, + gss_const_name_t name2_arg, + int *name_equal) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_display_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_export_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + gss_buffer_t exported_name) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_context(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *xopen) +{ + *lifetime_rec = GSS_C_INDEFINITE; + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_wrap_size_limit(OM_uint32 *minor_status, + gss_const_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_import_sec_context(OM_uint32 *minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_export_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_canonicalize_name(OM_uint32 *minor_status, + gss_const_name_t input_name, + const gss_OID mech_type, + gss_name_t *output_name) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_duplicate_name(OM_uint32 *minor_status, + gss_const_name_t src_name, + gss_name_t *dest_name) +{ + return GSS_S_UNAVAILABLE; +} + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_inquire_cred(OM_uint32 *minor_status, + gss_const_cred_id_t cred_handle, + gss_name_t *name_ret, + OM_uint32 *lifetime, + gss_cred_usage_t *cred_usage, + gss_OID_set *mechanisms) +{ + if (name_ret) + *name_ret = (gss_name_t)&dummy_name; + if (lifetime) + *lifetime = GSS_C_INDEFINITE; + if (cred_usage) + *cred_usage = GSS_C_BOTH; + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; + + return GSS_S_COMPLETE; +} + diff --git a/third_party/heimdal/lib/gssapi/test_ntlm.c b/third_party/heimdal/lib/gssapi/test_ntlm.c new file mode 100644 index 0000000..de3a8dd --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_ntlm.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include <roken.h> +#include <stdio.h> +#include <gssapi.h> +#include <err.h> +#include <getarg.h> +#include "test_common.h" + +#include <krb5.h> +#include <heimntlm.h> + +static int +test_libntlm_v1(int flags) +{ + const char *user = "foo", + *domain = "mydomain", + *password = "digestpassword"; + OM_uint32 maj_stat, min_stat; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_buffer_desc input, output; + struct ntlm_type1 type1; + struct ntlm_type2 type2; + struct ntlm_type3 type3; + struct ntlm_buf data; + krb5_error_code ret; + gss_name_t src_name = GSS_C_NO_NAME; + + memset(&type1, 0, sizeof(type1)); + memset(&type2, 0, sizeof(type2)); + memset(&type3, 0, sizeof(type3)); + + type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_TARGET|NTLM_NEG_NTLM|flags; + type1.domain = strdup(domain); + type1.hostname = NULL; + type1.os[0] = 0; + type1.os[1] = 0; + + ret = heim_ntlm_encode_type1(&type1, &data); + if (ret) + errx(1, "heim_ntlm_encode_type1"); + + input.value = data.data; + input.length = data.length; + + output.length = 0; + output.value = NULL; + + maj_stat = gss_accept_sec_context(&min_stat, + &ctx, + GSS_C_NO_CREDENTIAL, + &input, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, + &output, + NULL, + NULL, + NULL); + free(data.data); + if (GSS_ERROR(maj_stat)) + errx(1, "accept_sec_context v1: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + + if (output.length == 0) + errx(1, "output.length == 0"); + + data.data = output.value; + data.length = output.length; + + ret = heim_ntlm_decode_type2(&data, &type2); + if (ret) + errx(1, "heim_ntlm_decode_type2"); + + gss_release_buffer(&min_stat, &output); + + type3.flags = type2.flags; + type3.username = rk_UNCONST(user); + type3.targetname = type2.targetname; + type3.ws = rk_UNCONST("workstation"); + + { + struct ntlm_buf key; + + heim_ntlm_nt_key(password, &key); + + heim_ntlm_calculate_ntlm1(key.data, key.length, + type2.challenge, + &type3.ntlm); + + if (flags & NTLM_NEG_KEYEX) { + struct ntlm_buf sessionkey; + heim_ntlm_build_ntlm1_master(key.data, key.length, + &sessionkey, + &type3.sessionkey); + free(sessionkey.data); + } + free(key.data); + } + + ret = heim_ntlm_encode_type3(&type3, &data, NULL); + if (ret) + errx(1, "heim_ntlm_encode_type3"); + + input.length = data.length; + input.value = data.data; + + maj_stat = gss_accept_sec_context(&min_stat, + &ctx, + GSS_C_NO_CREDENTIAL, + &input, + GSS_C_NO_CHANNEL_BINDINGS, + &src_name, + NULL, + &output, + NULL, + NULL, + NULL); + free(input.value); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "accept_sec_context v1 2 %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + + gss_release_buffer(&min_stat, &output); + gss_delete_sec_context(&min_stat, &ctx, NULL); + + if (src_name == GSS_C_NO_NAME) + errx(1, "no source name!"); + + gss_display_name(&min_stat, src_name, &output, NULL); + + printf("src_name: %.*s\n", (int)output.length, (char*)output.value); + + gss_release_name(&min_stat, &src_name); + gss_release_buffer(&min_stat, &output); + + return 0; +} + +static int +test_libntlm_v2(int flags) +{ + const char *user = "foo", + *domain = "mydomain", + *password = "digestpassword"; + OM_uint32 maj_stat, min_stat; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_buffer_desc input, output; + struct ntlm_type1 type1; + struct ntlm_type2 type2; + struct ntlm_type3 type3; + struct ntlm_buf data; + krb5_error_code ret; + + memset(&type1, 0, sizeof(type1)); + memset(&type2, 0, sizeof(type2)); + memset(&type3, 0, sizeof(type3)); + + type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_NTLM|flags; + type1.domain = strdup(domain); + type1.hostname = NULL; + type1.os[0] = 0; + type1.os[1] = 0; + + ret = heim_ntlm_encode_type1(&type1, &data); + if (ret) + errx(1, "heim_ntlm_encode_type1"); + + input.value = data.data; + input.length = data.length; + + output.length = 0; + output.value = NULL; + + maj_stat = gss_accept_sec_context(&min_stat, + &ctx, + GSS_C_NO_CREDENTIAL, + &input, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, + &output, + NULL, + NULL, + NULL); + free(data.data); + if (GSS_ERROR(maj_stat)) + errx(1, "accept_sec_context v2 %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + + if (output.length == 0) + errx(1, "output.length == 0"); + + data.data = output.value; + data.length = output.length; + + ret = heim_ntlm_decode_type2(&data, &type2); + if (ret) + errx(1, "heim_ntlm_decode_type2"); + + type3.flags = type2.flags; + type3.username = rk_UNCONST(user); + type3.targetname = type2.targetname; + type3.ws = rk_UNCONST("workstation"); + + { + struct ntlm_buf key; + unsigned char ntlmv2[16]; + + heim_ntlm_nt_key(password, &key); + + heim_ntlm_calculate_ntlm2(key.data, key.length, + user, + type2.targetname, + type2.challenge, + &type2.targetinfo, + ntlmv2, + &type3.ntlm); + free(key.data); + + if (flags & NTLM_NEG_KEYEX) { + struct ntlm_buf sessionkey; + heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), + &sessionkey, + &type3.sessionkey); + free(sessionkey.data); + } + } + + ret = heim_ntlm_encode_type3(&type3, &data, NULL); + if (ret) + errx(1, "heim_ntlm_encode_type3"); + + input.length = data.length; + input.value = data.data; + + maj_stat = gss_accept_sec_context(&min_stat, + &ctx, + GSS_C_NO_CREDENTIAL, + &input, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, + &output, + NULL, + NULL, + NULL); + free(input.value); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "accept_sec_context v2 2 %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + + gss_delete_sec_context(&min_stat, &ctx, NULL); + + return 0; +} + + + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, "print version", NULL }, + {"help", 0, arg_flag, &help_flag, NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), + NULL, ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int ret = 0, optidx = 0; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret += test_libntlm_v1(0); + ret += test_libntlm_v1(NTLM_NEG_KEYEX); + + ret += test_libntlm_v2(0); + ret += test_libntlm_v2(NTLM_NEG_KEYEX); + + return ret; +} diff --git a/third_party/heimdal/lib/gssapi/test_oid.c b/third_party/heimdal/lib/gssapi/test_oid.c new file mode 100644 index 0000000..ced8a05 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/test_oid.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> +#include <stdio.h> +#include <gssapi.h> +#include <gssapi_krb5.h> +#include <gssapi_spnego.h> +#include <err.h> + +int +main(int argc, char **argv) +{ + OM_uint32 minor_status, maj_stat; + gss_buffer_desc data; + int ret; + + maj_stat = gss_oid_to_str(&minor_status, GSS_KRB5_MECHANISM, &data); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_oid_to_str failed"); + + ret = strncmp(data.value, "1 2 840 113554 1 2 2", data.length); + gss_release_buffer(&maj_stat, &data); + if (ret != 0) + return 1; + + maj_stat = gss_oid_to_str(&minor_status, GSS_C_NT_EXPORT_NAME, &data); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_oid_to_str failed"); + + ret = strncmp(data.value, "1 3 6 1 5 6 4", data.length); + gss_release_buffer(&maj_stat, &data); + if (ret != 0) + return 1; + + return 0; +} diff --git a/third_party/heimdal/lib/gssapi/version-script.map b/third_party/heimdal/lib/gssapi/version-script.map new file mode 100644 index 0000000..7f482b5 --- /dev/null +++ b/third_party/heimdal/lib/gssapi/version-script.map @@ -0,0 +1,210 @@ +# $Id$ + +HEIMDAL_GSS_2.0 { + global: +# __gss_c_nt_anonymous; + __gss_c_nt_anonymous_oid_desc; + __gss_c_nt_composite_export_oid_desc; + __gss_c_nt_export_name_oid_desc; + __gss_c_nt_hostbased_service_oid_desc; + __gss_c_nt_hostbased_service_x_oid_desc; + __gss_c_nt_machine_uid_name_oid_desc; + __gss_c_nt_string_uid_name_oid_desc; + __gss_c_nt_user_name_oid_desc; + __gss_krb5_nt_principal_name_oid_desc; + __gss_c_attr_stream_sizes_oid_desc; + __gss_c_attr_local_login_user; + gss_accept_sec_context; + gss_acquire_cred; + gss_acquire_cred_from; + gss_acquire_cred_impersonate_name; + gss_acquire_cred_with_password; + gss_add_buffer_set_member; + gss_add_cred; + gss_add_cred_from; + gss_add_cred_with_password; + gss_add_oid_set_member; + gss_authorize_localname; + gss_canonicalize_name; + gss_compare_name; + gss_context_query_attributes; + gss_context_time; + gss_create_empty_buffer_set; + gss_create_empty_oid_set; + gss_decapsulate_token; + gss_delete_name_attribute; + gss_delete_sec_context; + gss_display_name; + gss_display_name_ext; + gss_display_status; + gss_duplicate_name; + gss_duplicate_oid; + gss_duplicate_oid_set; + gss_encapsulate_token; + gss_export_cred; + gss_export_name; + gss_export_name_composite; + gss_export_sec_context; + gss_get_mic; + gss_get_neg_mechs; + gss_get_name_attribute; + gss_import_cred; + gss_import_name; + gss_import_sec_context; + gss_indicate_mechs; + gss_init_sec_context; + gss_inquire_context; + gss_inquire_cred; + gss_inquire_cred_by_mech; + gss_inquire_cred_by_oid; + gss_inquire_mechs_for_name; + gss_inquire_name; + gss_inquire_names_for_mech; + gss_inquire_sec_context_by_oid; + gss_inquire_sec_context_by_oid; + gss_krb5_ccache_name; + gss_krb5_copy_ccache; + gss_krb5_export_lucid_sec_context; + gss_krb5_free_lucid_sec_context; + gss_krb5_get_tkt_flags; + gss_krb5_import_cred; + gss_krb5_set_allowable_enctypes; + gss_localname; + gss_mg_collect_error; + gss_oid_equal; + gss_oid_to_str; + gss_pname_to_uid; + gss_process_context_token; + gss_pseudo_random; + gss_release_buffer; + gss_release_buffer_set; + gss_release_cred; + gss_release_iov_buffer; + gss_release_name; + gss_release_oid; + gss_release_oid_set; + gss_seal; + gss_set_cred_option; + gss_set_name_attribute; + gss_set_log_function; + gss_set_neg_mechs; + gss_set_sec_context_option; + gss_sign; + gss_store_cred; + gss_store_cred_into; + gss_store_cred_into2; + gss_test_oid_set_member; + gss_unseal; + gss_unwrap; + gss_unwrap_aead; + gss_unwrap_iov; + gss_userok; + gss_verify; + gss_verify_mic; + gss_wrap; + gss_wrap_aead; + gss_wrap_iov; + gss_wrap_iov_length; + gss_wrap_size_limit; + gsskrb5_extract_authtime_from_sec_context; + gsskrb5_extract_authz_data_from_sec_context; + gsskrb5_extract_service_keyblock; + gsskrb5_get_initiator_subkey; + gsskrb5_get_subkey; + gsskrb5_get_time_offset; + gsskrb5_register_acceptor_identity; + gsskrb5_set_default_realm; + gsskrb5_set_dns_canonicalize; + gsskrb5_set_send_to_kdc; + gsskrb5_set_time_offset; + krb5_gss_register_acceptor_identity; + gss_display_mech_attr; + gss_inquire_attrs_for_mech; + gss_indicate_mechs_by_attrs; + gss_inquire_mech_for_saslname; + gss_inquire_saslname_for_mech; + gss_mo_get; + gss_mo_set; + gss_mo_list; + gss_mo_name; + gss_name_to_oid; + gss_oid_to_name; + + # _gsskrb5cfx_ are really internal symbols, but export + # then now to make testing easier. + _gsskrb5cfx_wrap_length_cfx; + _gssapi_wrap_size_cfx; + + __gss_krb5_copy_ccache_x_oid_desc; + __gss_krb5_get_tkt_flags_x_oid_desc; + __gss_krb5_extract_authz_data_from_sec_context_x_oid_desc; + __gss_krb5_compat_des3_mic_x_oid_desc; + __gss_krb5_register_acceptor_identity_x_oid_desc; + __gss_krb5_export_lucid_context_x_oid_desc; + __gss_krb5_export_lucid_context_v1_x_oid_desc; + __gss_krb5_set_dns_canonicalize_x_oid_desc; + __gss_krb5_get_subkey_x_oid_desc; + __gss_krb5_get_initiator_subkey_x_oid_desc; + __gss_krb5_get_acceptor_subkey_x_oid_desc; + __gss_krb5_send_to_kdc_x_oid_desc; + __gss_krb5_get_authtime_x_oid_desc; + __gss_krb5_get_service_keyblock_x_oid_desc; + __gss_krb5_set_allowable_enctypes_x_oid_desc; + __gss_krb5_set_default_realm_x_oid_desc; + __gss_krb5_ccache_name_x_oid_desc; + __gss_krb5_set_time_offset_x_oid_desc; + __gss_krb5_get_time_offset_x_oid_desc; + __gss_krb5_plugin_register_x_oid_desc; + __gss_ntlm_get_session_key_x_oid_desc; + __gss_c_nt_ntlm_oid_desc; + __gss_c_nt_dn_oid_desc; + __gss_krb5_nt_principal_name_referral_oid_desc; + __gss_c_ntlm_avguest_oid_desc; + __gss_c_ntlm_v1_oid_desc; + __gss_c_ntlm_v2_oid_desc; + __gss_c_ntlm_session_key_oid_desc; + __gss_c_ntlm_force_v1_oid_desc; + __gss_krb5_cred_no_ci_flags_x_oid_desc; + __gss_krb5_import_cred_x_oid_desc; + __gss_c_ma_sasl_mech_name_oid_desc; + __gss_c_ma_mech_name_oid_desc; + __gss_c_ma_mech_description_oid_desc; + __gss_sasl_digest_md5_mechanism_oid_desc; + __gss_krb5_mechanism_oid_desc; + __gss_ntlm_mechanism_oid_desc; + __gss_spnego_mechanism_oid_desc; + __gss_sanon_x25519_mechanism_oid_desc; + __gss_c_ma_mech_concrete_oid_desc; + __gss_c_ma_mech_pseudo_oid_desc; + __gss_c_ma_mech_composite_oid_desc; + __gss_c_ma_mech_nego_oid_desc; + __gss_c_ma_mech_glue_oid_desc; + __gss_c_ma_not_mech_oid_desc; + __gss_c_ma_deprecated_oid_desc; + __gss_c_ma_not_dflt_mech_oid_desc; + __gss_c_ma_itok_framed_oid_desc; + __gss_c_ma_auth_init_oid_desc; + __gss_c_ma_auth_targ_oid_desc; + __gss_c_ma_auth_init_init_oid_desc; + __gss_c_ma_auth_targ_init_oid_desc; + __gss_c_ma_auth_init_anon_oid_desc; + __gss_c_ma_auth_targ_anon_oid_desc; + __gss_c_ma_deleg_cred_oid_desc; + __gss_c_ma_integ_prot_oid_desc; + __gss_c_ma_conf_prot_oid_desc; + __gss_c_ma_mic_oid_desc; + __gss_c_ma_wrap_oid_desc; + __gss_c_ma_prot_ready_oid_desc; + __gss_c_ma_replay_det_oid_desc; + __gss_c_ma_oos_det_oid_desc; + __gss_c_ma_cbindings_oid_desc; + __gss_c_ma_pfs_oid_desc; + __gss_c_ma_compress_oid_desc; + __gss_c_ma_ctx_trans_oid_desc; + __gss_c_ma_negoex_and_spnego_oid_desc; + __gss_c_inq_negoex_key_oid_desc; + __gss_c_inq_negoex_verify_key_oid_desc; + + local: + *; +}; |