Hello All, I can not connect to a HTTPS server of WebServices. ( https://hnfe.sefaz.es.gov.br/Nfe/wsdl/nfeStatusServico.wsdl)
The error occurs when the function SSL_read() is calling, returning 0 and SSL_get_error () equals SSL_ERROR_ZERO_RETURN. The problem is not the certificates, because when installing in firefox/IE to view the WSDL in the browser, its ok. Using ethereal, there was 1 extra handshake between this sample and firefox/IE. I created a simple program for example that reproduces the problem. #include <stdio.h> #include <winsock2.h> #include <ws2tcpip.h> #include <windows.h> #include <openssl/x509.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/pem.h> #include <openssl/rand.h> #define DEFAULT_FAMILY AF_INET #define DEFAULT_SOCKTYPE SOCK_STREAM #define DEFAULT_PORT "443" static unsigned char dh512_p[]={ 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, 0x47,0x74,0xE8,0x33, }; static unsigned char dh512_g[]={ 0x02, }; SOCKET sock = INVALID_SOCKET; int chkSSL(int AError, SSL *s, BIO *bio_e); DH *GetDH512(void); int myReceiveLine( SSL *ssl, char *data, int maxDataLen, int timeOut); bool WaitForReceive(long secs,long uSecs); //------------------------------------------------------------------ int main(int argc, char **argv) { ADDRINFO Hints, *AddrInfo = NULL, *AI; WSADATA wsaData; int nFamily = DEFAULT_FAMILY; int nSockType = DEFAULT_SOCKTYPE; char szRemoteAddrString[128]; char szRemoteName[64]; char *szPort = DEFAULT_PORT; char scommand[512]; // VARIAVEIS SSL int nServerVerify; int nServerSessionIdContext; char szCertificate[256]; SSL *ssl=NULL; SSL_CTX *ctx=NULL; SSL_METHOD *meth=NULL; BIO *sslBio; BIO *sslErr; if(argc < 5){ printf("Usage:\n sample <HOST> <PORT> <CERTPEMPATH> <PASSPHRASE>"); return(0); } if(WSAStartup(MAKEWORD(2,2), &wsaData)){ printf("ERROR: WSAStartup failed"); goto Cleanup; } strncpy(szRemoteName, argv[1], sizeof(szRemoteName)); szRemoteName[63] = '\0'; printf("Communicating with server - %hs\r\n", szRemoteName); printf("Communicating with port - %hs\r\n", szPort); memset(&Hints, 0, sizeof(Hints)); Hints.ai_family = nFamily; Hints.ai_socktype = nSockType; if(getaddrinfo(szRemoteName, szPort, &Hints, &AddrInfo) != 0){ printf("ERROR: Couldn't get resolve the server name/address!"); goto Cleanup; } AI = AddrInfo; if (AI == NULL) { printf("ERROR: Unable to connect to any of the server's addresses!"); goto Cleanup; } if(AI->ai_family == DEFAULT_FAMILY) { sock = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol); if (sock != INVALID_SOCKET) { if(connect(sock, AI->ai_addr, AI->ai_addrlen) == SOCKET_ERROR) { // Connect failed, let's close this socket and try again on the next address in the list printf("FAIL: Failed to connect"); closesocket(sock); } } if (getnameinfo(AI->ai_addr, AI->ai_addrlen, szRemoteAddrString, sizeof(szRemoteAddrString), NULL, 0, NI_NUMERICHOST) != 0) strcpy(szRemoteAddrString, ""); printf("Succeeded Conected with the server: %hs", szRemoteAddrString); } else printf("INVALID: Failed to connect with %hs", AI->ai_addr->sa_data); nServerVerify = SSL_VERIFY_NONE; nServerSessionIdContext = 1; //-----------START INITIALIZE HANDSHAKE-------------------------- SSL_load_error_strings(); SSL_library_init(); sslErr = BIO_new_file("ssl.log","a"); meth=SSLv3_client_method(); ctx = SSL_CTX_new(meth); SSL_CTX_set_quiet_shutdown(ctx,1); int nOffProtocol = 0; nOffProtocol |= SSL_OP_NO_SSLv2; nOffProtocol |= SSL_OP_NO_TLSv1; SSL_CTX_set_options(ctx, nOffProtocol); SSL_CTX_sess_set_cache_size(ctx, 2); SSL_CTX_set_session_id_context(ctx, (const unsigned char*)&nServerSessionIdContext, sizeof(nServerSessionIdContext)); strncpy(szCertificate, argv[3], sizeof(szCertificate)); szRemoteName[255] = '\0'; if( SSL_CTX_use_certificate_file(ctx, szCertificate, SSL_FILETYPE_PEM) <= 0){ printf( "ERROR: unable to get certificate from '%s'\n", argv[3]); ERR_print_errors(sslErr); goto Cleanup; } SSL_CTX_set_default_passwd_cb_userdata(ctx, argv[4]); if (SSL_CTX_use_PrivateKey_file(ctx, szCertificate, SSL_FILETYPE_PEM) <= 0){ printf("ERROR: unable to get private key from '%s'\n",argv[3]); ERR_print_errors(sslErr); goto Cleanup; } if (!SSL_CTX_check_private_key(ctx)){ printf( "ERROR: Private key does not match the certificate public key\n"); goto Cleanup; } SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL); if ((!SSL_CTX_load_verify_locations(ctx, szCertificate, 0)) || (!SSL_CTX_set_default_verify_paths(ctx))){ printf( "ERROR: not load verify locations\n"); goto Cleanup; } /* DH OPTIONS */ DH *dh = GetDH512(); BIO_flush(sslErr); SSL_CTX_set_tmp_dh(ctx, dh); DH_free(dh); ssl = SSL_new(ctx); chkSSL(SSL_clear(ssl),ssl,sslErr); sslBio = BIO_new_socket(sock,BIO_NOCLOSE); SSL_set_bio(ssl, sslBio, sslBio); //------------END INITIALIZE HANDSHAKE-------------------------- SSL_set_connect_state(ssl); int retCon = 0; retCon = chkSSL(SSL_connect(ssl), ssl, sslErr); if ( retCon < 0){ printf("ERROR: Failed to connect with SSL"); goto Cleanup; } if (SSL_ctrl(ssl,SSL_CTRL_GET_FLAGS,0,NULL) & TLS1_FLAGS_TLS_PADDING_BUG ){ printf( "ERROR: Peer has incorrect TLSv1 block padding\n"); goto Cleanup; } // ops, test program.... strncpy(scommand, "GET /Nfe/wsdl/nfeStatusServico.wsdl HTTP/1.1\r\nHost: hnfe.sefaz.es.gov.br\r\nConnection: Keep-Alive\r\nAccept: */*\r\n", sizeof(szCertificate)); scommand[511] = '\0'; int iResult = send( sock, scommand, (int)strlen(scommand), 0 ); if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError()); goto Cleanup; } char pTemp[16384]; iResult = myReceiveLine( ssl, pTemp, 2048, 120 ); if( iResult < 12 ){ printf("ERROR: Invalid HTTP Connection"); goto Cleanup; }; // HTTP/1.0 200 OK // ops!! receive ZERO Cleanup: BIO_free(sslErr); BIO_free(sslBio); closesocket(sock); WSACleanup(); SSL_shutdown(ssl); return(1); } //================================================================================= bool WaitForReceive(long secs,long uSecs) { fd_set readSet; struct timeval tv; tv.tv_sec = secs; tv.tv_usec =uSecs; if( sock==INVALID_SOCKET ) return false; FD_ZERO(&readSet); FD_SET(sock,&readSet); // Wait up to the specified time to see if data is avail if( select(sock+1,&readSet,NULL,NULL,&tv) != 1) return false; return true; } int myReceive( SSL *ssl, void *data, unsigned int len, int flags, int timeOut ) { int rcv = 0; if(timeOut > 0) if( !SSL_pending(ssl) && !WaitForReceive(timeOut,0) ) return 0; do { int tmp = SSL_read(ssl,(char *)data+rcv, len-rcv); rcv += tmp; int x = SSL_get_error(ssl, tmp); switch (x) { case SSL_ERROR_NONE: //#ifdef CHARSET_EBCDIC ascii2ebcdic(buf,buf,i); #endif break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: rcv = 0; tmp = SSL_peek(ssl, (char *)data+rcv, len-rcv); if (tmp > 0) { int tmp = SSL_read(ssl,(char *)data+rcv, len-rcv); rcv += tmp; } break; case SSL_ERROR_WANT_X509_LOOKUP: break; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: rcv = -1; break; case SSL_ERROR_ZERO_RETURN: rcv = -1; break; } } while (rcv >= 0 && ((len-rcv) >0) && SSL_pending(ssl)); return rcv; } int myReceiveLine( SSL *ssl, char *data, int maxDataLen, int timeOut) { int rt, count = 0; char *dataPtr = NULL; memset(data, 0, maxDataLen); maxDataLen--; while (maxDataLen > 0) { dataPtr = &data[count]; rt = myReceive(ssl,(char *) dataPtr, 1, 0, timeOut); if (rt == 1) { maxDataLen--; count++; if (*dataPtr == '\r') { dataPtr = &data[count]; rt = myReceive(ssl,(char *) dataPtr, 1, 0, 0); if (rt == 1) { maxDataLen--; count++; if (*dataPtr == '\n') return count; } else if (rt <= 0) return count; } } else if (rt <= 0) return count; } return count; } DH * GetDH512(void) { DH *dh = NULL; if ((dh=DH_new()) == NULL) return(NULL); dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL); dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL); if ((dh->p == NULL) || (dh->g == NULL)) return(NULL); return(dh); } int ShowSSLError(int AError, SSL *s, BIO *bio_e) { char cAux[1024]; int x = SSL_get_error(s, AError); if( x != 5 ) { printf("**** SSL erro = %d\n", AError); printf(" SSL code = %d\n", x); ERR_error_string(x, cAux); printf(" %s\n", cAux); }; return AError; } int chkSSL(int AError, SSL *s, BIO *bio_e) { if (AError < 0) ShowSSLError(AError, s, bio_e); return AError; } thanks in advanced!! Ricardo