imapext-2007

diff src/osdep/nt/kerb_w2k.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/osdep/nt/kerb_w2k.c	Mon Sep 14 15:17:45 2009 +0900
     1.3 @@ -0,0 +1,699 @@
     1.4 +/* ========================================================================
     1.5 + * Copyright 1988-2006 University of Washington
     1.6 + *
     1.7 + * Licensed under the Apache License, Version 2.0 (the "License");
     1.8 + * you may not use this file except in compliance with the License.
     1.9 + * You may obtain a copy of the License at
    1.10 + *
    1.11 + *     http://www.apache.org/licenses/LICENSE-2.0
    1.12 + *
    1.13 + * 
    1.14 + * ========================================================================
    1.15 + */
    1.16 +
    1.17 +/*
    1.18 + * Program:	GSSAPI Kerberos Shim 5 for Windows 2000/XP IMAP Toolkit
    1.19 + *
    1.20 + * Author:	Mark Crispin
    1.21 + *		Networks and Distributed Computing
    1.22 + *		Computing & Communications
    1.23 + *		University of Washington
    1.24 + *		Administration Building, AG-44
    1.25 + *		Seattle, WA  98195
    1.26 + *		Internet: MRC@CAC.Washington.EDU
    1.27 + *
    1.28 + * Date:	6 March 2000
    1.29 + * Last Edited:	30 August 2006
    1.30 + */
    1.31 +
    1.32 +/*  The purpose of this module is to be a shim, so that the auth_gss.c module
    1.33 + * (written for MIT Kerberos) will compile, link, and run with SSPI Kerberos
    1.34 + * on Windows 2000 systems.
    1.35 + *  There is no attempt whatsoever to make this be a complete implementation
    1.36 + * of GSSAPI.  A number of shortcuts were taken that a real GSSAPI
    1.37 + * implementation for SSPI can't do.
    1.38 + *  Nor is there any attempt to make the types identical with MIT Kerberos;
    1.39 + * you can't link this library with object files compiled with the MIT
    1.40 + * Kerberos .h files.
    1.41 + */
    1.42 +
    1.43 +
    1.44 +/* GSSAPI generic definitions */
    1.45 +
    1.46 +
    1.47 +#define SECURITY_WIN32
    1.48 +#include <security.h>
    1.49 +
    1.50 +
    1.51 +/* GSSAPI types for which we use SSPI equivalent types */
    1.52 +
    1.53 +typedef ULONG OM_uint32;
    1.54 +typedef PCredHandle gss_cred_id_t;
    1.55 +typedef ULONG gss_cred_usage_t;
    1.56 +typedef PCtxtHandle gss_ctx_id_t;
    1.57 +typedef SEC_CHAR * gss_name_t;
    1.58 +typedef ULONG gss_qop_t;
    1.59 +
    1.60 +
    1.61 +/* Major status codes */
    1.62 +
    1.63 +#define GSS_S_COMPLETE SEC_E_OK
    1.64 +#define GSS_S_BAD_MECH SEC_E_SECPKG_NOT_FOUND
    1.65 +#define GSS_S_CONTINUE_NEEDED SEC_I_CONTINUE_NEEDED
    1.66 +#define GSS_S_CREDENTIALS_EXPIRED SEC_E_CERT_EXPIRED
    1.67 +#define GSS_S_FAILURE SEC_E_INTERNAL_ERROR
    1.68 +#define GSS_S_NO_CRED SEC_E_NO_CREDENTIALS
    1.69 +#define GSS_S_NO_CONTEXT SEC_E_INVALID_HANDLE
    1.70 +
    1.71 +
    1.72 +/* Flag bits for context-level services */
    1.73 +
    1.74 +#define GSS_C_DELEG_FLAG ISC_REQ_DELEGATE
    1.75 +#define GSS_C_MUTUAL_FLAG ISC_REQ_MUTUAL_AUTH
    1.76 +#define GSS_C_REPLAY_FLAG ISC_REQ_REPLAY_DETECT
    1.77 +#define GSS_C_SEQUENCE_FLAG ISC_REQ_SEQUENCE_DETECT
    1.78 +#define GSS_C_CONF_FLAG ISC_REQ_CONFIDENTIALITY
    1.79 +#define GSS_C_INTEG_FLAG ISC_REQ_INTEGRITY
    1.80 +
    1.81 +
    1.82 +/* Credential usage options */
    1.83 +
    1.84 +#define GSS_C_BOTH SECPKG_CRED_BOTH
    1.85 +#define GSS_C_INITIATE SECPKG_CRED_OUTBOUND
    1.86 +#define GSS_C_ACCEPT SECPKG_CRED_INBOUND
    1.87 +
    1.88 +
    1.89 +/* Major status codes defined by shim */
    1.90 +
    1.91 +#define GSS_S_BAD_BINDINGS 100
    1.92 +#define GSS_S_BAD_NAME 101
    1.93 +#define GSS_S_BAD_NAMETYPE 102
    1.94 +#define GSS_S_BAD_STATUS 103
    1.95 +
    1.96 +/* GSSAPI types as used in GSSAPI */
    1.97 +
    1.98 +
    1.99 +/* Buffer */
   1.100 +
   1.101 +typedef struct gss_buffer_desc_struct {
   1.102 +  size_t length;
   1.103 +  void *value;
   1.104 +} gss_buffer_desc,*gss_buffer_t;
   1.105 +
   1.106 +
   1.107 +/* Object identifier */
   1.108 +
   1.109 +typedef struct gss_OID_desc_struct {
   1.110 +  OM_uint32 length;
   1.111 +  void *elements;
   1.112 +} gss_OID_desc,*gss_OID;
   1.113 +
   1.114 +typedef struct gss_OID_set_desc_struct {
   1.115 +  size_t count;
   1.116 +  gss_OID elements;
   1.117 +} gss_OID_set_desc,*gss_OID_set;
   1.118 +
   1.119 +
   1.120 +/* Unused, but needed in prototypes */
   1.121 +
   1.122 +typedef void * gss_channel_bindings_t;
   1.123 +
   1.124 +
   1.125 +/* Default constants */
   1.126 +
   1.127 +#define GSS_C_EMPTY_BUFFER {0,NIL}
   1.128 +#define GSS_C_NO_BUFFER ((gss_buffer_t) NIL)
   1.129 +#define GSS_C_NO_OID ((gss_OID) NIL)
   1.130 +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) NIL)
   1.131 +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) NIL)
   1.132 +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) NIL)
   1.133 +#define GSS_C_QOP_DEFAULT NIL
   1.134 +
   1.135 +
   1.136 +/* Status code types for gss_display_status */
   1.137 +
   1.138 +#define GSS_C_GSS_CODE 1
   1.139 +#define GSS_C_MECH_CODE 2
   1.140 +
   1.141 +
   1.142 +/* GSSAPI constants */
   1.143 +
   1.144 +const gss_OID gss_nt_service_name;
   1.145 +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
   1.146 +const gss_OID gss_mech_krb5;
   1.147 +const gss_OID_set gss_mech_set_krb5;
   1.148 +
   1.149 +/* GSSAPI prototypes */
   1.150 +
   1.151 +
   1.152 +OM_uint32 gss_accept_sec_context (OM_uint32 *minor_status,
   1.153 +				  gss_ctx_id_t *context_handle,
   1.154 +				  gss_cred_id_t acceptor_cred_handle,
   1.155 +				  gss_buffer_t input_token_buffer,
   1.156 +				  gss_channel_bindings_t input_chan_bindings,
   1.157 +				  gss_name_t *src_name,gss_OID *mech_type,
   1.158 +				  gss_buffer_t output_token,
   1.159 +				  OM_uint32 *ret_flags,OM_uint32 *time_rec,
   1.160 +				  gss_cred_id_t *delegated_cred_handle);
   1.161 +OM_uint32 gss_acquire_cred (OM_uint32 *minor_status,gss_name_t desired_name,
   1.162 +			    OM_uint32 time_req,gss_OID_set desired_mechs,
   1.163 +			    gss_cred_usage_t cred_usage,
   1.164 +			    gss_cred_id_t *output_cred_handle,
   1.165 +			    gss_OID_set *actual_mechs,OM_uint32 *time_rec);
   1.166 +OM_uint32 gss_delete_sec_context (OM_uint32 *minor_status,
   1.167 +				  gss_ctx_id_t *context_handle,
   1.168 +				  gss_buffer_t output_token);
   1.169 +OM_uint32 gss_display_name (OM_uint32 *minor_status,gss_name_t input_name,
   1.170 +			    gss_buffer_t output_name_buffer,
   1.171 +			    gss_OID *output_name_type);
   1.172 +OM_uint32 gss_display_status (OM_uint32 *minor_status,OM_uint32 status_value,
   1.173 +			      int status_type,gss_OID mech_type,
   1.174 +			      OM_uint32 *message_context,
   1.175 +			      gss_buffer_t status_string);
   1.176 +OM_uint32 gss_import_name (OM_uint32 *minor_status,
   1.177 +			   gss_buffer_t input_name_buffer,
   1.178 +			   gss_OID input_name_type,gss_name_t *output_name);
   1.179 +OM_uint32 gss_init_sec_context (OM_uint32 *minor_status,
   1.180 +				gss_cred_id_t claimant_cred_handle,
   1.181 +				gss_ctx_id_t *context_handle,
   1.182 +				gss_name_t target_name,gss_OID mech_type,
   1.183 +				OM_uint32 req_flags,OM_uint32 time_req,
   1.184 +				gss_channel_bindings_t input_chan_bindings,
   1.185 +				gss_buffer_t input_token,
   1.186 +				gss_OID *actual_mech_type,
   1.187 +				gss_buffer_t output_token,OM_uint32 *ret_flags,
   1.188 +				OM_uint32 *time_rec);
   1.189 +OM_uint32 gss_release_buffer (OM_uint32 *minor_status,gss_buffer_t buffer);
   1.190 +OM_uint32 gss_release_cred (OM_uint32 *minor_status,gss_cred_id_t *cred_handle);
   1.191 +OM_uint32 gss_release_name (OM_uint32 *minor_status,gss_name_t *input_name);
   1.192 +OM_uint32 gss_wrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
   1.193 +		    int conf_req_flag,gss_qop_t qop_req,
   1.194 +		    gss_buffer_t input_message_buffer,int *conf_state,
   1.195 +		    gss_buffer_t output_message_buffer);
   1.196 +OM_uint32 gss_unwrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
   1.197 +		      gss_buffer_t input_message_buffer,
   1.198 +		      gss_buffer_t output_message_buffer,int *conf_state,
   1.199 +		      gss_qop_t *qop_state);
   1.200 +
   1.201 +/* Kerberos definitions */
   1.202 +
   1.203 +long kerberos_server_valid (void);
   1.204 +long kerberos_try_kinit (OM_uint32 error);
   1.205 +char *kerberos_login (char *user,char *authuser,int argc,char *argv[]);
   1.206 +
   1.207 +
   1.208 +#define STRING WINSTRING	/* conflict with mail.h */
   1.209 +#include <NTSecAPI.h>
   1.210 +
   1.211 +/* GSSAPI build-in object identifiers */
   1.212 +
   1.213 +static gss_OID_desc oids[] = {	/* stupid C language makes this necessary */
   1.214 +  {10,"\052\206\110\206\367\022\001\002\001\004"},
   1.215 +  {9,"\052\206\110\206\367\022\001\002\002"}
   1.216 +};
   1.217 +
   1.218 +				/* stupid C language ditto */
   1.219 +static gss_OID_set_desc oidsets[] = {
   1.220 +  {1,(gss_OID) oids+1}
   1.221 +};
   1.222 +
   1.223 +				/* these are the real OIDs */
   1.224 +const gss_OID gss_nt_service_name = oids+0;
   1.225 +const gss_OID gss_mech_krb5 = oids+1;
   1.226 +const gss_OID_set gss_mech_set_krb5 = oidsets+0;
   1.227 +
   1.228 +
   1.229 +/* Other globals */
   1.230 +
   1.231 +				/* substitute for GSS_C_NO_CREDENTIAL */
   1.232 +static gss_cred_id_t gss_default_cred = NIL;
   1.233 +
   1.234 +/* GSSAPI import name (convert to full service principal name)
   1.235 + * Accepts: pointer to return minor status
   1.236 + *	    buffer containining input name
   1.237 + *	    type of input name
   1.238 + *	    pointer to return output internal name
   1.239 + * Returns: major status, always
   1.240 + */
   1.241 +
   1.242 +OM_uint32 gss_import_name (OM_uint32 *minor_status,
   1.243 +			   gss_buffer_t input_name_buffer,
   1.244 +			   gss_OID input_name_type,gss_name_t *output_name)
   1.245 +{
   1.246 +  OM_uint32 major_status = GSS_S_COMPLETE;
   1.247 +  TimeStamp expiry;
   1.248 +  static CredHandle gss_cred;
   1.249 +  char *s,tmp[MAILTMPLEN];
   1.250 +  *minor_status = 0;		/* never any minor status */
   1.251 +  if (!gss_default_cred) {	/* default credentials set up yet? */
   1.252 +    if (AcquireCredentialsHandle/* no, acquire them now */
   1.253 +	(NIL,MICROSOFT_KERBEROS_NAME_A,SECPKG_CRED_OUTBOUND,NIL,NIL,NIL,NIL,
   1.254 +	 &gss_cred,&expiry) != SEC_E_OK) return GSS_S_FAILURE;
   1.255 +				/* have default credentials now */
   1.256 +    gss_default_cred = &gss_cred;
   1.257 +  }
   1.258 +				/* must be the gss_nt_service_name format */
   1.259 +  if (input_name_type != gss_nt_service_name)
   1.260 +    major_status = GSS_S_BAD_NAMETYPE;
   1.261 +				/* name must be of sane length */
   1.262 +  else if (input_name_buffer->length > (MAILTMPLEN/2))
   1.263 +    major_status = GSS_S_BAD_NAME;
   1.264 +  else {			/* copy name */
   1.265 +    memcpy (tmp,input_name_buffer->value,input_name_buffer->length);
   1.266 +    tmp[input_name_buffer->length] = '\0';
   1.267 +    if (s = strchr (tmp,'@')) {	/* find service/host/delimiter */
   1.268 +      *s = '/';			/* convert to full service principal name */
   1.269 +      *output_name = cpystr (tmp);
   1.270 +    }
   1.271 +    else major_status = GSS_S_BAD_NAME;
   1.272 +  }
   1.273 +  return major_status;
   1.274 +}
   1.275 +
   1.276 +/* GSSAPI Initialize security context
   1.277 + * Accepts: pointer to return minor status
   1.278 + *	    claimant credential handle
   1.279 + *	    context (NIL means "none assigned yet")
   1.280 + *	    desired principal
   1.281 + *	    desired mechanisms
   1.282 + *	    required context attributes
   1.283 + *	    desired lifetime
   1.284 + *	    input channel bindings
   1.285 + *	    input token buffer
   1.286 + *	    pointer to return mechanism type
   1.287 + *	    buffer to return output token
   1.288 + *	    pointer to return flags
   1.289 + *	    pointer to return context lifetime
   1.290 + * Returns: major status, always
   1.291 + */
   1.292 +
   1.293 +OM_uint32 gss_init_sec_context (OM_uint32 *minor_status,
   1.294 +				gss_cred_id_t claimant_cred_handle,
   1.295 +				gss_ctx_id_t *context_handle,
   1.296 +				gss_name_t target_name,gss_OID mech_type,
   1.297 +				OM_uint32 req_flags,OM_uint32 time_req,
   1.298 +				gss_channel_bindings_t input_chan_bindings,
   1.299 +				gss_buffer_t input_token,
   1.300 +				gss_OID *actual_mech_type,
   1.301 +				gss_buffer_t output_token,OM_uint32 *ret_flags,
   1.302 +				OM_uint32 *time_rec)
   1.303 +{
   1.304 +  OM_uint32 i;
   1.305 +  OM_uint32 major_status;
   1.306 +  TimeStamp expiry;
   1.307 +  SecBuffer ibuf[1],obuf[1];
   1.308 +  SecBufferDesc ibufs,obufs;
   1.309 +  *minor_status = 0;		/* never any minor status */
   1.310 +				/* error if non-default time requested */
   1.311 +  if (time_req) return GSS_S_FAILURE;
   1.312 +  if (mech_type && memcmp (mech_type,gss_mech_krb5,sizeof (gss_OID)))
   1.313 +    return GSS_S_BAD_MECH;
   1.314 +				/* ditto if any channel bindings */
   1.315 +  if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS)
   1.316 +    return GSS_S_BAD_BINDINGS;
   1.317 +
   1.318 +				/* apply default credential if necessary */
   1.319 +  if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
   1.320 +    claimant_cred_handle = gss_default_cred;
   1.321 +				/* create output buffer storage as needed */
   1.322 +  req_flags |= ISC_REQ_ALLOCATE_MEMORY;
   1.323 +				/* make output buffer */
   1.324 +  obuf[0].BufferType = SECBUFFER_TOKEN;
   1.325 +  obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL;
   1.326 +				/* output buffer descriptor */
   1.327 +  obufs.ulVersion = SECBUFFER_VERSION;
   1.328 +  obufs.cBuffers = 1;
   1.329 +  obufs.pBuffers = obuf;
   1.330 +				/* first time caller? */
   1.331 +  if (*context_handle == GSS_C_NO_CONTEXT) {
   1.332 +				/* yes, set up output context handle */
   1.333 +    PCtxtHandle ctx = (PCtxtHandle) fs_get (sizeof (CtxtHandle));
   1.334 +    major_status = InitializeSecurityContext (claimant_cred_handle,NIL,
   1.335 +					      target_name,req_flags,0,
   1.336 +					      SECURITY_NETWORK_DREP,NIL,0,ctx,
   1.337 +					      &obufs,
   1.338 +					      ret_flags ? ret_flags : &i,
   1.339 +					      &expiry);
   1.340 +    *context_handle = ctx;	/* return updated context */
   1.341 +  }
   1.342 +  else {			/* no, make SSPI buffer from GSSAPI buffer */
   1.343 +    ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
   1.344 +    ibuf[0].cbBuffer = input_token->length;
   1.345 +    ibuf[0].pvBuffer = input_token->value;
   1.346 +				/* input buffer descriptor */
   1.347 +    ibufs.ulVersion = SECBUFFER_VERSION;
   1.348 +    ibufs.cBuffers = 1;
   1.349 +    ibufs.pBuffers = ibuf;
   1.350 +    major_status = InitializeSecurityContext (claimant_cred_handle,
   1.351 +					      *context_handle,target_name,
   1.352 +					      req_flags,0,
   1.353 +					      SECURITY_NETWORK_DREP,&ibufs,0,
   1.354 +					      *context_handle,&obufs,
   1.355 +					      ret_flags ? ret_flags : &i,
   1.356 +					      &expiry);
   1.357 +  }
   1.358 +				/* return output */
   1.359 +  output_token->value = obuf[0].pvBuffer;
   1.360 +  output_token->length = obuf[0].cbBuffer;
   1.361 +				/* in case client wanted lifetime returned */
   1.362 +  if (time_rec) *time_rec = expiry.LowPart;
   1.363 +  return major_status;
   1.364 +}
   1.365 +
   1.366 +/* GSSAPI display status text
   1.367 + * Accepts: pointer to return minor status
   1.368 + *	    status to display
   1.369 + *	    status type
   1.370 + *	    message context for continuation
   1.371 + *	    buffer to write status string
   1.372 + * Returns: major status, always
   1.373 + */
   1.374 +
   1.375 +OM_uint32 gss_display_status (OM_uint32 *minor_status,OM_uint32 status_value,
   1.376 +			      int status_type,gss_OID mech_type,
   1.377 +			      OM_uint32 *message_context,
   1.378 +			      gss_buffer_t status_string)
   1.379 +{
   1.380 +  char *s,tmp[MAILTMPLEN];
   1.381 +  *minor_status = 0;		/* never any minor status */
   1.382 +  if (*message_context) return GSS_S_FAILURE;
   1.383 +  switch (status_type) {	/* what type of status code? */
   1.384 +  case GSS_C_GSS_CODE:		/* major_status */
   1.385 +    switch (status_value) {	/* analyze status value */
   1.386 +    case GSS_S_FAILURE:
   1.387 +      s = "Unspecified failure"; break;
   1.388 +    case GSS_S_CREDENTIALS_EXPIRED:
   1.389 +      s = "Credentials expired"; break;
   1.390 +    case GSS_S_BAD_BINDINGS:
   1.391 +      s = "Bad bindings"; break;
   1.392 +    case GSS_S_BAD_MECH:
   1.393 +      s = "Bad mechanism type"; break;
   1.394 +    case GSS_S_BAD_NAME:
   1.395 +      s = "Bad name"; break;
   1.396 +    case GSS_S_BAD_NAMETYPE:
   1.397 +      s = "Bad name type"; break;
   1.398 +    case GSS_S_BAD_STATUS:
   1.399 +      s = "Bad status"; break;
   1.400 +    case GSS_S_NO_CONTEXT:
   1.401 +      s = "Invalid context handle"; break;
   1.402 +    case GSS_S_NO_CRED:
   1.403 +      s = "Unable to authenticate to Kerberos service";
   1.404 +      mail_parameters (NIL,DISABLE_AUTHENTICATOR,"GSSAPI");
   1.405 +      break;
   1.406 +    case SEC_E_NO_AUTHENTICATING_AUTHORITY:
   1.407 +      s = "No authenticating authority"; break;
   1.408 +    case SEC_E_TARGET_UNKNOWN:
   1.409 +      s = "Destination server unknown to Kerberos service"; break;
   1.410 +    default:
   1.411 +      sprintf (s = tmp,"SSPI code %lx",status_value);
   1.412 +    }
   1.413 +    break;
   1.414 +  case GSS_C_MECH_CODE:		/* minor status - drop into default */
   1.415 +  default:
   1.416 +    return GSS_S_BAD_STATUS;	/* bad status type */
   1.417 +  }
   1.418 +				/* return status string */
   1.419 +  status_string->length = strlen (status_string->value = cpystr (s));
   1.420 +  return GSS_S_COMPLETE;
   1.421 +}
   1.422 +
   1.423 +/* GSSAPI delete security context
   1.424 + * Accepts: pointer to return minor status
   1.425 + *	    context to delete
   1.426 + *	    output context token
   1.427 + * Returns: major status, always
   1.428 + */
   1.429 +
   1.430 +OM_uint32 gss_delete_sec_context (OM_uint32 *minor_status,
   1.431 +				  gss_ctx_id_t *context_handle,
   1.432 +				  gss_buffer_t output_token)
   1.433 +{
   1.434 +  OM_uint32 major_status;
   1.435 +  *minor_status = 0;		/* never any minor status */
   1.436 +				/* output token not supported */
   1.437 +  major_status = output_token ? GSS_S_FAILURE :
   1.438 +    DeleteSecurityContext (*context_handle);
   1.439 +  fs_give ((void **) context_handle);
   1.440 +  return major_status;
   1.441 +}
   1.442 +
   1.443 +
   1.444 +/* GSSAPI release buffer
   1.445 + * Accepts: pointer to return minor status
   1.446 + *	    buffer to release
   1.447 + * Returns: GSS_S_COMPLETE, always
   1.448 + */
   1.449 +
   1.450 +OM_uint32 gss_release_buffer (OM_uint32 *minor_status,gss_buffer_t buffer)
   1.451 +{
   1.452 +  *minor_status = 0;		/* never any minor status */
   1.453 +  fs_give (&buffer->value);
   1.454 +  return GSS_S_COMPLETE;
   1.455 +}
   1.456 +
   1.457 +
   1.458 +/* GSSAPI release name
   1.459 + * Accepts: pointer to return minor status
   1.460 + *	    pointer to name to release
   1.461 + * Returns: GSS_S_COMPLETE, always
   1.462 + */
   1.463 +
   1.464 +OM_uint32 gss_release_name (OM_uint32 *minor_status,gss_name_t *input_name)
   1.465 +{
   1.466 +  *minor_status = 0;		/* never any minor status */
   1.467 +  fs_give (input_name);
   1.468 +  return GSS_S_COMPLETE;
   1.469 +}
   1.470 +
   1.471 +/* GSSAPI wrap data
   1.472 + * Accepts: pointer to return minor status
   1.473 + *	    context handle
   1.474 + *	    requested confidentiality
   1.475 + *	    requested quality of protection
   1.476 + *	    input message buffer
   1.477 + *	    pointer to return confidentiality state
   1.478 + *	    output message buffer
   1.479 + * Returns: major status, always
   1.480 + */
   1.481 +
   1.482 +OM_uint32 gss_wrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
   1.483 +		    int conf_req_flag,gss_qop_t qop_req,
   1.484 +		    gss_buffer_t input_message_buffer,int *conf_state,
   1.485 +		    gss_buffer_t output_message_buffer)
   1.486 +{
   1.487 +  OM_uint32 major_status;
   1.488 +  SecBuffer buf[3];
   1.489 +  SecBufferDesc bufs;
   1.490 +  SecPkgContext_Sizes sizes;
   1.491 +  *minor_status = NIL;		/* never any minor status */
   1.492 +  *conf_state = conf_req_flag;	/* same as requested */
   1.493 +  if ((major_status =		/* get trailer and padding sizes */
   1.494 +       QueryContextAttributes (context_handle,SECPKG_ATTR_SIZES,&sizes)) ==
   1.495 +      SEC_E_OK) {
   1.496 +				/* create big enough output buffer */
   1.497 +    output_message_buffer->value =
   1.498 +      fs_get (sizes.cbSecurityTrailer + input_message_buffer->length +
   1.499 +	      sizes.cbBlockSize);
   1.500 +    /* MSDN claims that for EncryptMessage() in Kerberos, you need an
   1.501 +     * uninitialized SECBUFFER_STREAM_HEADER; a SECBUFFER_DATA that "contains
   1.502 +     * the message to be encrypted.  The message is encrypted in place,
   1.503 +     * overwriting the original contents of its buffer"; an uninitialized
   1.504 +     * SECBUFFER_STREAM_TRAILER, and an uninitialized SECBUFFER_EMPTY.  I've
   1.505 +     * never been able to get it to work that way.
   1.506 +     */
   1.507 +    bufs.cBuffers = 3;		/* set up buffer descriptor */
   1.508 +    bufs.pBuffers = buf;
   1.509 +    bufs.ulVersion = SECBUFFER_VERSION;
   1.510 +    buf[0].BufferType = SECBUFFER_TOKEN;
   1.511 +    buf[0].pvBuffer = output_message_buffer->value;
   1.512 +    buf[0].cbBuffer = sizes.cbSecurityTrailer;
   1.513 +				/* I/O buffer */
   1.514 +    buf[1].BufferType = SECBUFFER_DATA;
   1.515 +    buf[1].pvBuffer = ((char *) buf[0].pvBuffer) + buf[0].cbBuffer;
   1.516 +    buf[1].cbBuffer = input_message_buffer->length;
   1.517 +    memcpy (buf[1].pvBuffer,input_message_buffer->value,buf[1].cbBuffer);
   1.518 +    buf[2].BufferType = SECBUFFER_PADDING;
   1.519 +    buf[2].pvBuffer = ((char *) buf[1].pvBuffer) + buf[1].cbBuffer;
   1.520 +    buf[2].cbBuffer = sizes.cbBlockSize;
   1.521 +    if ((major_status = EncryptMessage (context_handle,qop_req,&bufs,0)) ==
   1.522 +	GSS_S_COMPLETE) {
   1.523 +				/* slide data as necessary (how annoying!) */
   1.524 +      unsigned long i = sizes.cbSecurityTrailer - buf[0].cbBuffer;
   1.525 +      if (i) buf[1].pvBuffer =
   1.526 +	       memmove (((char *) buf[0].pvBuffer) + buf[0].cbBuffer,
   1.527 +			buf[1].pvBuffer,buf[1].cbBuffer);
   1.528 +      if (i += (input_message_buffer->length - buf[1].cbBuffer))
   1.529 +	buf[1].pvBuffer = memmove (((char *)buf[1].pvBuffer) + buf[1].cbBuffer,
   1.530 +		   buf[2].pvBuffer,buf[2].cbBuffer);
   1.531 +      output_message_buffer->length = buf[0].cbBuffer + buf[1].cbBuffer +
   1.532 +	buf[2].cbBuffer;
   1.533 +    }
   1.534 +    else fs_give (&output_message_buffer->value);
   1.535 +  }
   1.536 +  return major_status;		/* return status */
   1.537 +}
   1.538 +
   1.539 +/* GSSAPI unwrap data
   1.540 + * Accepts: pointer to return minor status
   1.541 + *	    context handle
   1.542 + *	    input message buffer
   1.543 + *	    output message buffer
   1.544 + *	    pointer to return confidentiality state
   1.545 + *	    pointer to return quality of protection
   1.546 + * Returns: major status, always
   1.547 + */
   1.548 +
   1.549 +OM_uint32 gss_unwrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
   1.550 +		      gss_buffer_t input_message_buffer,
   1.551 +		      gss_buffer_t output_message_buffer,int *conf_state,
   1.552 +		      gss_qop_t *qop_state)
   1.553 +{
   1.554 +  OM_uint32 major_status;
   1.555 +  SecBuffer buf[2];
   1.556 +  SecBufferDesc bufs;
   1.557 +  *minor_status = NIL;		/* never any minor status */
   1.558 +  *conf_state = NIL;		/* or confidentiality state */
   1.559 +  /* MSDN implies that all that is needed for DecryptMessage() in Kerberos
   1.560 +   * is a single SECBUFFER_DATA which "contains the encrypted message.  The
   1.561 +   * encrypted message is decrypted in place, overwriting the original
   1.562 +   * contents of its buffer."  I've never been able to get it to work without
   1.563 +   * using a SECBUFFER_STREAM for input and an uninitialized SECBUFFER_DATA
   1.564 +   * for output.
   1.565 +   * It *does* overwrite the input buffer, but not at the same point; e.g.
   1.566 +   * with an input pointer of 0xa140a8 and size of 53, the output ends up
   1.567 +   * at 0xa140d5 and size of 4.
   1.568 +   */
   1.569 +  bufs.cBuffers = 2;		/* set up buffer descriptor */
   1.570 +  bufs.pBuffers = buf;
   1.571 +  bufs.ulVersion = SECBUFFER_VERSION;
   1.572 +				/* input buffer */
   1.573 +  buf[0].BufferType = SECBUFFER_STREAM;
   1.574 +  buf[0].pvBuffer = input_message_buffer->value;
   1.575 +  buf[0].cbBuffer = input_message_buffer->length;
   1.576 +				/* output buffer */
   1.577 +  buf[1].BufferType = SECBUFFER_DATA;
   1.578 +  buf[1].pvBuffer = NIL;
   1.579 +  buf[1].cbBuffer = 0;
   1.580 +				/* decrypt and copy to output buffer */
   1.581 +  if ((major_status = DecryptMessage (context_handle,&bufs,0,qop_state)) ==
   1.582 +      SEC_E_OK)
   1.583 +   memcpy (output_message_buffer->value = fs_get (buf[1].cbBuffer),
   1.584 +	   buf[1].pvBuffer,output_message_buffer->length = buf[1].cbBuffer);
   1.585 +  return major_status;		/* return status */
   1.586 +}
   1.587 +
   1.588 +/* From here on are server-only functions, currently unused */
   1.589 +
   1.590 +
   1.591 +/* GSSAPI acquire credentials
   1.592 + * Accepts: pointer to return minor status
   1.593 + *	    desired principal
   1.594 + *	    desired lifetime
   1.595 + *	    desired mechanisms
   1.596 + *	    credentials usage
   1.597 + *	    pointer to return credentials handle
   1.598 + *	    pointer to return mechanisms
   1.599 + *	    pointer to return lifetime
   1.600 + * Returns: GSS_S_FAILURE, always
   1.601 + */
   1.602 +
   1.603 +OM_uint32 gss_acquire_cred (OM_uint32 *minor_status,gss_name_t desired_name,
   1.604 +			    OM_uint32 time_req,gss_OID_set desired_mechs,
   1.605 +			    gss_cred_usage_t cred_usage,
   1.606 +			    gss_cred_id_t *output_cred_handle,
   1.607 +			    gss_OID_set *actual_mechs,OM_uint32 *time_rec)
   1.608 +{
   1.609 +  *minor_status = 0;		/* never any minor status */
   1.610 +  return GSS_S_FAILURE;		/* server only */
   1.611 +}
   1.612 +
   1.613 +
   1.614 +/* GSSAPI release credentials
   1.615 + * Accepts: pointer to return minor status
   1.616 + *	    credentials handle to free
   1.617 + * Returns: GSS_S_COMPLETE, always
   1.618 + */
   1.619 +
   1.620 +OM_uint32 gss_release_cred (OM_uint32 *minor_status,gss_cred_id_t *cred_handle)
   1.621 +{
   1.622 +  *minor_status = 0;		/* never any minor status */
   1.623 +  return GSS_S_FAILURE;		/* server only */
   1.624 +}
   1.625 +
   1.626 +/* GSSAPI Accept security context
   1.627 + * Accepts: pointer to return minor status
   1.628 + *	    context
   1.629 + *	    acceptor credentials
   1.630 + *	    input token buffer
   1.631 + *	    input channel bindings
   1.632 + *	    pointer to return source name
   1.633 + *	    pointer to return mechanism type
   1.634 + *	    buffer to return output token
   1.635 + *	    pointer to return flags
   1.636 + *	    pointer to return context lifetime
   1.637 + *	    pointer to return delegated credentials
   1.638 + * Returns: GSS_S_FAILURE, always
   1.639 + */
   1.640 +
   1.641 +OM_uint32 gss_accept_sec_context (OM_uint32 *minor_status,
   1.642 +				  gss_ctx_id_t *context_handle,
   1.643 +				  gss_cred_id_t acceptor_cred_handle,
   1.644 +				  gss_buffer_t input_token_buffer,
   1.645 +				  gss_channel_bindings_t input_chan_bindings,
   1.646 +				  gss_name_t *src_name,gss_OID *mech_type,
   1.647 +				  gss_buffer_t output_token,
   1.648 +				  OM_uint32 *ret_flags,OM_uint32 *time_rec,
   1.649 +				  gss_cred_id_t *delegated_cred_handle)
   1.650 +{
   1.651 +  *minor_status = 0;		/* never any minor status */
   1.652 +  return GSS_S_FAILURE;		/* server only */
   1.653 +}
   1.654 +
   1.655 +
   1.656 +/* GSSAPI return printable name
   1.657 + * Accepts: pointer to return minor status
   1.658 + *	    internal name
   1.659 + *	    buffer to return output name
   1.660 + *	    output name type
   1.661 + * Returns: GSS_S_FAILURE, always
   1.662 + */
   1.663 +
   1.664 +OM_uint32 gss_display_name (OM_uint32 *minor_status,gss_name_t input_name,
   1.665 +			    gss_buffer_t output_name_buffer,
   1.666 +			    gss_OID *output_name_type)
   1.667 +{
   1.668 +  *minor_status = 0;		/* never any minor status */
   1.669 +  return GSS_S_FAILURE;		/* server only */
   1.670 +}
   1.671 +
   1.672 +/* Kerberos server valid check
   1.673 + * Returns: T if have keytab, NIL otherwise
   1.674 + */
   1.675 +
   1.676 +long kerberos_server_valid ()
   1.677 +{
   1.678 +  return NIL;
   1.679 +}
   1.680 +
   1.681 +
   1.682 +/* Kerberos check for missing or expired credentials
   1.683 + * Returns: T if should suggest running kinit, NIL otherwise
   1.684 + */
   1.685 +
   1.686 +long kerberos_try_kinit (OM_uint32 error)
   1.687 +{
   1.688 +  return NIL;
   1.689 +}
   1.690 +
   1.691 +/* Kerberos server log in
   1.692 + * Accepts: authorization ID as user name
   1.693 + *	    authentication ID as Kerberos principal
   1.694 + *	    argument count
   1.695 + *	    argument vector
   1.696 + * Returns: logged in user name if logged in, NIL otherwise
   1.697 + */
   1.698 +
   1.699 +char *kerberos_login (char *user,char *authuser,int argc,char *argv[])
   1.700 +{
   1.701 +  return NIL;
   1.702 +}

UW-IMAP'd extensions by yuuji