问题描述
所以我正在将 Schannel 服务器写入 IOS Gmail 客户端应用程序 - IMAP 服务器。
我正在强制使用 TLS1.0(尝试使用 TLS1.0to1.3 - 1.3 似乎可以通过 algo_mismatch 保释,但其他人也这样做,我也尝试使用 SSL3.0,但读到 gmail 不支持) .
目前我无法克服似乎在 recv
挂起的握手过程。我不知道我做错了什么 - 我还在我的(客户端设备 - IOS)上安装了证书。
我需要澄清 - 它在第一次成功结束时进入循环(AcceptSecurityContext
与 SEC_I_CONTINUE_NEEDED
)但在 send
之后(我还检查了匹配的结果cbBuffer
大小,所以它一定没问题)下一次迭代它挂在 recv
上。
这是握手部分:
static struct performhandshake {
CtxtHandle ctx; CredHandle hCred; SOCKET sock; SecPkgContext_StreamSizes ctxSizes; BOOL bLowMemoryIndicator;
} performhandshake(ctx,hCred,sock) CtxtHandle ctx; CredHandle hCred; SOCKET sock; {
SecPkgContext_StreamSizes ctxSizes;
struct diagose_internal diagose_internal_res; BOOL bLowMemoryIndicator = FALSE; Security_STATUS acceptctxsecstat;
CtxtHandle* pctx = SecIsValidHandle(&ctx) ? &ctx : 0;
SecBufferDesc buff = { .ulVersion = SECBUFFER_VERSION,1,(SecBuffer[]) { [0] = {.BufferType = SECBUFFER_TOKEN} } },* LastRecieved,outbuff = { .ulVersion = SECBUFFER_VERSION,* InBuff = &outbuff,* OutBuff = &buff; DWORD attrs; TimeStamp nocare;
char(*d)[USHRT_MAX] = malloc(sizeof * d);
//OutBuff->pBuffers[0].cbBuffer = check_last_error_int(recv,sock,OutBuff->pBuffers[0].pvBuffer = *d,sizeof * d,0);
do {
InBuff->pBuffers[0].cbBuffer = check_last_error_int(recv,InBuff->pBuffers[0].pvBuffer = *d,0);
switch (acceptctxsecstat = diagnose(AcceptSecurityContext,&hCred,pctx,InBuff,ctxflags,&ctx,OutBuff,&attrs,&nocare))
{
case SEC_I_CONTINUE_NEEDED:
case_continue_needed:
//,server,Security_NATIVE_DREP,//diagnose(CompleteAuthToken,OutBuff),//OutBuff->pBuffers[0].cbBuffer = check_last_error_int(recv,0),check_last_error_int(send,OutBuff->pBuffers[0].pvBuffer,OutBuff->pBuffers[0].cbBuffer,0);
FreeContextBuffer(OutBuff->pBuffers[0].pvBuffer);
LastRecieved = OutBuff; swap_ptr64(InBuff,OutBuff);
pctx = &ctx;
break;
case SEC_I_COMPLETE_NEEDED:
case SEC_I_COMPLETE_AND_CONTINUE:
diagnose(CompleteAuthToken,OutBuff);
switch (acceptctxsecstat) {
case SEC_I_COMPLETE_NEEDED:
goto end;
case SEC_I_COMPLETE_AND_CONTINUE:
goto case_continue_needed;
}
default: goto end;
}
} while (/*OutBuff->pBuffers[0].cbBuffer != SOCKET_ERROR && OutBuff->pBuffers[0].cbBuffer*/true);
end:
diagnose(QueryContextAttributes,SECPKG_ATTR_STREAM_SIZES,&ctxSizes);
free(d);
return (struct performhandshake) { ctx,ctxSizes,bLowMemoryIndicator };
}
这是我的主要功能:
main() {
WSADATA wsadat; WSAStartup(MAKEWORD(2,2),&wsadat),getaddrinfo("<local-ip>","993",(struct addrinfo[])
{ {.ai_family = AF_INET,.ai_socktype = SOCK_STREAM,.ai_protocol = IPPROTO_TCP,.ai_flags = AI_PASSIVE}
},& addrinfo);
InitializeCriticalSection(&crit);
HCERTSTORE hMyCertStore = NULL;
PCCERT_CONTEXT aCertContext = NULL;
//-------------------------------------------------------
// Open the My store,also called the personal store.
// This call to CertOpenStore opens the Local_Machine My
// store as opposed to the Current_User's My store.
hMyCertStore = CertOpenStore(CERT_STORE_PROV_SYstem,X509_ASN_ENCODING,CERT_SYstem_STORE_CURRENT_USER,L"MY");
if (hMyCertStore == NULL)
printf("Error opening MY store for server.\n");
//-------------------------------------------------------
// Search for a certificate with some specified
// string in it. This example attempts to find
// a certificate with the string "example server" in
// its subject string. Substitute an appropriate string
// to find a certificate for a specific user.
aCertContext = CertFindCertificateInStore(hMyCertStore,CERT_FIND_SUBJECT_STR_A,// use appropriate subject name
NULL
);
if (aCertContext == NULL)
printf("Error retrieving server certificate.");
CertCloseStore(hMyCertStore,0);
char buff[USHRT_MAX];
SOCKET conn = beginconn(&buff);
struct performhandshake reshandshake;
CredHandle hCred; TimeStamp nocare; struct diagose_internal diagose_internal_res; BOOL bLowMemoryIndicator = FALSE;
diagnose(AcquireCredentialsHandle,UNISP_NAME,SECPKG_CRED_BOTH,&(SCHANNEL_CRED){.dwVersion = SCHANNEL_CRED_VERSION,.hRootStore = hMyCertStore,.cCreds = 1,.paCred = (PCCERT_CONTEXT[]){ aCertContext },.grbitEnabledProtocols = SP_PROT_TLS1_0_SERVER },& hCred,& nocare);
SecInvalidateHandle(&reshandshake.ctx) reshandshake = performhandshake(reshandshake.ctx,conn);
return;
}
这里是整个片段供参考:
#undef UNICODE
#include <winsock2.h>
#include <stdio.h>
#include <stdbool.h>
#define Security_WIN32
#include <Security.h>
#include <Schnlsp.h>
const char server[] = "<cert-name>";
#define errprintf(...) (printf(__VA_ARGS__))
#define ctxflags (ASC_REQ_ALLOCATE_MEMORY|ASC_REQ_CONFIDENTIALITY)
#define swap(x,y)(x ^= y,y ^= x,x ^= y)
#define swap_ptr64(x,y)swap(*(ULONG64 *)&x,*(ULONG64 *)&y)
struct addrinfo* addrinfo;
static CRITICAL_SECTION crit;
static struct diagose_internal {
Security_STATUS secstat;
BOOL bLowMemoryIndicator;
} diagose_internal(in,desc,line) char desc[]; Security_STATUS in; {BOOL bLowMemoryIndicator = FALSE; in & 0x80000000 ? EnterCriticalSection(&crit),errprintf("%d - %s - %lx\n",line,in),bLowMemoryIndicator = SEC_E_INSUFFICIENT_MEMORY == in,LeaveCriticalSection(&crit) : 0; return (struct diagose_internal) { in,bLowMemoryIndicator }; }
#define diagnose(x,...) (diagose_internal_res=diagose_internal(x(__VA_ARGS__),#x,__LINE__),bLowMemoryIndicator=bLowMemoryIndicator||diagose_internal_res.bLowMemoryIndicator,diagose_internal_res.secstat)
static BOOL check_last_error_internal_int(in,line) char desc[]; {BOOL bLowMemoryIndicator = FALSE; int error = WSAGetLastError(); error ? EnterCriticalSection(&crit),error),bLowMemoryIndicator = error == WSA_NOT_ENOUGH_MEMORY,//|| error == WSA_QOS_TRAFFIC_CTRL_ERROR,LeaveCriticalSection(&crit) : 0; return in; }
#define check_last_error_int(x,...) check_last_error_internal_int(x(__VA_ARGS__),__LINE__)
static struct check_last_error_internal_handle {
SOCKET socket;
BOOL bLowMemoryIndicator;
} check_last_error_internal_handle(in,line) char desc[]; SOCKET in; {BOOL bLowMemoryIndicator = FALSE; int error = WSAGetLastError(); error ? EnterCriticalSection(&crit),LeaveCriticalSection(&crit) : 0; return (struct check_last_error_internal_handle) { in,bLowMemoryIndicator }; }
#define check_last_error_handle(x,__LINE__)
static SOCKET beginconn() {
SOCKET sock = check_last_error_handle(socket,addrinfo->ai_family,addrinfo->ai_socktype,addrinfo->ai_protocol);
//check_last_error_int(setsockopt,SOL_SOCKET,SO_RCVTIMEO,(DWORD[]) { 100 },sizeof(DWORD)),//check_last_error_int(setsockopt,SO_SNDTIMEO,check_last_error_int(bind,addrinfo->ai_addr,addrinfo->ai_addrlen),check_last_error_int(listen,SOMAXCONN);
SOCKET finalsock = accept(sock,NULL,NULL);
closesocket(sock);
return finalsock;
}
static struct performhandshake {
CtxtHandle ctx; CredHandle hCred; SOCKET sock; SecPkgContext_StreamSizes ctxSizes; BOOL bLowMemoryIndicator;
} performhandshake(ctx,bLowMemoryIndicator };
}
main() {
WSADATA wsadat; WSAStartup(MAKEWORD(2,conn);
return;
}
<local-ip>
和 <cert-name>
隐藏我的真实本地 IP 和服务器/证书名称。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)