diff --git a/mozilla/minimo/components/ssl/nsNativeSSL.cpp b/mozilla/minimo/components/ssl/nsNativeSSL.cpp index b55416585c8..3e4f28c631a 100755 --- a/mozilla/minimo/components/ssl/nsNativeSSL.cpp +++ b/mozilla/minimo/components/ssl/nsNativeSSL.cpp @@ -30,6 +30,21 @@ static SSL_CRACK_CERTIFICATE_FN gSslCrackCertificate = 0 ; static SSL_FREE_CERTIFICATE_FN gSslFreeCertificate = 0 ; static HINSTANCE gSchannel = NULL ; +static PRDescIdentity nsWINCESSLIOLayerIdentity; +static PRIOMethods nsWINCESSLIOLayerMethods; + + +void MessageBoxWSAError(const char * msg) +{ + char buffer[100]; + int error = WSAGetLastError(); + if (error == 0) + return; + + sprintf(buffer, "%s error is: %d", msg, error); + MessageBox(0, buffer, buffer, MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND); +} + class nsWINCESSLSocketProvider : public nsISocketProvider { public: @@ -55,13 +70,16 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSITRANSPORTSECURITYINFO - void Init(const char *destinationHost, const char *proxyHost, PRInt32 proxyPort) + nsresult Init(const char *destinationHost, const char *proxyHost, PRInt32 proxyPort) { mDestinationHost = destinationHost; mProxyHost = proxyHost; mProxyPort = proxyPort; + + return NS_OK; }; + SOCKET mSocket; nsCString mDestinationHost; nsCString mProxyHost; PRInt32 mProxyPort; @@ -144,7 +162,10 @@ static int SSLValidationHook(DWORD dwType, LPVOID pvArg, DWORD dwChainLen, LPBLO } if (!gSslCrackCertificate || !gSslFreeCertificate) + { + MessageBox(0, "Could not find the right stuff in the default security library", "schannel.dll", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND); return SSL_ERR_BAD_DATA; + } } X509Certificate * cert = 0; @@ -204,6 +225,158 @@ static int SSLValidationHook(DWORD dwType, LPVOID pvArg, DWORD dwChainLen, LPBLO return res; } + +struct sockaddr * +nspr2winsock(const PRNetAddr *addr, int *len) +{ + struct sockaddr_in *ws = (struct sockaddr_in*) malloc(sizeof(*ws)); + if (!ws) + return NULL; + + memset(ws, 0, sizeof(*ws)); + + // family + ws->sin_family = AF_INET; + + // ip + memcpy(&ws->sin_addr, &addr->inet.ip, sizeof(ws->sin_addr)); + + // port + ws->sin_port = addr->inet.port; + + *len = sizeof(*ws); + return (struct sockaddr *)ws; +} + +static PRStatus PR_CALLBACK +nsWINCESSLIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime /*timeout*/) +{ + nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret; + if (info == NULL) + return PR_FAILURE; + + SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (!s) + { + MessageBox(0, "Failed to create a socket", "connect()", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND); + return PR_FAILURE; + } + + info->mSocket = s; + + // set the socket to secure mode + DWORD dwFlag = SO_SEC_SSL ; + DWORD error = setsockopt (s, SOL_SOCKET, SO_SECURE, (char *)&dwFlag, sizeof(dwFlag)); + if (error != 0) + { + MessageBox(0, "Failed to setsockopt", "connect()", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND); + return PR_FAILURE; + } + + // set the certificate validation callback. + SSLVALIDATECERTHOOK sslHook ; + sslHook.HookFunc = SSLValidationHook; + + NS_ADDREF(info); + sslHook.pvArg = (void *) info; // XXXX Leak! what is the lifespan of this? + + if ( WSAIoctl (s, + SO_SSL_SET_VALIDATE_CERT_HOOK, + &sslHook, + sizeof sslHook, + NULL, + 0, + NULL, + NULL, + NULL) ) + { + MessageBox(0, "SO_SSL_SET_VALIDATE_CERT_HOOK", "connect()", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND); + return PR_FAILURE; + } + + int len; + struct sockaddr* ws = nspr2winsock(addr, &len); + if (!ws) + return PR_FAILURE; + + int result = connect(s, ws, len); + + if (result == 0) + return PR_SUCCESS; + + MessageBoxWSAError("connect()"); + + return PR_FAILURE; +} + +static PRStatus PR_CALLBACK +nsWINCESSLIOLayerClose(PRFileDesc *fd) +{ + nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret; + PRDescIdentity id = PR_GetLayersIdentity(fd); + + if (info && id == nsWINCESSLIOLayerIdentity) + { + NS_RELEASE(info); + fd->identity = PR_INVALID_IO_LAYER; + } + + // closesocket(info->mSocket); + // NS_RELEASE(info); + // fd->secret = nsnull; + + return PR_SUCCESS; +} + + + +static PRInt32 PR_CALLBACK +nsWINCESSLIOLayerAvailable(PRFileDesc *fd) +{ + MessageBox(0, "available.", "available.", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND); + return 1; +} + +static PRInt32 PR_CALLBACK +nsWINCESSLIOLayerRead(PRFileDesc* fd, void* buf, PRInt32 amount) +{ + nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret; + if (info == NULL) + return PR_OUT_OF_MEMORY_ERROR; + + WSASetLastError (0) ; + PRInt32 rv = recv(info->mSocket, (char*)buf, amount, 0); + MessageBoxWSAError("read"); + + return rv; +} + +static PRInt32 PR_CALLBACK +nsWINCESSLIOLayerWrite(PRFileDesc* fd, const void* buf, PRInt32 amount) +{ + nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret; + if (info == NULL) + return PR_OUT_OF_MEMORY_ERROR; + + WSASetLastError (0) ; + PRInt32 rv = send(info->mSocket, (char*)buf, amount, 0); + MessageBoxWSAError("write"); + + return rv; +} + + +static PRInt16 PR_CALLBACK nsWINCESSLIOLayerPoll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) +{ + nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret; + if (info == NULL) + return PR_OUT_OF_MEMORY_ERROR; + + *out_flags = PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT; + return 1; +} + + NS_IMPL_THREADSAFE_ISUPPORTS1(nsWINCESSLSocketProvider, nsISocketProvider) NS_IMETHODIMP @@ -216,48 +389,56 @@ nsWINCESSLSocketProvider::NewSocket(PRInt32 family, PRFileDesc **result, nsISupports **socksInfo) { - SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - - if (!s) - return NS_ERROR_SOCKET_CREATE_FAILED; + static PRBool firstTime = PR_TRUE; + if (firstTime) { + + nsWINCESSLIOLayerIdentity = PR_GetUniqueIdentity("WINCESSL layer"); + nsWINCESSLIOLayerMethods = *PR_GetDefaultIOMethods(); + + nsWINCESSLIOLayerMethods.connect = nsWINCESSLIOLayerConnect; + nsWINCESSLIOLayerMethods.close = nsWINCESSLIOLayerClose; + nsWINCESSLIOLayerMethods.available = nsWINCESSLIOLayerAvailable; + nsWINCESSLIOLayerMethods.write = nsWINCESSLIOLayerWrite; + nsWINCESSLIOLayerMethods.read = nsWINCESSLIOLayerRead; + nsWINCESSLIOLayerMethods.poll = nsWINCESSLIOLayerPoll; + firstTime = PR_FALSE; + } + + PRFileDesc *fd = PR_OpenTCPSocket(family); + if (!fd) + return NS_ERROR_OUT_OF_MEMORY; + + PRFileDesc * layer; + PRStatus rv; + + layer = PR_CreateIOLayerStub(nsWINCESSLIOLayerIdentity, &nsWINCESSLIOLayerMethods); + if (! layer) + return NS_ERROR_UNEXPECTED; + nsWINCESSLSocketInfo * infoObject = new nsWINCESSLSocketInfo(); if (!infoObject) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(infoObject); + + layer->secret = (PRFilePrivate*) infoObject; + rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer); + if (NS_FAILED(rv)) + return NS_ERROR_UNEXPECTED; + + + nsresult initrv = infoObject->Init(host, proxyHost, proxyPort); + if (NS_FAILED(initrv)) { - closesocket(s); + MessageBox(0, "Can not create ssl socket.", "Can not create ssl socket.", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND); return NS_ERROR_FAILURE; } - NS_ADDREF(infoObject); - - infoObject->Init(host, proxyHost, proxyPort); - - // set the socket to secure mode - DWORD dwFlag = SO_SEC_SSL ; - if ( setsockopt (s, SOL_SOCKET, SO_SECURE, (char *)&dwFlag, sizeof(dwFlag)) ) - goto loser; - - // set the certificate validation callback. - SSLVALIDATECERTHOOK sslHook ; - sslHook.HookFunc = SSLValidationHook; - - NS_ADDREF(infoObject); - sslHook.pvArg = (void *) infoObject; // XXXX Leak! what is the lifespan of this? - - if ( WSAIoctl (s, SO_SSL_SET_VALIDATE_CERT_HOOK, &sslHook, sizeof sslHook, NULL, 0, NULL, NULL, NULL) ) - goto loser; - - *result = PR_ImportTCPSocket(s); - - if (!*result) - goto loser; + *result = fd; *socksInfo = (nsISupports*) (nsITransportSecurityInfo*) infoObject; return NS_OK; - loser: - closesocket(s); - NS_RELEASE(infoObject); - return NS_ERROR_SOCKET_CREATE_FAILED; } NS_IMETHODIMP