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 +}