📄 gss_shim.c
字号:
/* * Program: GSSAPI Kerberos Shim 5 for Windows 2000 IMAP Toolkit * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 6 March 2000 * Last Edited: 30 May 2000 * * Copyright 2000 by the University of Washington * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notices appear in all copies and that both the * above copyright notices and this permission notice appear in supporting * documentation, and that the name of the University of Washington not be * used in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. This software is made * available "as is", and * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *//* The purpose of this module is to be a shim, so that the auth_gss.c module * (written for MIT Kerberos) will compile, link, and run with SSPI Kerberos * on Windows 2000 systems. * There is no attempt whatsoever to make this be a complete implementation * of GSSAPI. A number of shortcuts were taken that a real GSSAPI * implementation for SSPI can't do. * Nor is there any attempt to make the types identical with MIT Kerberos; * you can't link this library with object files compiled with the MIT * Kerberos .h files. */#include "mail.h"#include "osdep.h"#include "misc.h"#include <stdio.h>#include <gssapi/gssapi_generic.h>#include <gssapi/gssapi_krb5.h>#define STRING WINSTRING /* conflict with mail.h */#include <NTSecAPI.h>/* GSSAPI build-in object identifiers */static gss_OID_desc oids[] = { /* stupid C language makes this necessary */ {10,"\052\206\110\206\367\022\001\002\001\004"}, {9,"\052\206\110\206\367\022\001\002\002"}}; /* stupid C language ditto */static gss_OID_set_desc oidsets[] = { {1,(gss_OID) oids+1}}; /* these are the real OIDs */const gss_OID gss_nt_service_name = oids+0;const gss_OID gss_mech_krb5 = oids+1;const gss_OID_set gss_mech_set_krb5 = oidsets+0;/* Other globals */ /* substitute for GSS_C_NO_CREDENTIAL */static gss_cred_id_t gss_default_cred = NIL;char *krb5_defkeyname = ""; /* needed for auth_gss keytab test *//* GSSAPI import name (convert to full service principal name) * Accepts: pointer to return minor status * buffer containining input name * type of input name * pointer to return output internal name * Returns: major status, always */OM_uint32 gss_import_name (OM_uint32 *minor_status, gss_buffer_t input_name_buffer, gss_OID input_name_type,gss_name_t *output_name){ OM_uint32 major_status = GSS_S_COMPLETE; TimeStamp expiry; static CredHandle gss_cred; char *s,tmp[MAILTMPLEN]; char *realm = getenv ("USERDOMAIN"); *minor_status = 0; /* never any minor status */ if (!gss_default_cred && /* default credentials set up yet? */ ((major_status = /* no, do so now */ AcquireCredentialsHandle (NIL,MICROSOFT_KERBEROS_NAME_A, SECPKG_CRED_OUTBOUND,NIL,NIL,NIL,NIL, &gss_cred,&expiry)) == SEC_E_OK)) gss_default_cred = &gss_cred; /* AcquireCredentialsHandle failed */ if (major_status != GSS_S_COMPLETE); /* can't do it if no realm */ else if (!realm || !*realm) major_status = GSS_S_FAILURE; /* must be the gss_nt_service_name format */ else if (input_name_type != gss_nt_service_name) major_status = GSS_S_BAD_NAMETYPE; /* name must be of sane length */ else if (input_name_buffer->length > (MAILTMPLEN/2)) major_status = GSS_S_BAD_NAME; else { /* copy name */ strncpy (tmp,input_name_buffer->value,input_name_buffer->length); tmp[input_name_buffer->length] = '\0'; /* find service/host/delimiter */ if (!(s = strchr (tmp,'@'))) major_status = GSS_S_BAD_NAME; else { *s = '/'; /* convert to full service principal name */ s = tmp + strlen (tmp); /* prepare to append */ *s++ = '@'; /* delimiter */ strcpy (s,realm); /* append realm */ *output_name = cpystr (tmp);/* and write the name */ } } return major_status;}/* GSSAPI Initialize security context * Accepts: pointer to return minor status * claimant credential handle * context (NIL means "none assigned yet") * desired principal * desired mechanisms * required context attributes * desired lifetime * input channel bindings * input token buffer * pointer to return mechanism type * buffer to return output token * pointer to return flags * pointer to return context lifetime * Returns: GSS_S_FAILURE, always */OM_uint32 gss_init_sec_context (OM_uint32 *minor_status, gss_cred_id_t claimant_cred_handle, gss_ctx_id_t *context_handle, gss_name_t target_name,gss_OID mech_type, OM_uint32 req_flags,OM_uint32 time_req, gss_channel_bindings_t input_chan_bindings, 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 i; OM_uint32 major_status; TimeStamp expiry; SecBuffer ibuf[1],obuf[1]; SecBufferDesc ibufs,obufs; *minor_status = 0; /* never any minor status */ /* error if non-default time requested */ if (time_req) return GSS_S_FAILURE; if (mech_type && memcmp (mech_type,gss_mech_krb5,sizeof (gss_OID))) return GSS_S_BAD_MECH; /* ditto if any channel bindings */ if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) return GSS_S_BAD_BINDINGS; /* apply default credential if necessary */ if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) claimant_cred_handle = gss_default_cred; /* create output buffer storage as needed */ req_flags |= ISC_REQ_ALLOCATE_MEMORY; /* make output buffer */ obuf[0].BufferType = SECBUFFER_TOKEN; obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL; /* output buffer descriptor */ obufs.ulVersion = SECBUFFER_VERSION; obufs.cBuffers = 1; obufs.pBuffers = obuf; /* first time caller? */ if (*context_handle == GSS_C_NO_CONTEXT) { /* yes, set up output context handle */ PCtxtHandle ctx = (PCtxtHandle) fs_get (sizeof (CtxtHandle)); major_status = InitializeSecurityContext (claimant_cred_handle,NIL, target_name,req_flags,0, SECURITY_NETWORK_DREP,NIL,0,ctx, &obufs, ret_flags ? ret_flags : &i, &expiry); *context_handle = ctx; /* return updated context */ } else { /* no, make SSPI buffer from GSSAPI buffer */ ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN; ibuf[0].cbBuffer = input_token->length; ibuf[0].pvBuffer = input_token->value; /* input buffer descriptor */ ibufs.ulVersion = SECBUFFER_VERSION; ibufs.cBuffers = 1; ibufs.pBuffers = ibuf; major_status = InitializeSecurityContext (claimant_cred_handle, *context_handle,target_name, req_flags,0, SECURITY_NETWORK_DREP,&ibufs,0, *context_handle,&obufs, ret_flags ? ret_flags : &i, &expiry); } /* return output */ output_token->value = obuf[0].pvBuffer; output_token->length = obuf[0].cbBuffer; /* in case client wanted lifetime returned */ if (time_rec) *time_rec = expiry.LowPart; return major_status;}/* GSSAPI display status text * Accepts: pointer to return minor status * status to display * status type * message context for continuation * buffer to write status string * Returns: major status, always */OM_uint32 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){ char *s,tmp[MAILTMPLEN]; *minor_status = 0; /* never any minor status */ if (*message_context) return GSS_S_FAILURE; switch (status_type) { /* what type of status code? */ case GSS_C_GSS_CODE: /* major_status */ switch (status_value) { /* analyze status value */ case GSS_S_FAILURE: s = "Unspecified failure"; break; case GSS_S_CREDENTIALS_EXPIRED: s = "Credentials expired"; break; case GSS_S_BAD_BINDINGS: s = "Bad bindings"; break; case GSS_S_BAD_MECH: s = "Bad mechanism type"; break; case GSS_S_BAD_NAME: s = "Bad name"; break; case GSS_S_BAD_NAMETYPE: s = "Bad name type"; break; case GSS_S_BAD_QOP: s = "Bad quality of protection"; break; case GSS_S_BAD_STATUS: s = "Bad status"; break; case GSS_S_NO_CONTEXT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -