📄 accept_sec_context.c
字号:
/* * Copyright (c) 1997 - 2006 Kungliga Tekniska H鰃skolan * (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/spnego_locl.h"RCSID("$Id: accept_sec_context.c 22600 2008-02-21 12:46:24Z lha $");static OM_uint32send_reject (OM_uint32 *minor_status, gss_buffer_t output_token){ NegotiationToken nt; size_t size; nt.element = choice_NegotiationToken_negTokenResp; ALLOC(nt.u.negTokenResp.negResult, 1); if (nt.u.negTokenResp.negResult == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } *(nt.u.negTokenResp.negResult) = reject; nt.u.negTokenResp.supportedMech = NULL; nt.u.negTokenResp.responseToken = NULL; nt.u.negTokenResp.mechListMIC = NULL; ASN1_MALLOC_ENCODE(NegotiationToken, output_token->value, output_token->length, &nt, &size, *minor_status); free_NegotiationToken(&nt); if (*minor_status != 0) return GSS_S_FAILURE; return GSS_S_BAD_MECH;}static OM_uint32acceptor_approved(gss_name_t target_name, gss_OID mech){ gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; gss_OID_set oidset; OM_uint32 junk, ret; if (target_name == GSS_C_NO_NAME) return GSS_S_COMPLETE; gss_create_empty_oid_set(&junk, &oidset); gss_add_oid_set_member(&junk, mech, &oidset); ret = gss_acquire_cred(&junk, target_name, GSS_C_INDEFINITE, oidset, GSS_C_ACCEPT, &cred, NULL, NULL); gss_release_oid_set(&junk, &oidset); if (ret != GSS_S_COMPLETE) return ret; gss_release_cred(&junk, &cred); return GSS_S_COMPLETE;}static OM_uint32send_supported_mechs (OM_uint32 *minor_status, gss_buffer_t output_token){ NegotiationTokenWin nt; char hostname[MAXHOSTNAMELEN + 1], *p; gss_buffer_desc name_buf; gss_OID name_type; gss_name_t target_princ; gss_name_t canon_princ; OM_uint32 minor; size_t buf_len; gss_buffer_desc data; OM_uint32 ret; memset(&nt, 0, sizeof(nt)); nt.element = choice_NegotiationTokenWin_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, acceptor_approved, 1, NULL, &nt.u.negTokenInit.mechTypes, NULL); if (ret != GSS_S_COMPLETE) { return ret; } memset(&target_princ, 0, sizeof(target_princ)); if (gethostname(hostname, sizeof(hostname) - 2) != 0) { *minor_status = errno; free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } hostname[sizeof(hostname) - 1] = '\0'; /* Send the constructed SAM name for this host */ for (p = hostname; *p != '\0' && *p != '.'; p++) { *p = toupper((unsigned char)*p); } *p++ = '$'; *p = '\0'; name_buf.length = strlen(hostname); name_buf.value = hostname; ret = gss_import_name(minor_status, &name_buf, GSS_C_NO_OID, &target_princ); if (ret != GSS_S_COMPLETE) { free_NegotiationTokenWin(&nt); return ret; } name_buf.length = 0; name_buf.value = NULL; /* Canonicalize the name using the preferred mechanism */ ret = gss_canonicalize_name(minor_status, target_princ, GSS_C_NO_OID, &canon_princ); if (ret != GSS_S_COMPLETE) { free_NegotiationTokenWin(&nt); gss_release_name(&minor, &target_princ); return ret; } ret = gss_display_name(minor_status, canon_princ, &name_buf, &name_type); if (ret != GSS_S_COMPLETE) { free_NegotiationTokenWin(&nt); gss_release_name(&minor, &canon_princ); gss_release_name(&minor, &target_princ); return ret; } gss_release_name(&minor, &canon_princ); gss_release_name(&minor, &target_princ); ALLOC(nt.u.negTokenInit.negHints, 1); if (nt.u.negTokenInit.negHints == NULL) { *minor_status = ENOMEM; gss_release_buffer(&minor, &name_buf); free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } ALLOC(nt.u.negTokenInit.negHints->hintName, 1); if (nt.u.negTokenInit.negHints->hintName == NULL) { *minor_status = ENOMEM; gss_release_buffer(&minor, &name_buf); free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } *(nt.u.negTokenInit.negHints->hintName) = name_buf.value; name_buf.value = NULL; nt.u.negTokenInit.negHints->hintAddress = NULL; ASN1_MALLOC_ENCODE(NegotiationTokenWin, data.value, data.length, &nt, &buf_len, ret); free_NegotiationTokenWin(&nt); if (ret) { return ret; } if (data.length != buf_len) abort(); 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_uint32send_accept (OM_uint32 *minor_status, gssspnego_ctx context_handle, gss_buffer_t mech_token, int initial_response, gss_buffer_t mech_buf, gss_buffer_t output_token){ NegotiationToken nt; OM_uint32 ret; gss_buffer_desc mech_mic_buf; size_t size; memset(&nt, 0, sizeof(nt)); nt.element = choice_NegotiationToken_negTokenResp; ALLOC(nt.u.negTokenResp.negResult, 1); if (nt.u.negTokenResp.negResult == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } if (context_handle->open) { if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0 && mech_buf != GSS_C_NO_BUFFER) *(nt.u.negTokenResp.negResult) = accept_incomplete; else *(nt.u.negTokenResp.negResult) = accept_completed; } else { if (initial_response && context_handle->require_mic) *(nt.u.negTokenResp.negResult) = request_mic; else *(nt.u.negTokenResp.negResult) = accept_incomplete; } if (initial_response) { ALLOC(nt.u.negTokenResp.supportedMech, 1); if (nt.u.negTokenResp.supportedMech == NULL) { free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } ret = der_get_oid(context_handle->preferred_mech_type->elements, context_handle->preferred_mech_type->length, nt.u.negTokenResp.supportedMech, NULL); if (ret) { free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } } 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) { 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; } 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) { ALLOC(nt.u.negTokenResp.mechListMIC, 1); if (nt.u.negTokenResp.mechListMIC == NULL) { gss_release_buffer(minor_status, &mech_mic_buf); free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } 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 { free_NegotiationToken(&nt); return ret; } } else nt.u.negTokenResp.mechListMIC = NULL; ASN1_MALLOC_ENCODE(NegotiationToken, output_token->value, output_token->length, &nt, &size, ret); if (ret) { free_NegotiationToken(&nt); *minor_status = ret; return GSS_S_FAILURE; } /* * 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.negResult) == accept_completed) ret = GSS_S_COMPLETE; else ret = GSS_S_CONTINUE_NEEDED; free_NegotiationToken(&nt); return ret;}static OM_uint32verify_mechlist_mic (OM_uint32 *minor_status, gssspnego_ctx context_handle, gss_buffer_t mech_buf, heim_octet_string *mechListMIC ){ OM_uint32 ret; gss_buffer_desc mic_buf; if (context_handle->verified_mic) { /* This doesn't make sense, we've already verified it? */ *minor_status = 0; return GSS_S_DUPLICATE_TOKEN; } if (mechListMIC == NULL) { *minor_status = 0; return GSS_S_DEFECTIVE_TOKEN; } mic_buf.length = mechListMIC->length; mic_buf.value = mechListMIC->data; ret = gss_verify_mic(minor_status, context_handle->negotiated_ctx_id, mech_buf, &mic_buf, NULL); if (ret != GSS_S_COMPLETE) ret = GSS_S_DEFECTIVE_TOKEN; return ret;}static OM_uint32select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p, gss_OID *mech_p){ char mechbuf[64]; size_t mech_len; gss_OID_desc oid; OM_uint32 ret, junk; ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, sizeof(mechbuf), mechType, &mech_len); if (ret) { return GSS_S_DEFECTIVE_TOKEN; } oid.length = mech_len; oid.elements = mechbuf + sizeof(mechbuf) - mech_len; if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) { return GSS_S_BAD_MECH; } *minor_status = 0; /* Translate broken MS Kebreros OID */ if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) { gssapi_mech_interface mech; mech = __gss_get_mechanism(&_gss_spnego_krb5_mechanism_oid_desc); if (mech == NULL) return GSS_S_BAD_MECH; ret = gss_duplicate_oid(minor_status, &_gss_spnego_mskrb_mechanism_oid_desc, mech_p); } else { gssapi_mech_interface mech; mech = __gss_get_mechanism(&oid); if (mech == NULL) return GSS_S_BAD_MECH; ret = gss_duplicate_oid(minor_status, &mech->gm_mech_oid, mech_p); } if (verify_p) { gss_name_t name = GSS_C_NO_NAME; gss_buffer_desc namebuf; char *str = NULL, *host, hostname[MAXHOSTNAMELEN]; host = getenv("GSSAPI_SPNEGO_NAME"); if (host == NULL || issuid()) { if (gethostname(hostname, sizeof(hostname)) != 0) { *minor_status = errno; return GSS_S_FAILURE; } asprintf(&str, "host@%s", hostname); host = str; } namebuf.length = strlen(host); namebuf.value = host; ret = gss_import_name(minor_status, &namebuf, GSS_C_NT_HOSTBASED_SERVICE, &name); if (str) free(str); if (ret != GSS_S_COMPLETE) return ret; ret = acceptor_approved(name, *mech_p); gss_release_name(&junk, &name); } return ret;}static OM_uint32acceptor_complete(OM_uint32 * minor_status, gssspnego_ctx ctx, int *get_mic, gss_buffer_t mech_buf, gss_buffer_t mech_input_token, gss_buffer_t mech_output_token, heim_octet_string *mic, gss_buffer_t output_token){ OM_uint32 ret; int require_mic, verify_mic; gss_buffer_desc buf; buf.length = 0; buf.value = NULL; ret = _gss_spnego_require_mechlist_mic(minor_status, ctx, &require_mic); if (ret) return ret; ctx->require_mic = require_mic; if (mic != NULL) require_mic = 1; if (ctx->open && require_mic) { 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; } if (verify_mic || get_mic) { int eret; size_t buf_len; ASN1_MALLOC_ENCODE(MechTypeList, mech_buf->value, mech_buf->length, &ctx->initiator_mech_types, &buf_len, eret); if (eret) { *minor_status = eret; return GSS_S_FAILURE; } if (buf.length != buf_len) abort(); } if (verify_mic) { ret = verify_mechlist_mic(minor_status, ctx, mech_buf, mic); if (ret) { if (get_mic) send_reject (minor_status, output_token); if (buf.value) free(buf.value); return ret; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -