src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp
branchJDK-8199569-branch
changeset 56552 543279c75f1a
child 56553 3e490160d5ec
equal deleted inserted replaced
56551:5eb8262e8c5f 56552:543279c75f1a
       
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #define UNICODE
       
    27 #define _UNICODE
       
    28 
       
    29 #include <windows.h>
       
    30 #include <stdlib.h>
       
    31 #include <stdio.h>
       
    32 #include <stdlib.h>
       
    33 #include <string.h>
       
    34 
       
    35 #define GSS_DLL_FILE
       
    36 #include "gssapi.h"
       
    37 
       
    38 #define SECURITY_WIN32
       
    39 #include <sspi.h>
       
    40 
       
    41 #pragma comment(lib, "secur32.lib")
       
    42 
       
    43 //#define DEBUG
       
    44 
       
    45 #ifdef DEBUG
       
    46 TCHAR _bb[256];
       
    47 #define SEC_SUCCESS(Status) ((Status) >= 0 ? TRUE: (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,0,ss,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),_bb,256,0),printf("SECURITY_STATUS: (%lx) %ls\n",ss,_bb),FALSE))
       
    48 #define P fprintf(stdout, "SSPI (%ld): \n", __LINE__); fflush(stdout);
       
    49 #define PP(s) fprintf(stdout, "SSPI (%ld): ", __LINE__); fprintf(stdout, "%s\n", s); fflush(stdout)
       
    50 #define PP1(s,n) fprintf(stdout, "SSPI (%ld): ", __LINE__); fprintf(stdout, s, n); fflush(stdout)
       
    51 #define PP2(s,n1,n2) fprintf(stdout, "SSPI (%ld): ", __LINE__); fprintf(stdout, s, n1, n2); fflush(stdout)
       
    52 #define PP3(s,n1,n2,n3) fprintf(stdout, "SSPI (%ld): ", __LINE__); fprintf(stdout, s, n1, n2, n3); fflush(stdout)
       
    53 BOOL debug = TRUE;
       
    54 #else
       
    55 #define SEC_SUCCESS(Status) ((Status) >= 0)
       
    56 #define P
       
    57 #define PP(s)
       
    58 #define PP1(s,n)
       
    59 #define PP2(s,n1,n2)
       
    60 #define PP3(s,n1,n2,n3)
       
    61 BOOL debug = FALSE;
       
    62 #endif
       
    63 
       
    64 char KRB5_OID[9] = {(char)0x2a, (char)0x86, (char)0x48, (char)0x86, (char)0xf7, (char)0x12, (char)0x01, (char)0x02, (char)0x02};
       
    65 char KRB5_U2U_OID[10] = {(char)0x2a, (char)0x86, (char)0x48, (char)0x86, (char)0xf7, (char)0x12, (char)0x01, (char)0x02, (char)0x02, (char)0x03};
       
    66 char SPNEGO_OID[6] = {(char)0x2b, (char)0x06, (char)0x01, (char)0x05, (char)0x05, (char)0x02};
       
    67 char USER_NAME_OID[10] = {(char)0x2a, (char)0x86, (char)0x48, (char)0x86, (char)0xf7, (char)0x12, (char)0x01, (char)0x02, (char)0x01, (char)0x01};
       
    68 char HOST_SERVICE_NAME_OID[10] = {(char)0x2a, (char)0x86, (char)0x48, (char)0x86, (char)0xf7, (char)0x12, (char)0x01, (char)0x02, (char)0x01, (char)0x04};
       
    69 
       
    70 typedef struct {
       
    71     TCHAR PackageName[20];
       
    72     CredHandle* phCred;
       
    73     struct _SecHandle hCtxt;
       
    74     DWORD cbMaxMessage;
       
    75     SecPkgContext_Sizes SecPkgContextSizes;
       
    76 } Context;
       
    77 
       
    78 #ifdef __cplusplus
       
    79 extern "C" {
       
    80 #endif /* __cplusplus */
       
    81 
       
    82 __declspec(dllexport) OM_uint32 gss_release_name
       
    83                                 (OM_uint32 *minor_status,
       
    84                                 gss_name_t *name) {
       
    85     return GSS_S_FAILURE;
       
    86 }
       
    87 
       
    88 __declspec(dllexport) OM_uint32 gss_import_name
       
    89                                 (OM_uint32 *minor_status,
       
    90                                 gss_buffer_t input_name_buffer,
       
    91                                 gss_OID input_name_type,
       
    92                                 gss_name_t *output_name) {
       
    93     SecPkgCredentials_Names* names = new SecPkgCredentials_Names();
       
    94     int len = (int)input_name_buffer->length;
       
    95     names->sUserName = new SEC_WCHAR[len + 1];
       
    96     MultiByteToWideChar(CP_ACP, 0, (LPSTR)input_name_buffer->value, len, names->sUserName, len);
       
    97     names->sUserName[len] = 0;
       
    98     if (input_name_type->length == 10 && !memcmp(input_name_type->elements, HOST_SERVICE_NAME_OID, 10)) {
       
    99         for (int i = 0; i < len; i++) {
       
   100             if (names->sUserName[i] == '@') {
       
   101                 names->sUserName[i] = '/';
       
   102             }
       
   103         }
       
   104     }
       
   105     *output_name = (gss_name_t) names;
       
   106     return GSS_S_COMPLETE;
       
   107 }
       
   108 
       
   109 __declspec(dllexport) OM_uint32 gss_compare_name
       
   110                                 (OM_uint32 *minor_status,
       
   111                                 gss_name_t name1,
       
   112                                 gss_name_t name2,
       
   113                                 int *name_equal) {
       
   114     return GSS_S_FAILURE;
       
   115 }
       
   116 
       
   117 __declspec(dllexport) OM_uint32 gss_canonicalize_name
       
   118                                 (OM_uint32 *minor_status,
       
   119                                 gss_name_t input_name,
       
   120                                 gss_OID mech_type,
       
   121                                 gss_name_t *output_name) {
       
   122     return GSS_S_FAILURE;
       
   123 }
       
   124 
       
   125 __declspec(dllexport) OM_uint32 gss_export_name
       
   126                                 (OM_uint32 *minor_status,
       
   127                                 gss_name_t input_name,
       
   128                                 gss_buffer_t exported_name) {
       
   129     return GSS_S_FAILURE;
       
   130 }
       
   131 
       
   132 __declspec(dllexport) OM_uint32 gss_display_name
       
   133                                 (OM_uint32 *minor_status,
       
   134                                 gss_name_t input_name,
       
   135                                 gss_buffer_t output_name_buffer,
       
   136                                 gss_OID *output_name_type) {
       
   137     SecPkgCredentials_Names* names = (SecPkgCredentials_Names*)input_name;
       
   138     int len = (int)wcslen(names->sUserName);
       
   139     char* buffer = new char[len+1];
       
   140     WideCharToMultiByte(CP_ACP, 0, names->sUserName, len, buffer, len, NULL, NULL);
       
   141     buffer[len] = 0;
       
   142     output_name_buffer->length = len+1;
       
   143     output_name_buffer->value = buffer;
       
   144     PP1("Name found: %ls\n", names->sUserName);
       
   145     PP2("%d [%s]", len, buffer);
       
   146     if (output_name_type != NULL) {
       
   147         gss_OID_desc* oid = new gss_OID_desc();
       
   148         oid->length = (OM_uint32)strlen(USER_NAME_OID);
       
   149         oid->elements = strdup(USER_NAME_OID);
       
   150         *output_name_type = oid;
       
   151     }
       
   152     return GSS_S_COMPLETE;
       
   153 }
       
   154 
       
   155 long TimeStampToLong(TimeStamp *time) {
       
   156     ULARGE_INTEGER *a, *b;
       
   157     FILETIME fnow;
       
   158     GetSystemTimeAsFileTime(&fnow);
       
   159     a = (ULARGE_INTEGER*)time;
       
   160     b = (ULARGE_INTEGER*)&fnow;
       
   161     PP1("Difference %ld\n", (long)((a->QuadPart - b->QuadPart) / 10000000));
       
   162     return (long)((a->QuadPart - b->QuadPart) / 10000000);
       
   163 }
       
   164 
       
   165 __declspec(dllexport) OM_uint32 gss_acquire_cred
       
   166                                 (OM_uint32 *minor_status,
       
   167                                 gss_name_t desired_name,
       
   168                                 OM_uint32 time_req,
       
   169                                 gss_OID_set desired_mech,
       
   170                                 gss_cred_usage_t cred_usage,
       
   171                                 gss_cred_id_t *output_cred_handle,
       
   172                                 gss_OID_set *actual_mechs,
       
   173                                 OM_uint32 *time_rec) {
       
   174     if (desired_name != NULL) {
       
   175         return GSS_S_FAILURE; // Only support default cred
       
   176     }
       
   177     SECURITY_STATUS ss;
       
   178     CredHandle* cred = new CredHandle();
       
   179     TimeStamp ts;
       
   180 	cred_usage = 0;
       
   181     PP1("AcquireCredentialsHandle with %d\n", cred_usage);
       
   182     ss = AcquireCredentialsHandle(
       
   183             NULL,
       
   184             L"Kerberos",
       
   185             cred_usage == 0 ? SECPKG_CRED_BOTH :
       
   186                 (cred_usage == 1 ? SECPKG_CRED_OUTBOUND : SECPKG_CRED_INBOUND),
       
   187             NULL,
       
   188             NULL,
       
   189             NULL,
       
   190             NULL,
       
   191             cred,
       
   192             &ts
       
   193             );
       
   194 
       
   195     actual_mechs = &desired_mech;
       
   196     *output_cred_handle = (void*)cred;
       
   197     if (time_rec != NULL) {
       
   198         *time_rec = TimeStampToLong(&ts);
       
   199     }
       
   200 
       
   201     return GSS_S_COMPLETE;
       
   202 }
       
   203 
       
   204 __declspec(dllexport) OM_uint32 gss_release_cred
       
   205                                 (OM_uint32 *minor_status,
       
   206                                 gss_cred_id_t *cred_handle) {
       
   207     return GSS_S_FAILURE;
       
   208 }
       
   209 
       
   210 __declspec(dllexport) OM_uint32 gss_inquire_cred
       
   211                                 (OM_uint32 *minor_status,
       
   212                                 gss_cred_id_t cred_handle,
       
   213                                 gss_name_t *name,
       
   214                                 OM_uint32 *lifetime,
       
   215                                 gss_cred_usage_t *cred_usage,
       
   216                                 gss_OID_set *mechanisms) {
       
   217     CredHandle* cred = (CredHandle*)cred_handle;
       
   218     SECURITY_STATUS ss;
       
   219     if (name) {
       
   220         SecPkgCredentials_Names* names = new SecPkgCredentials_Names();
       
   221         ss = QueryCredentialsAttributes(cred, SECPKG_CRED_ATTR_NAMES, names);
       
   222         *name = (gss_name_t) names;
       
   223     }
       
   224     // Others inquiries not supported yet
       
   225     return GSS_S_COMPLETE;
       
   226 }
       
   227 
       
   228 __declspec(dllexport) OM_uint32 gss_import_sec_context
       
   229                                 (OM_uint32 *minor_status,
       
   230                                 gss_buffer_t interprocess_token,
       
   231                                 gss_ctx_id_t *context_handle) {
       
   232     return GSS_S_FAILURE;
       
   233 }
       
   234 
       
   235 void FillContextAfterEstablished(Context *pc) {
       
   236     QueryContextAttributes(&pc->hCtxt, SECPKG_ATTR_SIZES,
       
   237                 &pc->SecPkgContextSizes);
       
   238 }
       
   239 
       
   240 SECURITY_STATUS GenClientContext(
       
   241         Context *pc,
       
   242         int flag,
       
   243         BYTE *pIn,
       
   244         size_t cbIn,
       
   245         BYTE *pOut,
       
   246         size_t *pcbOut,
       
   247         BOOL *pfDone,
       
   248         ULONG *pOutFlag,
       
   249         TCHAR *pszTarget) {
       
   250     SECURITY_STATUS ss;
       
   251     TimeStamp Lifetime;
       
   252     SecBufferDesc OutBuffDesc;
       
   253     SecBuffer OutSecBuff;
       
   254     SecBufferDesc InBuffDesc;
       
   255     SecBuffer InSecBuff;
       
   256 
       
   257     OutBuffDesc.ulVersion = SECBUFFER_VERSION;
       
   258     OutBuffDesc.cBuffers = 1;
       
   259     OutBuffDesc.pBuffers = &OutSecBuff;
       
   260 
       
   261     OutSecBuff.cbBuffer = (ULONG)*pcbOut;
       
   262     OutSecBuff.BufferType = SECBUFFER_TOKEN;
       
   263     OutSecBuff.pvBuffer = pOut;
       
   264 
       
   265     PP2("TARGET: %ls %ls\n", pszTarget, pc->PackageName);
       
   266     PP2("flag: %x [%ls]\n", flag, pszTarget);
       
   267     if (pIn) {
       
   268         InBuffDesc.ulVersion = SECBUFFER_VERSION;
       
   269         InBuffDesc.cBuffers = 1;
       
   270         InBuffDesc.pBuffers = &InSecBuff;
       
   271 
       
   272         InSecBuff.cbBuffer = (ULONG)cbIn;
       
   273         InSecBuff.BufferType = SECBUFFER_TOKEN;
       
   274         InSecBuff.pvBuffer = pIn;
       
   275 
       
   276         ss = InitializeSecurityContext(
       
   277                 pc->phCred,
       
   278                 &pc->hCtxt,
       
   279                 pszTarget,
       
   280                 flag,
       
   281                 0,
       
   282                 SECURITY_NATIVE_DREP,
       
   283                 &InBuffDesc,
       
   284                 0,
       
   285                 &pc->hCtxt,
       
   286                 &OutBuffDesc,
       
   287                 pOutFlag,
       
   288                 &Lifetime);
       
   289     } else {
       
   290         if (!pc->phCred) {
       
   291             PP("No credentials provided, acquire automatically");
       
   292             ss = AcquireCredentialsHandle(
       
   293                     NULL,
       
   294                     pc->PackageName,
       
   295                     SECPKG_CRED_OUTBOUND,
       
   296                     NULL,
       
   297                     NULL,
       
   298                     NULL,
       
   299                     NULL,
       
   300                     pc->phCred,
       
   301                     &Lifetime);
       
   302             PP("end");
       
   303             if (!(SEC_SUCCESS(ss))) {
       
   304                 PP("Failed");
       
   305                 return ss;
       
   306             }
       
   307         } else {
       
   308             PP("Credentials OK");
       
   309         }
       
   310         ss = InitializeSecurityContext(
       
   311                 pc->phCred,
       
   312                 NULL,
       
   313                 pszTarget,
       
   314                 flag,
       
   315                 0,
       
   316                 SECURITY_NATIVE_DREP,
       
   317                 NULL,
       
   318                 0,
       
   319                 &pc->hCtxt,
       
   320                 &OutBuffDesc,
       
   321                 pOutFlag,
       
   322                 &Lifetime);
       
   323     }
       
   324 
       
   325     if (!SEC_SUCCESS(ss)) {
       
   326         PP("InitializeSecurityContext Failed");
       
   327         return ss;
       
   328     }
       
   329     //-------------------------------------------------------------------
       
   330     //  If necessary, complete the token.
       
   331 
       
   332     if ((SEC_I_COMPLETE_NEEDED == ss)
       
   333             || (SEC_I_COMPLETE_AND_CONTINUE == ss)) {
       
   334         ss = CompleteAuthToken(&pc->hCtxt, &OutBuffDesc);
       
   335         if (!SEC_SUCCESS(ss)) {
       
   336             return ss;
       
   337         }
       
   338     }
       
   339 
       
   340     *pcbOut = OutSecBuff.cbBuffer;
       
   341 
       
   342     *pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
       
   343             (SEC_I_COMPLETE_AND_CONTINUE == ss));
       
   344 
       
   345     return ss;
       
   346 }
       
   347 
       
   348 Context* NewContext(TCHAR* PackageName) {
       
   349     SECURITY_STATUS ss;
       
   350     PSecPkgInfo pkgInfo;
       
   351 
       
   352     Context* out = (Context*)malloc(sizeof(Context));
       
   353     ss = QuerySecurityPackageInfo(
       
   354             PackageName,
       
   355             &pkgInfo);
       
   356     if (!SEC_SUCCESS(ss)) {
       
   357         return NULL;
       
   358     }
       
   359     out->phCred = NULL;
       
   360     out->cbMaxMessage = pkgInfo->cbMaxToken;
       
   361     PP2("   QuerySecurityPackageInfo %ls goes %ld\n", PackageName, out->cbMaxMessage);
       
   362     wcscpy(out->PackageName, PackageName);
       
   363     FreeContextBuffer(pkgInfo);
       
   364     return out;
       
   365 }
       
   366 
       
   367 int flagSspi2Gss(int fin) {
       
   368 	int fout = 0;
       
   369 	if (fin & ISC_REQ_MUTUAL_AUTH) fout |= GSS_C_MUTUAL_FLAG;
       
   370 	if (fin & ISC_REQ_CONFIDENTIALITY) fout |= GSS_C_CONF_FLAG;
       
   371 	if (fin & ISC_REQ_DELEGATE) fout |= GSS_C_DELEG_FLAG;
       
   372 	if (fin & ISC_REQ_INTEGRITY) fout |= GSS_C_INTEG_FLAG;
       
   373 	if (fin & ISC_REQ_REPLAY_DETECT) fout |= GSS_C_REPLAY_FLAG;
       
   374 	if (fin & ISC_REQ_SEQUENCE_DETECT) fout |= GSS_C_SEQUENCE_FLAG;
       
   375 	return fout;
       
   376 }
       
   377 
       
   378 int flagGss2Sspi(int fin) {
       
   379 	int fout = 0;
       
   380 	if (fin & GSS_C_MUTUAL_FLAG) fout |= ISC_RET_MUTUAL_AUTH;
       
   381 	if (fin & GSS_C_CONF_FLAG) fout |= ISC_RET_CONFIDENTIALITY;
       
   382 	if (fin & GSS_C_DELEG_FLAG) fout |= ISC_RET_DELEGATE;
       
   383 	if (fin & GSS_C_INTEG_FLAG) fout |= ISC_RET_INTEGRITY;
       
   384 	if (fin & GSS_C_REPLAY_FLAG) fout |= ISC_RET_REPLAY_DETECT;
       
   385 	if (fin & GSS_C_SEQUENCE_FLAG) fout |= ISC_RET_SEQUENCE_DETECT;
       
   386 	return fout;
       
   387 }
       
   388 
       
   389 __declspec(dllexport) OM_uint32 gss_init_sec_context
       
   390                                 (OM_uint32 *minor_status,
       
   391                                 gss_cred_id_t initiator_cred_handle,
       
   392                                 gss_ctx_id_t *context_handle,
       
   393                                 gss_name_t target_name,
       
   394                                 gss_OID mech_type,
       
   395                                 OM_uint32 req_flags,
       
   396                                 OM_uint32 time_req,
       
   397                                 gss_channel_bindings_t input_chan_bindings,
       
   398                                 gss_buffer_t input_token,
       
   399                                 gss_OID *actual_mech_type,
       
   400                                 gss_buffer_t output_token,
       
   401                                 OM_uint32 *ret_flags,
       
   402                                 OM_uint32 *time_rec) {
       
   403     SECURITY_STATUS ss;
       
   404 
       
   405     Context* pc;
       
   406     if (input_token->length == 0) {
       
   407         pc = NewContext(L"Kerberos");
       
   408         pc->phCred = (CredHandle*)initiator_cred_handle;
       
   409         *context_handle = (gss_ctx_id_t) pc;
       
   410     } else {
       
   411         pc = (Context*)*context_handle;
       
   412     }
       
   413 
       
   414     output_token->length = pc->cbMaxMessage;
       
   415     output_token->value = new char[pc->cbMaxMessage];
       
   416 
       
   417     DWORD outFlag;    
       
   418     TCHAR outName[100];
       
   419 
       
   420     OM_uint32 minor;
       
   421     gss_buffer_desc tn;
       
   422     gss_display_name(&minor, target_name, &tn, NULL);
       
   423     MultiByteToWideChar(CP_ACP, 0, (LPCCH)tn.value, (int)tn.length, outName, (int)tn.length);
       
   424     outName[tn.length] = 0;
       
   425 
       
   426     BOOL pfDone;
       
   427     ss = GenClientContext(
       
   428             pc, flagGss2Sspi(req_flags),
       
   429             (BYTE*)input_token->value, input_token->length,
       
   430             (BYTE*)output_token->value, &(output_token->length),
       
   431             &pfDone, &outFlag,
       
   432             (TCHAR*)outName);
       
   433     if (ss == SEC_E_OK) FillContextAfterEstablished(pc);
       
   434 	outFlag = flagSspi2Gss(outFlag);
       
   435 
       
   436 	if (!SEC_SUCCESS(ss)) {
       
   437 		return GSS_S_FAILURE;
       
   438 	}
       
   439 
       
   440     *ret_flags = (OM_uint32)outFlag;
       
   441     if (ss == SEC_I_CONTINUE_NEEDED) {
       
   442         return GSS_S_CONTINUE_NEEDED;
       
   443     } else {
       
   444         *ret_flags |= GSS_C_PROT_READY_FLAG;
       
   445         return GSS_S_COMPLETE;
       
   446     }
       
   447 }
       
   448 
       
   449 __declspec(dllexport) OM_uint32 gss_accept_sec_context
       
   450                                 (OM_uint32 *minor_status,
       
   451                                 gss_ctx_id_t *context_handle,
       
   452                                 gss_cred_id_t acceptor_cred_handle,
       
   453                                 gss_buffer_t input_token,
       
   454                                 gss_channel_bindings_t input_chan_bindings,
       
   455                                 gss_name_t *src_name,
       
   456                                 gss_OID *mech_type,
       
   457                                 gss_buffer_t output_token,
       
   458                                 OM_uint32 *ret_flags,
       
   459                                 OM_uint32 *time_rec,
       
   460                                 gss_cred_id_t *delegated_cred_handle) {
       
   461     return GSS_S_FAILURE;
       
   462 }
       
   463 
       
   464 __declspec(dllexport) OM_uint32 gss_inquire_context
       
   465                                 (OM_uint32 *minor_status,
       
   466                                 gss_ctx_id_t context_handle,
       
   467                                 gss_name_t *src_name,
       
   468                                 gss_name_t *targ_name,
       
   469                                 OM_uint32 *lifetime_rec,
       
   470                                 gss_OID *mech_type,
       
   471                                 OM_uint32 *ctx_flags,
       
   472                                 int *locally_initiated,
       
   473                                 int *open) {
       
   474     Context* pc = (Context*) context_handle;
       
   475     return GSS_S_FAILURE;
       
   476 }
       
   477 
       
   478 __declspec(dllexport) OM_uint32 gss_delete_sec_context
       
   479                                 (OM_uint32 *minor_status,
       
   480                                 gss_ctx_id_t *context_handle,
       
   481                                 gss_buffer_t output_token) {
       
   482     return GSS_S_FAILURE;
       
   483 }
       
   484 
       
   485 __declspec(dllexport) OM_uint32 gss_context_time
       
   486                                 (OM_uint32 *minor_status,
       
   487                                 gss_ctx_id_t context_handle,
       
   488                                 OM_uint32 *time_rec) {
       
   489     Context* pc = (Context*) context_handle;
       
   490     return GSS_S_FAILURE;
       
   491 }
       
   492 
       
   493 __declspec(dllexport) OM_uint32 gss_wrap_size_limit
       
   494                                 (OM_uint32 *minor_status,
       
   495                                 gss_ctx_id_t context_handle,
       
   496                                 int conf_req_flag,
       
   497                                 gss_qop_t qop_req,
       
   498                                 OM_uint32 req_output_size,
       
   499                                 OM_uint32 *max_input_size) {
       
   500     Context* pc = (Context*) context_handle;
       
   501     *max_input_size = pc->cbMaxMessage;
       
   502     return GSS_S_COMPLETE;
       
   503 }
       
   504 
       
   505 __declspec(dllexport) OM_uint32 gss_export_sec_context
       
   506                                 (OM_uint32 *minor_status,
       
   507                                 gss_ctx_id_t *context_handle,
       
   508                                 gss_buffer_t interprocess_token) {
       
   509     return GSS_S_FAILURE;
       
   510 }
       
   511 
       
   512 __declspec(dllexport) OM_uint32 gss_get_mic
       
   513                                 (OM_uint32 *minor_status,
       
   514                                 gss_ctx_id_t context_handle,
       
   515                                 gss_qop_t qop_req,
       
   516                                 gss_buffer_t message_buffer,
       
   517                                 gss_buffer_t msg_token) {
       
   518 
       
   519     Context* pc = (Context*) context_handle;
       
   520 
       
   521     SECURITY_STATUS ss;
       
   522     SecBufferDesc BuffDesc;
       
   523     SecBuffer SecBuff[2];
       
   524 
       
   525     BuffDesc.cBuffers = 2;
       
   526     BuffDesc.pBuffers = SecBuff;
       
   527     BuffDesc.ulVersion = SECBUFFER_VERSION;
       
   528 
       
   529     SecBuff[0].BufferType = SECBUFFER_DATA;
       
   530     SecBuff[0].cbBuffer = (ULONG)message_buffer->length;
       
   531     SecBuff[0].pvBuffer = message_buffer->value;
       
   532 
       
   533     SecBuff[1].BufferType = SECBUFFER_TOKEN;
       
   534     SecBuff[1].cbBuffer = pc->SecPkgContextSizes.cbMaxSignature;
       
   535     SecBuff[1].pvBuffer = msg_token->value = malloc(SecBuff[1].cbBuffer);
       
   536 
       
   537     ss = MakeSignature(&pc->hCtxt, 0, &BuffDesc, 0);
       
   538 
       
   539     if (!SEC_SUCCESS(ss)) {
       
   540         free(SecBuff[1].pvBuffer);
       
   541         return GSS_S_FAILURE;
       
   542     }
       
   543 
       
   544     msg_token->length = SecBuff[1].cbBuffer;
       
   545     return GSS_S_COMPLETE;
       
   546 }
       
   547 
       
   548 __declspec(dllexport) OM_uint32 gss_verify_mic
       
   549                                 (OM_uint32 *minor_status,
       
   550                                 gss_ctx_id_t context_handle,
       
   551                                 gss_buffer_t message_buffer,
       
   552                                 gss_buffer_t token_buffer,
       
   553                                 gss_qop_t *qop_state) {
       
   554     Context* pc = (Context*) context_handle;
       
   555 
       
   556     SECURITY_STATUS ss;
       
   557     SecBufferDesc BuffDesc;
       
   558     SecBuffer SecBuff[2];
       
   559     ULONG qop;
       
   560 
       
   561     BuffDesc.ulVersion = 0;
       
   562     BuffDesc.cBuffers = 2;
       
   563     BuffDesc.pBuffers = SecBuff;
       
   564 
       
   565     SecBuff[0].BufferType = SECBUFFER_TOKEN;
       
   566     SecBuff[0].cbBuffer = (ULONG)token_buffer->length;
       
   567     SecBuff[0].pvBuffer = token_buffer->value;
       
   568 
       
   569     SecBuff[1].BufferType = SECBUFFER_DATA;
       
   570     SecBuff[1].cbBuffer = (ULONG)message_buffer->length;
       
   571     SecBuff[1].pvBuffer = message_buffer->value;
       
   572 
       
   573     ss = VerifySignature(&pc->hCtxt, &BuffDesc, 0, &qop);
       
   574     *qop_state = qop;
       
   575 
       
   576     if (ss == SEC_E_OK) {
       
   577         return GSS_S_COMPLETE;
       
   578     } else if (ss == SEC_E_OUT_OF_SEQUENCE) {
       
   579         return GSS_S_UNSEQ_TOKEN;
       
   580     } else {
       
   581         return GSS_S_BAD_SIG;
       
   582     }
       
   583 }
       
   584 
       
   585 __declspec(dllexport) OM_uint32 gss_wrap
       
   586                                 (OM_uint32 *minor_status,
       
   587                                 gss_ctx_id_t context_handle,
       
   588                                 int conf_req_flag,
       
   589                                 gss_qop_t qop_req,
       
   590                                 gss_buffer_t input_message_buffer,
       
   591                                 int *conf_state,
       
   592                                 gss_buffer_t output_message_buffer) {
       
   593 
       
   594     Context* pc = (Context*) context_handle;
       
   595 
       
   596     SECURITY_STATUS ss;
       
   597     SecBufferDesc BuffDesc;
       
   598     SecBuffer SecBuff[3];
       
   599 
       
   600     BuffDesc.ulVersion = SECBUFFER_VERSION;
       
   601     BuffDesc.cBuffers = 3;
       
   602     BuffDesc.pBuffers = SecBuff;
       
   603 
       
   604     SecBuff[0].BufferType = SECBUFFER_TOKEN;
       
   605     SecBuff[0].cbBuffer = pc->SecPkgContextSizes.cbSecurityTrailer;
       
   606     output_message_buffer->value = SecBuff[0].pvBuffer = malloc(pc->SecPkgContextSizes.cbSecurityTrailer
       
   607             + input_message_buffer->length + pc->SecPkgContextSizes.cbBlockSize);;
       
   608 
       
   609     SecBuff[1].BufferType = SECBUFFER_DATA;
       
   610     SecBuff[1].cbBuffer = (ULONG)input_message_buffer->length;
       
   611     SecBuff[1].pvBuffer = malloc(SecBuff[1].cbBuffer);
       
   612     memcpy(SecBuff[1].pvBuffer, input_message_buffer->value, input_message_buffer->length);
       
   613 
       
   614     SecBuff[2].BufferType = SECBUFFER_PADDING;
       
   615     SecBuff[2].cbBuffer = pc->SecPkgContextSizes.cbBlockSize;
       
   616     SecBuff[2].pvBuffer = malloc(SecBuff[2].cbBuffer);
       
   617 
       
   618     ss = EncryptMessage(&pc->hCtxt, conf_req_flag ? 0 : SECQOP_WRAP_NO_ENCRYPT, &BuffDesc, 0);
       
   619     *conf_state = conf_req_flag;
       
   620 
       
   621     if (!SEC_SUCCESS(ss)) {
       
   622         free(SecBuff[0].pvBuffer);
       
   623         free(SecBuff[1].pvBuffer);
       
   624         free(SecBuff[2].pvBuffer);
       
   625         return GSS_S_FAILURE;
       
   626     }
       
   627 
       
   628     memcpy((PBYTE)SecBuff[0].pvBuffer + SecBuff[0].cbBuffer, SecBuff[1].pvBuffer,
       
   629             SecBuff[1].cbBuffer);
       
   630     memcpy((PBYTE)SecBuff[0].pvBuffer + SecBuff[0].cbBuffer + SecBuff[1].cbBuffer,
       
   631             SecBuff[2].pvBuffer, SecBuff[2].cbBuffer);
       
   632 
       
   633     output_message_buffer->length = SecBuff[1].cbBuffer + SecBuff[0].cbBuffer
       
   634             + SecBuff[2].cbBuffer;
       
   635     free(SecBuff[1].pvBuffer);
       
   636     free(SecBuff[2].pvBuffer);
       
   637 
       
   638     return GSS_S_COMPLETE;
       
   639 }
       
   640 
       
   641 __declspec(dllexport) OM_uint32 gss_unwrap
       
   642                                 (OM_uint32 *minor_status,
       
   643                                 gss_ctx_id_t context_handle,
       
   644                                 gss_buffer_t input_message_buffer,
       
   645                                 gss_buffer_t output_message_buffer,
       
   646                                 int *conf_state,
       
   647                                 gss_qop_t *qop_state) {
       
   648     Context* pc = (Context*) context_handle;
       
   649 
       
   650     SECURITY_STATUS ss;
       
   651     SecBufferDesc BuffDesc;
       
   652     SecBuffer SecBuff[2];
       
   653     ULONG ulQop = 0;
       
   654 
       
   655     BuffDesc.cBuffers = 2;
       
   656     BuffDesc.pBuffers = SecBuff;
       
   657     BuffDesc.ulVersion = SECBUFFER_VERSION;
       
   658 
       
   659     SecBuff[0].BufferType = SECBUFFER_STREAM;
       
   660     SecBuff[0].cbBuffer = (ULONG)input_message_buffer->length;
       
   661     output_message_buffer->value = SecBuff[0].pvBuffer = malloc(input_message_buffer->length);
       
   662     memcpy(SecBuff[0].pvBuffer, input_message_buffer->value, input_message_buffer->length);
       
   663 
       
   664     SecBuff[1].BufferType = SECBUFFER_DATA;
       
   665     SecBuff[1].cbBuffer = 0;
       
   666     SecBuff[1].pvBuffer = NULL;
       
   667 
       
   668     ss = DecryptMessage(&pc->hCtxt, &BuffDesc, 0, &ulQop);
       
   669     if (!SEC_SUCCESS(ss)) {
       
   670         free(SecBuff[0].pvBuffer);
       
   671         return GSS_S_FAILURE;
       
   672     }
       
   673     output_message_buffer->length = SecBuff[1].cbBuffer;
       
   674     output_message_buffer->value = SecBuff[1].pvBuffer;
       
   675     *conf_state = ulQop == SECQOP_WRAP_NO_ENCRYPT ? 0 : 1;
       
   676     return GSS_S_COMPLETE;
       
   677 }
       
   678 
       
   679 __declspec(dllexport) OM_uint32 gss_indicate_mechs
       
   680                                 (OM_uint32 *minor_status,
       
   681                                 gss_OID_set *mech_set) {
       
   682     gss_OID_set_desc *copy;
       
   683     OM_uint32 minor = 0;
       
   684     OM_uint32 major = GSS_S_COMPLETE;
       
   685     int n = 0;
       
   686     int i = 0;
       
   687     BOOLEAN hasSpnego = false, hasKerberos = false;
       
   688 
       
   689     ULONG ccPackages;
       
   690     PSecPkgInfo packages;
       
   691     EnumerateSecurityPackages(&ccPackages, &packages);
       
   692     PP1("EnumerateSecurityPackages returns %ld\n", ccPackages);
       
   693     // TODO: only return Kerberos, so no need to check input later
       
   694     PSecPkgInfo pkgInfo;
       
   695     SECURITY_STATUS ss = QuerySecurityPackageInfo(L"Negotiate", &pkgInfo);
       
   696     if (ss == SEC_E_OK) {
       
   697         // n++;
       
   698         // hasSpnego = true;
       
   699     }
       
   700     ss = QuerySecurityPackageInfo(L"Kerberos", &pkgInfo);
       
   701     if (ss == SEC_E_OK) {
       
   702         n++;
       
   703         hasKerberos = true;
       
   704     }
       
   705 
       
   706     if ((copy = new gss_OID_set_desc[1]) == NULL) {
       
   707         major = GSS_S_FAILURE;
       
   708         goto done;
       
   709     }
       
   710 
       
   711     if ((copy->elements = new gss_OID_desc[n]) == NULL) {
       
   712         major = GSS_S_FAILURE;
       
   713         goto done;
       
   714     }
       
   715 
       
   716     if (hasKerberos) {
       
   717         gss_OID_desc *out = &copy->elements[i];
       
   718         if ((out->elements = new char[sizeof(KRB5_OID)]) == NULL) {
       
   719             major = GSS_S_FAILURE;
       
   720             goto done;
       
   721         }
       
   722         (void) memcpy(out->elements, KRB5_OID, sizeof(KRB5_OID));
       
   723         out->length = sizeof(KRB5_OID);
       
   724         i++;
       
   725     }    
       
   726     if (hasSpnego) {
       
   727         gss_OID_desc *out = &copy->elements[i];
       
   728         char in[6] = { 0x2B, 0x06, 0x01, 0x05, 0x05, 0x02 };
       
   729         if ((out->elements = new char[sizeof(in)]) == NULL) {
       
   730             major = GSS_S_FAILURE;
       
   731             goto done;
       
   732         }
       
   733         (void) memcpy(out->elements, in, sizeof(in));
       
   734         out->length = sizeof(in);
       
   735         i++;
       
   736     }    
       
   737     copy->count = i;
       
   738 
       
   739     *mech_set = copy;
       
   740 done:
       
   741     if (major != GSS_S_COMPLETE) {
       
   742         // (void) generic_gss_release_oid_set(&minor, &copy);
       
   743     }
       
   744 
       
   745     return (major);
       
   746 }
       
   747 
       
   748 __declspec(dllexport) OM_uint32 gss_inquire_names_for_mech
       
   749                                 (OM_uint32 *minor_status,
       
   750                                 const gss_OID mechanism,
       
   751                                 gss_OID_set *name_types) {
       
   752     return GSS_S_FAILURE;
       
   753 }
       
   754 
       
   755 __declspec(dllexport) OM_uint32 gss_add_oid_set_member
       
   756                                 (OM_uint32 *minor_status,
       
   757                                 gss_OID member_oid,
       
   758                                 gss_OID_set *oid_set) {
       
   759     return GSS_S_FAILURE;
       
   760 }
       
   761 
       
   762 __declspec(dllexport) OM_uint32 gss_display_status
       
   763                                 (OM_uint32 *minor_status,
       
   764                                 OM_uint32 status_value,
       
   765                                 int status_type,
       
   766                                 gss_OID mech_type,
       
   767                                 OM_uint32 *message_context,
       
   768                                 gss_buffer_t status_string) {
       
   769     return GSS_S_FAILURE;
       
   770 }
       
   771 
       
   772 __declspec(dllexport) OM_uint32 gss_create_empty_oid_set
       
   773                                 (OM_uint32 *minor_status,
       
   774                                 gss_OID_set *oid_set) {
       
   775     return GSS_S_FAILURE;
       
   776 }
       
   777 
       
   778 __declspec(dllexport) OM_uint32 gss_release_oid_set
       
   779                                 (OM_uint32 *minor_status,
       
   780                                 gss_OID_set *set) {
       
   781     return GSS_S_FAILURE;
       
   782 }
       
   783 
       
   784 __declspec(dllexport) OM_uint32 gss_release_buffer
       
   785                                 (OM_uint32 *minor_status,
       
   786                                 gss_buffer_t buffer) {
       
   787     return GSS_S_FAILURE;
       
   788 }
       
   789 
       
   790 #ifdef __cplusplus
       
   791 }
       
   792 #endif