SSL_Connect sys call taking more time
Hi all, I have a daemon where I am trying to retrieve the common name from the certificate during an HTTPS connection. What i am observing is that , SSL_Connect() function is taking more time to connect on some of the websites. I am trying on Mac OS X 10.8.3. Below is the code I have been using and I am using non-blocking sockets #include SSLUtil.h #include sys/socket.h #include sys/types.h #include netinet/in.h #include arpa/inet.h #include strings.h #include openssl/ssl.h #include openssl/x509.h #include openssl/crypto.h #include errno.h #include fcntl.h #include string #include Logging.h bool SSLUtil::GetSSLServerNameFromIP(std::string ipAddress, std::string serverName) { bool bRet = false; int sock=-1; MCLOG(SSLUtil::GetSSLServerNameFromIP Call for IP,ipAddress.c_str()); if(ConnectToServerAsync(ipAddress,443,sock)) { if(RetrieveNameUsingSSL(sock,serverName)) { bRet = true; MCLOG(SSLUtil::GetSSLServerNameFromIP Call return,ipAddress.c_str(),serverName.c_str()); } else { MCLOG(SSLUtil::GetSSLServerNameFromIP RetrieveNameUsingSSL call failed,ipAddress.c_str()); } close(sock); }else { MCLOG(SSLUtil::GetSSLServerNameFromIP connect asycn failed,ipAddress.c_str()); } return bRet; } #define TIMEOUT_SERVER 3 //seconds bool SSLUtil::ConnectToServerAsync(std::string ipaddress, int port , int sock) { //create the socket sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(sock0) { //creating socket failed MCLOG(SSLUtil::ConnectToServerAsync soceket creation failed ); return false; } //change socket options int opts = fcntl(sock,F_GETFL); if (opts 0) { //pFailed F_GETFL MCLOG(SSLUtil::ConnectToServerAsync F_GETFL failed ); return false; } opts = (opts | O_NONBLOCK); if (fcntl(sock,F_SETFL,opts) 0) { //Failed F_SETFL MCLOG(SSLUtil::ConnectToServerAsync F_SETFL failed); return false; } //make sure there is no error pending int err = errno; if (err 0) { MCLOG(SSLUtil::ConnectToServerAsync can't create non blocking socket ); //printf(MakeConnectAttempt = can't set non-blocking socket); if(sock) { close(sock); } return false; } struct sockaddr_in server_addr; memset (server_addr, '\0', sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port= htons(port); /* Server Port number */ server_addr.sin_addr.s_addr = inet_addr(ipaddress.c_str()); /* Server IP */ int status = connect(sock, (struct sockaddr*) server_addr, sizeof(server_addr)); //wait for connection to succeed if(status0) { status = errno; if(status == EINPROGRESS) { MCLOG(SSLUtil::ConnectToServerAsync in progress , ipaddress.c_str()); if(!WaitOnSocket(sock,TIMEOUT_SERVER)) { //printf(connect to %s failed\n,argv[1]); MCLOG(SSLUtil::ConnectToServerAsync wait failed , ipaddress.c_str()); return false; } }else { //printf(connect to %s failed\n,argv[1]); MCLOG(SSLUtil::ConnectToServerAsync connect failed , status); return false; } } MCLOG(SSLUtil::ConnectToServerAsync connect success , status); return true; } bool SSLUtil::WaitOnSocket(int sockfd,int timeOutInSeconds) { fd_set readFDs; fd_set writeFDs; intselectResult; // booltimeOut = false; FD_ZERO(readFDs); FD_ZERO(writeFDs); FD_SET(sockfd, readFDs); FD_SET(sockfd, writeFDs); bool continueSelect ; struct timeval waitd; time_t seconds; time_t future; time_t now; seconds = time(NULL); future = seconds + timeOutInSeconds; // waitd.tv_sec = timeOutInSeconds; // Make select wait up to 10 seconds for data // waitd.tv_usec = 0; // and 0 milliseconds. int err = 0; continueSelect = true; do { waitd.tv_sec = timeOutInSeconds; // Make select wait up to 5 seconds for data waitd.tv_usec = 0; // and 0 milliseconds. selectResult = select(sockfd+1, readFDs, writeFDs, NULL, waitd); //printf(after select %d\n, selectResult); err = errno; if (selectResult 0) { for(int i=0;isockfd+1;i++) { if (FD_ISSET(i,readFDs)) { continueSelect = false; break; } if (FD_ISSET(i,writeFDs)) { continueSelect = false; break; } } } else { now = time(NULL); if (now future ) {
Re: SSL_Connect call gives SSL_ERROR_WANT_READ for non blocking sockets
Ohh .. ok. But I just want the SSL_connect to succeed because I want to fetch the certificate of an HTTPS website. So after the success of SSL_connect() function, I would call SSL_get_peer_certificate(). Since I wait until the SSL_connect() function succeeds I wanted to know if there is a better approach. Hope I am able to convey my understandings for these functions. If you feel that I dont, please help in understanding the same. ~Arjun On Mon, Nov 21, 2011 at 8:10 PM, Michael S. Zick open...@morethan.orgwrote: On Mon November 21 2011, Arjun SM wrote: Well yes, these are not errors. My bad for naming the variable as 'error'. Not my point - Your logic shows that you think the connection has failed when it has simple not yet finished with its protocol. Not finished because you didn't respond to the want-write and/or want-read. Something which your code must do when using non-blocking sockets. Mike ~Arjun On Thu, Nov 17, 2011 at 11:50 PM, Michael S. Zick open...@morethan.org wrote: On Thu November 17 2011, Arjun SM wrote: Hi, Thanks for the reply. I have called the ssl_connect() function again after checking for SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE. But I wanted to know if I can optimize my code. Below is my code int counter = 6; while (status 0 --counter 0 ) { if(status 0) { error=SSL_get_error(ssl,status); if(error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) { MessageLog.Write(SSL 1st Connect error , error); But these two cases are __not__ errors, you just need to 'read' or 'write' as indicated so the protocol can advance. Mike usleep(200); status = SSL_connect(ssl); error=SSL_get_error(ssl,status); MessageLog.Write(SSL 2nd Connect error , error); } else { break; } } } // end of while I would try for some time and break out saying unable to connect. I am sure I can optimize this code by using select() but I am unable to make it work. If there is a better approach please do share. ~Arjun On Tue, Nov 15, 2011 at 9:04 PM, Huaqing Wang whuaq...@gmail.com wrote: Hi, Arjun, For non-blocking case, you have to handle SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE In that case you need to redo *SSL_connect.* * * Huaqing On Tue, Nov 15, 2011 at 5:51 AM, Arjun SM arjun...@gmail.com wrote: Hi all, I am newbie to openssl any help is greatly appreciated. I have a requirement of fetching the Common name (domin name ) from the certificate that I request from any HTTPS websites. I followed the regular method of 1. establish a connection with the ip address using *connect() *system call. 2. Use *SSL_connect()* system call to perform handshake. 3. Use *SSL_get_peer_certificate()* to get the certificate. The problem I faced was that, the connect() call would at times return a errno 4 (EINTR) error . So i changed code from blocking to non-blocking sockets and used select() call to have a valid connection and return an appropriate file descriptor. Now the ssl_connect() call returns SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE error. I am unable to make my code work by adding a select() even on ssl_connect() call. If any one can please help as to how I need to use the ssl_connect() by polling that would be of great help. preferred language would be C/C++ thanks, ~Arjun -- Thank you. Best Regards, Michael(Huaqing) Wang __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager majord...@openssl.org __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager majord...@openssl.org
Re: SSL_Connect call gives SSL_ERROR_WANT_READ for non blocking sockets
Well yes, these are not errors. My bad for naming the variable as 'error'. ~Arjun On Thu, Nov 17, 2011 at 11:50 PM, Michael S. Zick open...@morethan.orgwrote: On Thu November 17 2011, Arjun SM wrote: Hi, Thanks for the reply. I have called the ssl_connect() function again after checking for SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE. But I wanted to know if I can optimize my code. Below is my code int counter = 6; while (status 0 --counter 0 ) { if(status 0) { error=SSL_get_error(ssl,status); if(error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) { MessageLog.Write(SSL 1st Connect error , error); But these two cases are __not__ errors, you just need to 'read' or 'write' as indicated so the protocol can advance. Mike usleep(200); status = SSL_connect(ssl); error=SSL_get_error(ssl,status); MessageLog.Write(SSL 2nd Connect error , error); } else { break; } } } // end of while I would try for some time and break out saying unable to connect. I am sure I can optimize this code by using select() but I am unable to make it work. If there is a better approach please do share. ~Arjun On Tue, Nov 15, 2011 at 9:04 PM, Huaqing Wang whuaq...@gmail.com wrote: Hi, Arjun, For non-blocking case, you have to handle SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE In that case you need to redo *SSL_connect.* * * Huaqing On Tue, Nov 15, 2011 at 5:51 AM, Arjun SM arjun...@gmail.com wrote: Hi all, I am newbie to openssl any help is greatly appreciated. I have a requirement of fetching the Common name (domin name ) from the certificate that I request from any HTTPS websites. I followed the regular method of 1. establish a connection with the ip address using *connect() *system call. 2. Use *SSL_connect()* system call to perform handshake. 3. Use *SSL_get_peer_certificate()* to get the certificate. The problem I faced was that, the connect() call would at times return a errno 4 (EINTR) error . So i changed code from blocking to non-blocking sockets and used select() call to have a valid connection and return an appropriate file descriptor. Now the ssl_connect() call returns SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE error. I am unable to make my code work by adding a select() even on ssl_connect() call. If any one can please help as to how I need to use the ssl_connect() by polling that would be of great help. preferred language would be C/C++ thanks, ~Arjun -- Thank you. Best Regards, Michael(Huaqing) Wang __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager majord...@openssl.org
Re: SSL_Connect call gives SSL_ERROR_WANT_READ for non blocking sockets
Hi, Thanks for the reply. I have called the ssl_connect() function again after checking for SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE. But I wanted to know if I can optimize my code. Below is my code int counter = 6; while (status 0 --counter 0 ) { if(status 0) { error=SSL_get_error(ssl,status); if(error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) { MessageLog.Write(SSL 1st Connect error , error); usleep(200); status = SSL_connect(ssl); error=SSL_get_error(ssl,status); MessageLog.Write(SSL 2nd Connect error , error); } else { break; } } } // end of while I would try for some time and break out saying unable to connect. I am sure I can optimize this code by using select() but I am unable to make it work. If there is a better approach please do share. ~Arjun On Tue, Nov 15, 2011 at 9:04 PM, Huaqing Wang whuaq...@gmail.com wrote: Hi, Arjun, For non-blocking case, you have to handle SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE In that case you need to redo *SSL_connect.* * * Huaqing On Tue, Nov 15, 2011 at 5:51 AM, Arjun SM arjun...@gmail.com wrote: Hi all, I am newbie to openssl any help is greatly appreciated. I have a requirement of fetching the Common name (domin name ) from the certificate that I request from any HTTPS websites. I followed the regular method of 1. establish a connection with the ip address using *connect() *system call. 2. Use *SSL_connect()* system call to perform handshake. 3. Use *SSL_get_peer_certificate()* to get the certificate. The problem I faced was that, the connect() call would at times return a errno 4 (EINTR) error . So i changed code from blocking to non-blocking sockets and used select() call to have a valid connection and return an appropriate file descriptor. Now the ssl_connect() call returns SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE error. I am unable to make my code work by adding a select() even on ssl_connect() call. If any one can please help as to how I need to use the ssl_connect() by polling that would be of great help. preferred language would be C/C++ thanks, ~Arjun -- Thank you. Best Regards, Michael(Huaqing) Wang
SSL_Connect call gives SSL_ERROR_WANT_READ for non blocking sockets
Hi all, I am newbie to openssl any help is greatly appreciated. I have a requirement of fetching the Common name (domin name ) from the certificate that I request from any HTTPS websites. I followed the regular method of 1. establish a connection with the ip address using *connect() *system call. 2. Use *SSL_connect()* system call to perform handshake. 3. Use *SSL_get_peer_certificate()* to get the certificate. The problem I faced was that, the connect() call would at times return a errno 4 (EINTR) error . So i changed code from blocking to non-blocking sockets and used select() call to have a valid connection and return an appropriate file descriptor. Now the ssl_connect() call returns SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE error. I am unable to make my code work by adding a select() even on ssl_connect() call. If any one can please help as to how I need to use the ssl_connect() by polling that would be of great help. preferred language would be C/C++ thanks, ~Arjun