online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
#define WIN32_LEAN_AND_MEAN #include <assert.h> #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> #define SECURITY_WIN32 1 #include <Security.h> #include <WinCrypt.h> #include <schannel.h> #include <string.h> #define SERVER_CERTIFICATE_SUBJECT_NAME "C=US,ST=Ks,L=Olathe,O=XYZ LTD,OU=ABC,CN=Server7,[email protected]" #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "Advapi32.lib") #pragma comment(lib,"Secur32.lib") #pragma comment(lib,"Crypt32.lib") #define DEFAULT_BUFLEN 100 #define DEFAULT_PORT "27015" int context_expire = 0; static DWORD EncryptSend(SOCKET Socket, CtxtHandle * phContext, PBYTE pbIoBuffer, SecPkgContext_StreamSizes Sizes); int ReadDecrypt(SOCKET Socket, PCredHandle phCreds, CtxtHandle * phContext, PBYTE pbIoBuffer, DWORD cbIoBufferLength, char* message, int messagelen); PBYTE ExtraEncBuff; #define ExtraMemorySize 1024 unsigned int ExtraEncBufferSize = 0; unsigned int ExtraEncBufferLen = 0; char *ExtraDecBuff=NULL; unsigned int ExtraDecBufferSize = 0; unsigned int ExtraDecBufferLen = 0; static int ssl_default_callback_read(SOCKET fd, void *buf, int num) { int rc; do { { while (((rc = recv(fd, buf, num, 0)) == -1) && ((NT_WSA2errno ()) == EINTR || (NT_WSA2errno ()) == EINPROGRESS)); }; } while (rc < 0 && ((NT_WSA2errno ()) == EAGAIN || (NT_WSA2errno()) == EWOULDBLOCK) && ssl_wait_for_socket(fd, 1) > 0); if (rc < 0) printf("cannot recv data from socket %d", (int)fd); return rc; } static int ssl_default_callback_write(SOCKET fd, void *buf, int num) { int rc; do { { while (((rc = send(fd, buf, num, 0)) == -1) && ((NT_WSA2errno ()) == EINTR || (NT_WSA2errno ()) == EINPROGRESS)); }; } while (rc < 0 && ((NT_WSA2errno ()) == EAGAIN || (NT_WSA2errno ()) == EWOULDBLOCK) && ssl_wait_for_socket(fd, 0) > 0); if (rc < 0) printf("cannot send data to socket %d", (int)fd); return rc; } #define ESHUTDOWN 58 static int NT_WSA2errno() { int ret; switch (WSAGetLastError()) { case WSAEACCES: ret = EACCES; break; case WSAEADDRINUSE: ret = EADDRINUSE; break; case WSAEADDRNOTAVAIL: ret = EADDRNOTAVAIL; break; case WSAEAFNOSUPPORT: ret = EAFNOSUPPORT; break; case WSAEALREADY: ret = EALREADY; break; case WSAEBADF: ret = EBADF; break; case WSAECONNABORTED: ret = ECONNABORTED; break; case WSAECONNREFUSED: ret = ECONNREFUSED; break; case WSAECONNRESET: ret = ECONNRESET; break; case WSAEDESTADDRREQ: ret = EDESTADDRREQ; break; case WSAEFAULT: ret = EFAULT; break; case WSAEHOSTUNREACH: ret = EHOSTUNREACH; break; case WSAEINPROGRESS: ret = EINPROGRESS; break; case WSAEINTR: ret = EINTR; break; case WSAEINVAL: ret = EINVAL; break; case WSAEISCONN: ret = EISCONN; break; case WSAELOOP: ret = ELOOP; break; case WSAEMFILE: ret = EMFILE; break; case WSAEMSGSIZE: ret = EMSGSIZE; break; case WSAENAMETOOLONG: ret = ENAMETOOLONG; break; case WSAENETDOWN: ret = ENETDOWN; break; case WSAENETRESET: ret = EBADF; break; case WSAENETUNREACH: ret = ENETUNREACH; break; case WSAENOBUFS: ret = ENOBUFS; break; case WSAENOPROTOOPT: ret = ENOPROTOOPT; break; case WSAENOTCONN: ret = ENOTCONN; break; case WSAENOTEMPTY: ret = ENOTEMPTY; break; case WSAENOTSOCK: ret = EBADF; break; case WSAEOPNOTSUPP: ret = EBADF; break; case WSAEPROTONOSUPPORT: ret = EPROTONOSUPPORT; break; case WSAEPROTOTYPE: ret = EPROTOTYPE; break; case WSAESHUTDOWN: ret = ESHUTDOWN; break; case WSAETIMEDOUT: ret = ETIMEDOUT; break; case WSAEWOULDBLOCK: ret = EWOULDBLOCK; break; case WSA_INVALID_PARAMETER: ret = EINVAL; break; case WSA_NOT_ENOUGH_MEMORY: ret = ENOMEM; break; case WSANOTINITIALISED: ret = ENETDOWN; break; default: ret = WSAGetLastError(); break; } return ret; } #define SELECT_TIMEOUT_MS 200 static int ssl_wait_for_socket(SOCKET fd, int mode_read) { int rc; fd_set fds, *read_fds, *write_fds; struct timeval timeout = { 0, SELECT_TIMEOUT_MS * 1000 }; read_fds = mode_read ? &fds : NULL; write_fds = mode_read ? NULL : &fds; do { FD_ZERO(&fds); FD_SET(fd, &fds); {while (((rc = select(fd + 1, read_fds, write_fds, NULL, &timeout)) == -1) && ((NT_WSA2errno ()) == EINTR || (NT_WSA2errno ()) == EINPROGRESS));}; } while (rc == 0); if (rc < 0) printf("failed checking socket %d for being %s", (int)fd, mode_read ? "readable" : "writable"); return rc; } /*****************************************************************************/ DWORD server_send(char * client_message, SOCKET Socket,CtxtHandle * phContext, SecPkgContext_StreamSizes Sizes ){ DWORD cbIoBufferLength, cbData; PBYTE pbIoBuffer; // Create a buffer. cbIoBufferLength = Sizes.cbHeader + Sizes.cbMaximumMessage + Sizes.cbTrailer; pbIoBuffer = LocalAlloc(LMEM_FIXED, cbIoBufferLength); if(pbIoBuffer == NULL) { printf("**** Out of memory (2)\n"); return -1; } // Build the request - must be < maximum message size2 sprintf( pbIoBuffer+Sizes.cbHeader, "%s", client_message ); // message begins after the header cbData = EncryptSend( Socket, phContext, pbIoBuffer, Sizes ); if(cbData == SOCKET_ERROR || cbData == 0) { printf("**** Error %d sending data to server (3)\n", WSAGetLastError()); } LocalFree(pbIoBuffer); return cbData; } static void DisplaySchannelError(DWORD ErrCode) { LPSTR pszName = NULL; switch(ErrCode) { case SEC_E_BUFFER_TOO_SMALL: pszName = "SEC_E_BUFFER_TOO_SMALL - The message buffer is too small. Used with the Digest SSP."; break; case SEC_E_CRYPTO_SYSTEM_INVALID: pszName = "SEC_E_CRYPTO_SYSTEM_INVALID - The cipher chosen for the security context is not supported. Used with the Digest SSP."; break; case SEC_E_INCOMPLETE_MESSAGE: pszName = "SEC_E_INCOMPLETE_MESSAGE - The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessage (General) again."; break; case SEC_E_INVALID_HANDLE: pszName = "SEC_E_INVALID_HANDLE - A context handle that is not valid was specified in the phContext parameter. Used with the Digest and Schannel SSPs."; break; case SEC_E_INVALID_TOKEN: pszName = "SEC_E_INVALID_TOKEN - The buffers are of the wrong type or no buffer of type SECBUFFER_DATA was found. Used with the Schannel SSP."; break; case SEC_E_MESSAGE_ALTERED: pszName = "SEC_E_MESSAGE_ALTERED - The message has been altered. Used with the Digest and Schannel SSPs."; break; case SEC_E_OUT_OF_SEQUENCE: pszName = "SEC_E_OUT_OF_SEQUENCE - The message was not received in the correct sequence."; break; case SEC_E_QOP_NOT_SUPPORTED: pszName = "SEC_E_QOP_NOT_SUPPORTED - Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP."; break; case SEC_I_CONTEXT_EXPIRED: pszName = "SEC_I_CONTEXT_EXPIRED - The message sender has finished using the connection and has initiated a shutdown."; break; case SEC_I_RENEGOTIATE: pszName = "SEC_I_RENEGOTIATE - The remote party requires a new handshake sequence or the application has just initiated a shutdown."; break; case SEC_E_ENCRYPT_FAILURE: pszName = "SEC_E_ENCRYPT_FAILURE - The specified data could not be encrypted."; break; case SEC_E_DECRYPT_FAILURE: pszName = "SEC_E_DECRYPT_FAILURE - The specified data could not be decrypted."; break; } printf("Error 0x%x %s \n", ErrCode, pszName); } static void DisplayCertChain(PCCERT_CONTEXT pServerCert) { CHAR szName[1000]; PCCERT_CONTEXT pCurrentCert, pIssuerCert; DWORD dwVerificationFlags; printf("\n"); // display leaf name if(!CertNameToStr( pServerCert->dwCertEncodingType, &pServerCert->pCertInfo->Subject, CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG, szName, sizeof(szName) ) ) { printf("**** Error 0x%x building subject name\n", GetLastError()); } printf("Server subject: %s\n", szName); if(!CertNameToStr( pServerCert->dwCertEncodingType, &pServerCert->pCertInfo->Issuer, CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG, szName, sizeof(szName) ) ) { printf("**** Error 0x%x building issuer name\n", GetLastError()); } printf("Server issuer: %s\n\n", szName); // display certificate chain pCurrentCert = pServerCert; while(pCurrentCert != NULL) { dwVerificationFlags = 0; pIssuerCert = CertGetIssuerCertificateFromStore( pServerCert->hCertStore, pCurrentCert, NULL, &dwVerificationFlags ); if(pIssuerCert == NULL) { if(pCurrentCert != pServerCert) CertFreeCertificateContext(pCurrentCert); break; } if( !CertNameToStr( pIssuerCert->dwCertEncodingType, &pIssuerCert->pCertInfo->Subject, CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG, szName, sizeof(szName) ) ) { printf("**** Error 0x%x building subject name\n", GetLastError()); } printf("CA subject: %s\n", szName); if(!CertNameToStr( pIssuerCert->dwCertEncodingType, &pIssuerCert->pCertInfo->Issuer, CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG, szName, sizeof(szName) ) ) { printf("**** Error 0x%x building issuer name\n", GetLastError()); } printf("CA issuer: %s\n\n", szName); if(pCurrentCert != pServerCert) CertFreeCertificateContext(pCurrentCert); pCurrentCert = pIssuerCert; pIssuerCert = NULL; } } int GetCertificateandCredHandle(CredHandle *pcredHandle) { HCERTSTORE cert_store = NULL; PCCERT_CONTEXT server_cert = NULL; cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"); if(!cert_store) { printf("\nschannel: Failed to open cert store last error is 0x%x", GetLastError()); } CERT_NAME_BLOB *subBlob = NULL; DWORD subBlobLen = 0; if (!CertStrToNameA(X509_ASN_ENCODING, "C=US,ST=Ks,L=Olathe,O=XYZ LTD,OU=ABC,CN=Server7,[email protected]", CERT_X500_NAME_STR, NULL, NULL, &subBlobLen, NULL)) { printf("\nCertStrToName 1 failed"); return -1; } subBlob = malloc(subBlobLen); if (!CertStrToNameA(X509_ASN_ENCODING, "C=US,ST=Ks,L=Olathe,O=XYZ LTD,OU=ABC,CN=Server7,[email protected]", CERT_X500_NAME_STR, NULL, (BYTE*)subBlob, &subBlobLen, NULL)) { printf("\n CertStrToName 2 failed"); return -1; } const char *cert_prop="8c9d88c9ad953cd66f1f98504f16414cbbeaa1d5"; unsigned char hash[255]; char *p; int i, x = 0; CRYPT_HASH_BLOB blob; for (p = (char *) cert_prop, i = 0; *p && i < sizeof(hash); i++) { if (*p >= '0' && *p <= '9') x = (*p - '0') << 4; else if (*p >= 'A' && *p <= 'F') x = (*p - 'A' + 10) << 4; else if (*p >= 'a' && *p <= 'f') x = (*p - 'a' + 10) << 4; if (!*++p) /* unexpected end of string */ break; if (*p >= '0' && *p <= '9') x += *p - '0'; else if (*p >= 'A' && *p <= 'F') x += *p - 'A' + 10; else if (*p >= 'a' && *p <= 'f') x += *p - 'a' + 10; hash[i] = x; /* skip any space(s) between hex numbers */ for (p++; *p && *p == ' '; p++); } blob.cbData = i; blob.pbData = (unsigned char *) &hash; server_cert = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING, 0, CERT_FIND_HASH, &blob, NULL); if(server_cert == NULL) { printf("\n\n certificate not found"); return -1; } else printf("\n\n certificate found"); DisplayCertChain(server_cert); TimeStamp expiration; SCHANNEL_CRED schannelCred; memset(&schannelCred, 0, sizeof(schannelCred)); schannelCred.dwVersion = SCHANNEL_CRED_VERSION; schannelCred.cCreds = 1; schannelCred.paCred = &server_cert; schannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER; schannelCred.hRootStore = NULL; schannelCred.dwFlags = SCH_USE_STRONG_CRYPTO ; SECURITY_STATUS status = AcquireCredentialsHandle( NULL, UNISP_NAME, SECPKG_CRED_INBOUND, NULL, &schannelCred, NULL, NULL, pcredHandle, &expiration); printf("\nstatus after AcquireCredentialsHandle <0x%x >",status); if (status != SEC_E_OK) { CertCloseStore(cert_store, 0); return -1; } CertCloseStore(cert_store, 0); return 0; } #define IO_BUFFER_SIZE 0x10000 int SSPINegotiateLoop(CredHandle *pcredHandle, SOCKET ClientSocket, CtxtHandle *hContext ) { TimeStamp tsExpiry; SECURITY_STATUS scRet; SecBufferDesc InBuffer; SecBufferDesc OutBuffer; SecBuffer InBuffers[2]; SecBuffer OutBuffers[1]; DWORD dwSSPIOutFlags = 0; int first_time = 1; DWORD readBufferBytes = 0; DWORD dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_STREAM ; dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH; OutBuffer.cBuffers = 1; OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; printf("\nStarted SSPINegotiateLoop with %d bytes already received from client.", readBufferBytes); scRet = SEC_E_INCOMPLETE_MESSAGE; // Main loop, keep going around this until the handshake is completed or fails while (scRet == SEC_I_CONTINUE_NEEDED || scRet == SEC_E_INCOMPLETE_MESSAGE || scRet == SEC_I_INCOMPLETE_CREDENTIALS) { printf("\nExtraEncbufflen : %d",ExtraEncBufferLen); printf("\nExtraEncbuffsize : %d",ExtraEncBufferSize); printf("\nscRet Value : 0x%x",scRet); if (ExtraEncBufferLen == 0 || scRet == SEC_E_INCOMPLETE_MESSAGE) { // Read some more bytes if available, we may read more than is needed for this phase of handshake if(ExtraEncBufferSize - ExtraDecBufferLen < ExtraMemorySize){ ExtraEncBuff = realloc(ExtraEncBuff, ExtraEncBufferSize + ExtraMemorySize); if(ExtraEncBuff == NULL){ printf("**** Out of memory (1)\n"); return SEC_E_INTERNAL_ERROR; } ExtraEncBufferSize = ExtraEncBufferSize + ExtraMemorySize; } printf("\n sizeof %d",(int) (sizeof(ExtraEncBuff) - readBufferBytes)); int err = ssl_default_callback_read(ClientSocket, ExtraEncBuff + ExtraEncBufferLen, ExtraEncBufferSize - ExtraEncBufferLen); //const DWORD err = recv(ClientSocket, readBuffer + readBufferBytes, IO_BUFFER_SIZE - readBufferBytes, 0); if (err == SOCKET_ERROR || err == 0) { if (ERROR_TIMEOUT == GetLastError()) printf("\nRecv timed out"); else if (WSA_IO_PENDING == GetLastError()) printf("\nRecv Overlapped operations will complete later"); else if (WSAECONNRESET == GetLastError()) printf("\nRecv failed, the socket was closed by the other host"); else printf("\nRecv failed: %d", GetLastError()); return 0; } else { readBufferBytes += err; ExtraEncBufferLen += err; printf("\n "); if (err == readBufferBytes) printf("\nReceived %d handshake bytes from client", err); else printf("\nReceived %d handshake bytes from client, total is now %d ", err, readBufferBytes); } } InBuffers[0].pvBuffer = ExtraEncBuff ; InBuffers[0].cbBuffer = ExtraEncBufferLen; InBuffers[0].BufferType = SECBUFFER_TOKEN; InBuffers[1].pvBuffer = NULL; InBuffers[1].cbBuffer = 0; InBuffers[1].BufferType = SECBUFFER_EMPTY; InBuffer.cBuffers = 2; InBuffer.pBuffers = InBuffers; InBuffer.ulVersion = SECBUFFER_VERSION; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; if(first_time) { printf("\n first_time"); scRet = AcceptSecurityContext( pcredHandle, // Which certificate to use, already established NULL, // The context handle if we have one, ask to make one if this is first call &InBuffer, // Input buffer list dwSSPIFlags, // What we require of the connection 0, // Data representation, not used hContext, // If we don't yet have a context handle, it is returned here &OutBuffer, // [out] The output buffer, for messages to be sent to the other end &dwSSPIOutFlags, // [out] The flags associated with the negotiated connection &tsExpiry); if(scRet != SEC_E_INCOMPLETE_MESSAGE){ first_time =0; } } else { printf("\n second_time"); scRet = AcceptSecurityContext( pcredHandle, // Which certificate to use, already established hContext, // The context handle if we have one, ask to make one if this is first call &InBuffer, // Input buffer list dwSSPIFlags, // What we require of the connection 0, // Data representation, not used hContext, // If we don't yet have a context handle, it is returned here &OutBuffer, // [out] The output buffer, for messages to be sent to the other end &dwSSPIOutFlags, // [out] The flags associated with the negotiated connection &tsExpiry); } printf("\nscRet Value soon after : 0x%x",scRet); if (scRet == SEC_E_OK || scRet == SEC_I_CONTINUE_NEEDED || (!scRet && (0 != (dwSSPIOutFlags & ASC_RET_EXTENDED_ERROR)))) { if (OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL) { // Send response to client if there is one int err = ssl_default_callback_write(ClientSocket, OutBuffers[0].pvBuffer,OutBuffers[0].cbBuffer); if (err == SOCKET_ERROR || err == 0) { printf("\nSend handshake to client failed: %d", GetLastError()); FreeContextBuffer(OutBuffers[0].pvBuffer); return 0; } else { printf("\nSend %d handshake bytes to client", OutBuffers[0].cbBuffer); } FreeContextBuffer(OutBuffers[0].pvBuffer); OutBuffers[0].pvBuffer = NULL; } } // At this point, we've read and checked a message (giving scRet) and maybe sent a response (giving err) // as far as the client is concerned, the SSL handshake may be done, but we still have checks to make. if (InBuffers[1].BufferType == SECBUFFER_EXTRA && InBuffers[1].cbBuffer > 0) { if(ExtraEncBufferSize==0){ ExtraEncBuff=malloc(InBuffers[1].cbBuffer); ExtraEncBufferSize=InBuffers[1].cbBuffer; } int free_mem = ExtraEncBufferSize - ExtraEncBufferLen; if(ExtraEncBufferSize < InBuffers[1].cbBuffer) { ExtraEncBuff = realloc(ExtraEncBuff, ExtraEncBufferSize + InBuffers[1].cbBuffer - free_mem ); ExtraEncBufferSize = ExtraEncBufferSize + InBuffers[1].cbBuffer - free_mem; } memmove(ExtraEncBuff,InBuffers[1].pvBuffer, InBuffers[1].cbBuffer); ExtraEncBufferLen = InBuffers[1].cbBuffer; } else { readBufferBytes = 0; ExtraEncBufferLen = 0; readBufferBytes = 0; // prepare for next receive printf("\nHandshake working so far, more packets required"); } if (scRet == SEC_E_OK) { break; // The normal exit } else if (scRet == SEC_E_INCOMPLETE_MESSAGE) { printf("\nAcceptSecurityContext got a partial message and is requesting more be read"); continue; } else if (scRet == SEC_E_INCOMPLETE_CREDENTIALS) { printf("\nAcceptSecurityContext got SEC_E_INCOMPLETE_CREDENTIALS, it shouldn't but we'll treat it like a partial message"); // Go around again. break; } else if (scRet == SEC_I_CONTINUE_NEEDED) { printf("\nAcceptSecurityContext got SEC_I_CONTINUE_NEEDED, it shouldn't but we'll treat it like a partial message"); // Go around again. continue; } else if (scRet) { if (scRet == SEC_E_INVALID_TOKEN) printf("\nAcceptSecurityContext detected an invalid token, maybe the client rejected our certificate"); else printf("\nAcceptSecurityContext Failed with error code %lx", scRet); return 0; } printf("\n scRet value %lx", scRet); } // while loop printf("\n scRet value %lx", scRet); return 0; } static LONG DisconnectFromClient( SOCKET Socket, PCredHandle phCreds, CtxtHandle * phContext ) { PBYTE pbMessage; DWORD dwType, dwSSPIFlags, dwSSPIOutFlags, cbMessage, Status; SecBufferDesc OutBuffer; SecBuffer OutBuffers[1]; TimeStamp tsExpiry; int cbData; dwType = SCHANNEL_SHUTDOWN; // Notify schannel that we are about to close the connection. OutBuffers[0].pvBuffer = &dwType; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = sizeof(dwType); OutBuffer.cBuffers = 1; OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; Status = ApplyControlToken(phContext, &OutBuffer); if(FAILED(Status)) { printf("**** Error 0x%x returned by ApplyControlToken\n", Status); goto cleanup; } // Build an SSL close notify message. dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; OutBuffer.cBuffers = 1; OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; Status = AcceptSecurityContext( phCreds, phContext, NULL, dwSSPIFlags, 0, NULL, &OutBuffer, &dwSSPIOutFlags, &tsExpiry ); if(FAILED(Status)) { printf("**** Error 0x%x returned by InitializeSecurityContext\n", Status); goto cleanup; } pbMessage = OutBuffers[0].pvBuffer; cbMessage = OutBuffers[0].cbBuffer; // Send the close notify message to the server. if(pbMessage != NULL && cbMessage != 0) { cbData = ssl_default_callback_write(Socket,pbMessage, cbMessage); // cbData = send(Socket, pbMessage, cbMessage, 0); if(cbData == SOCKET_ERROR || cbData == 0) { Status = WSAGetLastError(); printf("**** Error %d sending close notify\n", Status); } printf("Sending Close Notify\n"); printf("%d bytes of handshake data sent\n", cbData); FreeContextBuffer(pbMessage); // Free output buffer. } cleanup: int iResult; DeleteSecurityContext(phContext); // Free the security context. iResult = shutdown(Socket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("\nshutdown failed with error: %d\n", WSAGetLastError()); closesocket(Socket); WSACleanup(); } else{ closesocket(Socket); WSACleanup(); printf(" shutdown done/n"); } return Status; } static DWORD EncryptSend( SOCKET Socket, CtxtHandle * phContext, PBYTE pbIoBuffer, SecPkgContext_StreamSizes Sizes ) // http://msdn.microsoft.com/en-us/library/aa375378(VS.85).aspx // The encrypted message is encrypted in place, overwriting the original contents of its buffer. { SECURITY_STATUS scRet; // unsigned long cbBuffer; // Size of the buffer, in bytes SecBufferDesc Message; // unsigned long BufferType; // Type of the buffer (below) SecBuffer Buffers[4]; // void SEC_FAR * pvBuffer; // Pointer to the buffer DWORD cbMessage; PBYTE pbMessage; int cbData; printf("inside encrypt send"); pbMessage = pbIoBuffer + Sizes.cbHeader; // Offset by "header size" cbMessage = (DWORD)strlen(pbMessage); printf("Sending %d bytes of plaintext:", cbMessage); // Encrypt the HTTP request. Buffers[0].pvBuffer = pbIoBuffer; // Pointer to buffer 1 Buffers[0].cbBuffer = Sizes.cbHeader; // length of header Buffers[0].BufferType = SECBUFFER_STREAM_HEADER; // Type of the buffer Buffers[1].pvBuffer = pbMessage; // Pointer to buffer 2 Buffers[1].cbBuffer = cbMessage; // length of the message Buffers[1].BufferType = SECBUFFER_DATA; // Type of the buffer Buffers[2].pvBuffer = pbMessage + cbMessage; // Pointer to buffer 3 Buffers[2].cbBuffer = Sizes.cbTrailer; // length of the trailor Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER; // Type of the buffer Buffers[3].pvBuffer = SECBUFFER_EMPTY; // Pointer to buffer 4 Buffers[3].cbBuffer = SECBUFFER_EMPTY; // length of buffer 4 Buffers[3].BufferType = SECBUFFER_EMPTY; // Type of the buffer 4 Message.ulVersion = SECBUFFER_VERSION; // Version number Message.cBuffers = 4; // Number of buffers - must contain four SecBuffer structures. Message.pBuffers = Buffers; // Pointer to array of buffers scRet = EncryptMessage(phContext, 0, &Message, 0); // must contain four SecBuffer structures. if(FAILED(scRet)) { printf("**** Error 0x%x returned by EncryptMessage\n", scRet); return scRet; } if(scRet == SEC_E_CONTEXT_EXPIRED){ printf("SEC_E_CONTEXT_EXPIRED\n"); return scRet; } // Send the encrypted data to the server. cbData = ssl_default_callback_write(Socket, pbIoBuffer, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer); printf("%d bytes of encrypted data sent\n", cbData); return cbData; // send( Socket, pbIoBuffer, Sizes.cbHeader + strlen(pbMessage) + Sizes.cbTrailer, 0 ); } int ReadDecrypt(SOCKET Socket, PCredHandle phCreds, CtxtHandle *phContext, PBYTE pbIoBuffer, DWORD cbIoBufferLength, char * message, int messagesize) { SecBuffer ExtraBuffer; SecBuffer *pDataBuffer, *pExtraBuffer; SECURITY_STATUS scRet; // unsigned long cbBuffer; // Size of the buffer, in bytes SecBufferDesc Message; // unsigned long BufferType; // Type of the buffer (below) SecBuffer Buffers[4]; // void SEC_FAR * pvBuffer; // Pointer to the buffer DWORD cbIoBuffer, length; PBYTE buff; int free_mem = 0; int cbData,i; cbIoBuffer = 0; printf("\nread decrypt-Started"); if(ExtraDecBufferLen>0 && messagesize<ExtraDecBufferLen){ printf("\nFound Decrypted Data"); memcpy(message, ExtraDecBuff,messagesize); memmove(ExtraDecBuff,ExtraDecBuff+messagesize,ExtraDecBufferLen - messagesize);//Check this ExtraDecBufferSize ExtraDecBufferLen=ExtraDecBufferLen-messagesize; return messagesize; } if(context_expire==1){ return -1; } // Read data from server until done. while(TRUE) // Read some data. { if( ExtraEncBufferLen == 0 || scRet == SEC_E_INCOMPLETE_MESSAGE ) // get the data { if((ExtraEncBufferSize - ExtraEncBufferLen) < cbIoBufferLength) { if(ExtraEncBufferSize == 0) { ExtraEncBuff = malloc(cbIoBufferLength); ExtraEncBufferSize = cbIoBufferLength; printf("\nAllocated merory ExtraEncBufferSize <%d>",ExtraEncBufferSize); } else { ExtraEncBuff = realloc(ExtraEncBuff,cbIoBufferLength+ExtraEncBufferSize); ExtraEncBufferSize = ExtraEncBufferSize + cbIoBufferLength; } } cbData = ssl_default_callback_read(Socket, ExtraEncBuff + ExtraEncBufferLen, cbIoBufferLength - ExtraEncBufferLen); printf("\nafter read cbData is <%d>",cbData); if(cbData == SOCKET_ERROR) { printf("\n**** Error %d reading data from server", WSAGetLastError()); scRet = SEC_E_INTERNAL_ERROR; break; } else if(cbData == 0) // Server disconnected. { if(cbIoBuffer) { printf("\n**** Server unexpectedly disconnected"); scRet = SEC_E_INTERNAL_ERROR; return -1; } else break; // All Done } else // success { cbIoBuffer += cbData; printf("\nBefore updating ExtraEncBufferLen %d\n",ExtraEncBufferLen); ExtraEncBufferLen += cbData; printf("\nAfter updating ExtraEncBufferLen %d\n",ExtraEncBufferLen); } } // Decrypt the received data. Buffers[0].pvBuffer = ExtraEncBuff; Buffers[0].cbBuffer = ExtraEncBufferLen; Buffers[0].BufferType = SECBUFFER_DATA; // Initial Type of the buffer 1 Buffers[1].BufferType = SECBUFFER_EMPTY; // Initial Type of the buffer 2 Buffers[2].BufferType = SECBUFFER_EMPTY; // Initial Type of the buffer 3 Buffers[3].BufferType = SECBUFFER_EMPTY; // Initial Type of the buffer 4 Message.ulVersion = SECBUFFER_VERSION; // Version number Message.cBuffers = 4; // Number of buffers - must contain four SecBuffer structures. Message.pBuffers = Buffers; // Pointer to array of buffers scRet = DecryptMessage(phContext, &Message, 0, NULL); if( scRet == SEC_I_CONTEXT_EXPIRED ){ context_expire=1; break; } if( scRet != SEC_E_OK && scRet != SEC_I_RENEGOTIATE && scRet != SEC_I_CONTEXT_EXPIRED ) { printf("\n**** DecryptMessage"); DisplaySchannelError((DWORD)scRet); return -1; } // Locate data and (optional) extra buffers. pDataBuffer = NULL; pExtraBuffer = NULL; for(i = 1; i < 4; i++) { if( pDataBuffer == NULL && Buffers[i].BufferType == SECBUFFER_DATA ) pDataBuffer = &Buffers[i]; if( pExtraBuffer == NULL && Buffers[i].BufferType == SECBUFFER_EXTRA ) pExtraBuffer = &Buffers[i]; } if(pDataBuffer) { free_mem = ExtraDecBufferSize - ExtraDecBufferLen; if(free_mem < pDataBuffer->cbBuffer) { ExtraDecBuff = realloc(ExtraDecBuff,ExtraDecBufferSize + pDataBuffer->cbBuffer- free_mem); ExtraDecBufferSize=ExtraDecBufferSize + pDataBuffer->cbBuffer - free_mem; } memcpy(ExtraDecBuff+ExtraDecBufferLen,pDataBuffer->pvBuffer,pDataBuffer->cbBuffer); ExtraDecBufferLen=pDataBuffer->cbBuffer + ExtraDecBufferLen; printf("\nDecrypt mess %.*s\n",ExtraDecBufferLen,ExtraDecBuff); printf("\n ExtraDecBufferLen <%d> pDataBuffer->cbBuffer <%d>",ExtraDecBufferLen,pDataBuffer->cbBuffer); if(messagesize <= ExtraDecBufferLen) { printf("\nextra message decripted 2"); memcpy(message,ExtraDecBuff,messagesize); memmove(ExtraDecBuff,ExtraDecBuff+messagesize,ExtraDecBufferLen - messagesize); ExtraDecBufferLen=ExtraDecBufferLen-messagesize; // break; } } // Move any "extra" data to the input buffer. printf("\nDecrypted message pvBuffer : %.*s",pDataBuffer->cbBuffer,(char *)pDataBuffer->pvBuffer); if(pExtraBuffer && pExtraBuffer->cbBuffer > 0 ) { free_mem = ExtraEncBufferSize - ExtraEncBufferLen; if(ExtraEncBufferLen > pExtraBuffer->cbBuffer) { if(ExtraEncBufferSize < pExtraBuffer->cbBuffer) { printf("\nExtra ExtraEncBufferSize Before <%d>",ExtraEncBufferSize); ExtraEncBuff = realloc(ExtraEncBuff, pExtraBuffer->cbBuffer); ExtraEncBufferSize = pExtraBuffer->cbBuffer; printf("\nExtra ExtraEncBufferSize after <%d>",ExtraEncBufferSize); } //memmove(ExtraEncBuff,ExtraEncBuff + ExtraEncBufferLen - pExtraBuffer->cbBuffer, pExtraBuffer->cbBuffer ); memmove(ExtraEncBuff,pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer ); ExtraEncBufferLen = pExtraBuffer->cbBuffer; printf("\nAfter moving data %d",ExtraEncBufferLen); } } else { ExtraEncBufferLen = 0; } // The server wants to perform another handshake sequence. if(scRet == SEC_I_RENEGOTIATE) { printf("\nServer requested renegotiate!"); scRet = SSPINegotiateLoop(phCreds, Socket, phContext); if(scRet != SEC_E_OK) return -2; } if(scRet == SEC_E_INCOMPLETE_MESSAGE){ continue; } else{ break; } } // Loop till CRLF is found at the end of the data printf("\n%.16s",message); return messagesize; } int __cdecl main(void) { WSADATA wsaData; int iResult; CtxtHandle hContext; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; struct addrinfo *result = NULL; struct addrinfo hints; int iSendResult; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; char* message, message_same[3000]; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("\nWSAStartup failed with error: %d\n", iResult); return 1; } ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the server address and port iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("\ngetaddrinfo failed with error: %d\n", iResult); WSACleanup(); return 1; } CredHandle credHandle; int status=GetCertificateandCredHandle(&credHandle); if (status < 0) { printf("\nGetCertificateandCredHandle failed"); freeaddrinfo(result); WSACleanup(); return 1; } // Create a SOCKET for connecting to server ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { printf("\nsocket failed with error: %ld\n", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // Setup the TCP listening socket iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("\nbind failed with error: %d\n", WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } freeaddrinfo(result); iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("\nlisten failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // Accept a client socket ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { printf("\naccept failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } closesocket(ListenSocket); PCCERT_CONTEXT pRemoteCertContext = NULL; void **Token; SECURITY_STATUS Status ; // Receive until the peer shuts down the connection SSPINegotiateLoop(&credHandle, ClientSocket, &hContext ); Status = QuerySecurityContextToken(&hContext, Token); if(Status != SEC_E_OK) { printf("Error 0x%x QuerySecurityContextToken\n", Status); } PSecPkgInfoA *ppPackageInfo; Status = QuerySecurityPackageInfoA(L"schannel", ppPackageInfo); { printf("Error 0x%x QuerySecurityPackageInfoA\n", Status); } Status = ImpersonateSecurityContext(&hContext); if(Status != SEC_E_OK) { printf("Error 0x%x ImpersonateSecurityContext\n", Status); } Status = QuerySecurityContextToken(&hContext, Token); if(Status != SEC_E_OK) { printf("Error 0x%x QuerySecurityContextToken\n", Status); } Status = QueryContextAttributes(&hContext, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext); if(Status != SEC_E_OK) { printf("Error 0x%x querying remote certificate\n", Status); return -1; } SecPkgContext_StreamSizes Sizes; SECURITY_STATUS scRet; PBYTE pbIoBuffer; DWORD cbIoBufferLength, cbData; scRet = QueryContextAttributes( &hContext, SECPKG_ATTR_STREAM_SIZES, &Sizes ); if(scRet != SEC_E_OK) { printf("**** Error 0x%x reading SECPKG_ATTR_STREAM_SIZES\n", scRet); closesocket(ListenSocket); WSACleanup(); return 1; } // Create a buffer. cbIoBufferLength = Sizes.cbHeader + Sizes.cbMaximumMessage + Sizes.cbTrailer; pbIoBuffer = LocalAlloc(LMEM_FIXED, cbIoBufferLength); if(pbIoBuffer == NULL) { printf("**** Out of memory (2)\n"); closesocket(ListenSocket); WSACleanup(); return 1; } int recv_len=0; message=malloc(3000); int mess_len=2887; recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } mess_len=16; recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } char server_message[] ="server message 1"; message=server_message; server_send(message,ClientSocket, &hContext, Sizes); char server_message2[] ="server message 2"; message=server_message2; server_send(message,ClientSocket, &hContext, Sizes); char server_message3[] ="server message 3"; message=server_message3; server_send(message,ClientSocket, &hContext, Sizes); char server_message4[] ="server message 4"; message=server_message4; server_send(message,ClientSocket, &hContext, Sizes); recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } char server_message5[] ="server message 5"; message=server_message5; server_send(message,ClientSocket, &hContext, Sizes); char server_message6[] ="server message 6"; message=server_message6; server_send(message,ClientSocket, &hContext, Sizes); recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } char server_message7[] ="server message 7"; message=server_message7; server_send(message,ClientSocket, &hContext, Sizes); recv_len = ReadDecrypt( ClientSocket, &credHandle, &hContext, pbIoBuffer, cbIoBufferLength ,message_same,mess_len); if(recv_len > 0){ printf("\nReceived mess length id:%d\n",recv_len); } else{ printf("something went wrong in read decrypt\n"); } char server_message8[] ="server message 8"; message=server_message8; server_send(message,ClientSocket, &hContext, Sizes); // shutdown the connection since we're done if(DisconnectFromClient(ClientSocket, &credHandle, &hContext)) { printf("Error disconnecting from Client\n"); } printf("----- Disconnected From Client\n"); // cleanup closesocket(ClientSocket); WSACleanup(); return 0; }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue