140
/* Kerberos/Negotiate common specific data */
143
CredHandle hKerbEtcCred;
145
CtxtHandle hKerbEtcCtxt;
150
KerberosEtcSpec kdata;
153
static int DoSchannelNegotiation(SocketClass *, SspiData *, const void *opt);
154
static int DoKerberosNegotiation(SocketClass *, SspiData *, const void *opt);
155
static int DoNegotiateNegotiation(SocketClass *, SspiData *, const void *opt);
156
static int DoKerberosEtcProcessAuthentication(SocketClass *, const void *opt);
158
static SspiData *SspiDataAlloc(SocketClass *self)
162
if (sspidata = self->ssd, !sspidata)
163
sspidata = calloc(sizeof(SspiData), 1);
167
int StartupSspiService(SocketClass *self, SSPI_Service svc, const void *opt)
169
CSTR func = "DoServicelNegotiation";
172
if (NULL == (sspidata = SspiDataAlloc(self)))
176
case SchannelService:
177
return DoSchannelNegotiation(self, sspidata, opt);
178
case KerberosService:
179
return DoKerberosNegotiation(self, sspidata, opt);
180
case NegotiateService:
181
return DoNegotiateNegotiation(self, sspidata, opt);
188
int ContinueSspiService(SocketClass *self, SSPI_Service svc, const void *opt)
190
CSTR func = "ContinueSspiService";
194
case KerberosService:
195
case NegotiateService:
196
return DoKerberosEtcProcessAuthentication(self, opt);
202
static BOOL format_sspierr(char *errmsg, size_t buflen, SECURITY_STATUS r, const char *cmd, const char *cmd2)
208
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
209
r, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
210
errmsg, (DWORD)buflen, NULL))
214
size_t tlen = strlen(errmsg);
217
snprintf(errmsg, buflen, " in %s:%s", cmd, cmd2);
220
snprintf(errmsg, buflen, "%s:%s failed ", cmd, cmd2);
224
static void SSPI_set_error(SocketClass *s, SECURITY_STATUS r, const char *cmd, const char *cmd2)
226
int gerrno = SOCK_ERRNO;
229
format_sspierr(emsg, sizeof(emsg), r, cmd, cmd2);
231
if (NULL != s->_errormsg_)
234
s->_errormsg_ = strdup(emsg);
236
s->_errormsg_ = NULL;
237
mylog("(%d)%s ERRNO=%d\n", r, emsg, gerrno);
241
* Stuff for Schannel service
243
#include <schannel.h>
244
#pragma comment(lib, "crypt32")
245
#define UNI_SCHANNEL TEXT("sChannel")
246
#define IO_BUFFER_SIZE 0x10000
158
248
static SECURITY_STATUS CreateSchannelCredentials(LPCTSTR, LPSTR, PCredHandle);
159
249
static SECURITY_STATUS PerformSchannelClientHandshake(SOCKET, PCredHandle, LPSTR, CtxtHandle *, SecBuffer *);
160
250
static SECURITY_STATUS SchannelClientHandshakeLoop(SOCKET, PCredHandle, CtxtHandle *, BOOL, SecBuffer *);
163
253
static HCERTSTORE hMyCertStore = NULL;
165
static int DoSchannelNegotiation(SocketClass *self, const char *opt)
255
static int DoSchannelNegotiation(SocketClass *self, SspiData *sspidata, const void *opt)
167
257
CSTR func = "DoSchannelNegotiation";
258
SECURITY_STATUS r = SEC_E_OK;
259
const char *cmd = NULL;
168
260
SecBuffer ExtraData;
169
261
BOOL ret = 0, cCreds = FALSE, cCtxt = FALSE;
170
SchannelSpec *ssd = NULL;
262
SchannelSpec *ssd = &(sspidata->sdata);
172
if (NULL == (ssd = calloc(sizeof(SchannelSpec), 1)))
176
if (SEC_E_OK != CreateSchannelCredentials(NULL, NULL, &ssd->hCred))
178
mylog("%s:CreateSchannel failed\n", func);
264
if (SEC_E_OK != (r = CreateSchannelCredentials(NULL, NULL, &ssd->hCred)))
266
cmd = "CreateSchannelCredentials";
267
mylog("%s:%s failed\n", func, cmd);
182
if (SEC_E_OK != PerformSchannelClientHandshake(self->socket, &ssd->hCred, NULL, &ssd->hCtxt, &ExtraData))
271
if (SEC_E_OK != (r = PerformSchannelClientHandshake(self->socket, &ssd->hCred, NULL, &ssd->hCtxt, &ExtraData)))
184
mylog("%s:PerformSchannelClientHandshake failed\n", func);
273
cmd = "PerformSchannelClientHandshake";
274
mylog("%s:%s failed\n", func, cmd);
305
397
Status = AcquireCredentialsHandle(
306
NULL, /* Name of principal */
307
UNI_SCHANNEL, /* Name of package */
308
SECPKG_CRED_OUTBOUND, /* Flags indicating use */
309
NULL, /* Pointer to logon ID */
310
&SchannelCred, /* Package specific data */
311
NULL, /* Pointer to GetKey() func */
312
NULL, /* Value to pass to GetKey() */
313
phCreds, /* (out) Cred Handle */
314
&tsExpiry); /* (out) Lifetime (optional) */
398
NULL, /* Name of principal */
399
UNI_SCHANNEL, /* Name of package */
400
SECPKG_CRED_OUTBOUND, /* Flags indicating use */
401
NULL, /* Pointer to logon ID */
402
&SchannelCred, /* Package specific data */
403
NULL, /* Pointer to GetKey() func */
404
NULL, /* Value to pass to GetKey() */
405
phCreds, /* (out) Cred Handle */
406
&tsExpiry); /* (out) Lifetime (optional) */
315
407
if (Status != SEC_E_OK)
317
409
mylog("**** Error 0x%p returned by AcquireCredentialsHandle\n", Status);
927
* Stuff for Kerberos etc service
929
#define UNI_KERBEROS TEXT("Kerberos")
930
#define UNI_NEGOTIATE TEXT("Negotiate")
931
#define IO_BUFFER_SIZE 0x10000
934
static SECURITY_STATUS CreateKerberosEtcCredentials(LPCTSTR, SEC_CHAR *, LPCTSTR, PCredHandle);
935
static SECURITY_STATUS PerformKerberosEtcClientHandshake(SocketClass *, KerberosEtcSpec *ssd, size_t);
937
static int DoKerberosNegotiation(SocketClass *self, SspiData *sspidata, const void *opt)
939
CSTR func = "DoKerberosNegotiation";
940
SECURITY_STATUS r = SEC_E_OK;
941
const char * cmd = NULL;
943
KerberosEtcSpec *ssd = &(sspidata->kdata);
945
mylog("!!! %s in\n", __FUNCTION__);
946
if (SEC_E_OK != (r = CreateKerberosEtcCredentials(NULL, UNI_KERBEROS, (LPCTSTR) opt, &ssd->hKerbEtcCred)))
948
cmd = "CreateKerberosCredentials";
949
mylog("%s:%s failed\n", func, cmd);
950
SSPI_set_error(self, r, __FUNCTION__, cmd);
953
mylog("!!! CreateKerberosCredentials passed\n");
955
ssd->svcprinc = (LPTSTR) opt;
956
self->sspisvcs |= KerberosService;
957
self->ssd = sspidata;
958
return DoKerberosEtcProcessAuthentication(self, NULL);
961
static int DoNegotiateNegotiation(SocketClass *self, SspiData *sspidata, const void *opt)
963
CSTR func = "DoNegotiateNegotiation";
964
SECURITY_STATUS r = SEC_E_OK;
965
const char * cmd = NULL;
967
KerberosEtcSpec *ssd = &(sspidata->kdata);
969
mylog("!!! %s in\n", __FUNCTION__);
970
if (SEC_E_OK != (r = CreateKerberosEtcCredentials(NULL, UNI_NEGOTIATE, (LPCTSTR) opt, &ssd->hKerbEtcCred)))
972
cmd = "CreateNegotiateCredentials";
973
mylog("%s:%s failed\n", func, cmd);
974
SSPI_set_error(self, r, __FUNCTION__, cmd);
977
mylog("!!! CreateNegotiateCredentials passed\n");
979
ssd->svcprinc = (LPTSTR) opt;
980
self->sspisvcs |= NegotiateService;
981
self->ssd = sspidata;
982
return DoKerberosEtcProcessAuthentication(self, NULL);
985
static int DoKerberosEtcProcessAuthentication(SocketClass *self, const void *opt)
987
CSTR func = "DoKerberosEtcProcessAuthentication";
988
SECURITY_STATUS r = SEC_E_OK;
989
const char * cmd = NULL;
990
BOOL ret = 0, cCtxt = FALSE;
991
KerberosEtcSpec *ssd;
993
mylog("!!! %s in\n", __FUNCTION__);
994
ssd = &(((SspiData *)(self->ssd))->kdata);
995
if (SEC_E_OK != (r = PerformKerberosEtcClientHandshake(self, ssd, (size_t) opt)))
997
cmd = "PerformKerberosEtcClientHandshake";
998
mylog("%s:%s failed\n", func, cmd);
1001
mylog("!!! PerformKerberosEtcClientHandshake passed\n");
1007
SSPI_set_error(self, r, __FUNCTION__, cmd);
1008
FreeCredentialHandle(&ssd->hKerbEtcCred);
1011
DeleteSecurityContext(&ssd->hKerbEtcCtxt);
1013
self->sspisvcs &= (~(KerberosService | NegotiateService));
1020
CreateKerberosEtcCredentials(
1021
LPCTSTR opt, /* in */
1022
SEC_CHAR *packname, /* in */
1023
LPCTSTR pszUserName, /* in */
1024
PCredHandle phCreds) /* out */
1027
SECURITY_STATUS Status;
1030
* Create an SSPI credential.
1033
Status = AcquireCredentialsHandle(
1034
NULL, /* Name of principal */
1035
packname, /* Name of package */
1036
SECPKG_CRED_OUTBOUND, /* Flags indicating use */
1037
NULL, /* Pointer to logon ID */
1038
NULL, /* Package specific data */
1039
NULL, /* Pointer to GetKey() func */
1040
NULL, /* Value to pass to GetKey() */
1041
phCreds, /* (out) Cred Handle */
1042
&tsExpiry); /* (out) Lifetime (optional) */
1043
if (Status != SEC_E_OK)
1045
mylog("**** Error 0x%p returned by AcquireCredentialsHandle\n", Status);
1056
PerformKerberosEtcClientHandshake(
1057
SocketClass *sock, /* in */
1058
KerberosEtcSpec *ssd, /* i-o */
1061
SecBufferDesc InBuffer;
1062
SecBuffer InBuffers[1];
1063
SecBufferDesc OutBuffer;
1064
SecBuffer OutBuffers[1];
1066
DWORD dwSSPIOutFlags;
1068
SECURITY_STATUS scRet;
1069
CtxtHandle hContext;
1072
mylog("!!! inlen=%u svcprinc=%s\n", inlen, ssd->svcprinc);
1073
if (ssd->ValidCtxt && inlen > 0)
1075
if (NULL == (inbuf = malloc(inlen + 1)))
1077
return SEC_E_INTERNAL_ERROR;
1079
SOCK_get_n_char(sock, inbuf, inlen);
1080
if (SOCK_get_errcode(sock) != 0)
1082
mylog("**** Error %d receiving data from server (1)\n", SOCK_ERRNO);
1084
return SEC_E_INTERNAL_ERROR;
1087
InBuffer.ulVersion = SECBUFFER_VERSION;
1088
InBuffer.cBuffers = 1;
1089
InBuffer.pBuffers = InBuffers;
1090
InBuffers[0].pvBuffer = inbuf;
1091
InBuffers[0].cbBuffer = inlen;
1092
InBuffers[0].BufferType = SECBUFFER_TOKEN;
1095
dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
1096
ISC_REQ_REPLAY_DETECT |
1097
ISC_REQ_CONFIDENTIALITY |
1098
ISC_RET_EXTENDED_ERROR |
1099
ISC_REQ_ALLOCATE_MEMORY |
1103
* Initiate a ClientHello message and generate a token.
1106
OutBuffers[0].pvBuffer = NULL;
1107
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
1108
OutBuffers[0].cbBuffer = 0;
1110
OutBuffer.cBuffers = 1;
1111
OutBuffer.pBuffers = OutBuffers;
1112
OutBuffer.ulVersion = SECBUFFER_VERSION;
1114
mylog("!!! before InitializeSecurityContext\n");
1115
scRet = InitializeSecurityContext(
1117
ssd->ValidCtxt ? &ssd->hKerbEtcCtxt : NULL,
1121
SECURITY_NATIVE_DREP,
1122
ssd->ValidCtxt ? &InBuffer : NULL,
1128
mylog("!!! %s:InitializeSecurityContext ret=%x\n", __FUNCTION__, scRet);
1132
if (SEC_E_OK != scRet && SEC_I_CONTINUE_NEEDED != scRet)
1134
mylog("**** Error %x returned by InitializeSecurityContext\n", scRet);
1137
if (!ssd->ValidCtxt)
1139
memcpy(&ssd->hKerbEtcCtxt, &hContext, sizeof(CtxtHandle));
1140
ssd->ValidCtxt = TRUE;
1143
mylog("!!! cbBuffer=%d pvBuffer=%p\n", OutBuffers[0].cbBuffer, OutBuffers[0].pvBuffer);
1144
/* Send response to server if there is one. */
1145
if (OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
1147
int reslen = OutBuffers[0].cbBuffer;
1148
mylog("!!! responding 'p' + int(%d) + %dbytes of data\n", reslen + 4, reslen);
1149
SOCK_put_char(sock, 'p');
1150
SOCK_put_int(sock, reslen + 4, 4);
1151
SOCK_put_n_char(sock, OutBuffers[0].pvBuffer, reslen);
1152
SOCK_flush_output(sock);
1153
if (SOCK_get_errcode(sock) != 0)
1155
mylog("**** Error %d sending data to server (1)\n", SOCK_ERRNO);
1156
FreeContextBuffer(OutBuffers[0].pvBuffer);
1157
return SEC_E_INTERNAL_ERROR;
1160
mylog("%d bytes of handshake data sent\n", OutBuffers[0].cbBuffer);
1162
/* Free output buffer. */
1163
FreeContextBuffer(OutBuffers[0].pvBuffer);
1164
OutBuffers[0].pvBuffer = NULL;
1168
// return KerberosEtcClientHandshakeLoop(Socket, ssd, TRUE, pExtraData);
833
1172
int SSPI_recv(SocketClass *self, void *buffer, int len)
835
1174
CSTR func = "SSPI_recv";