You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

client.cpp 6.6 KiB

11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
10 jaren geleden
11 jaren geleden
11 jaren geleden
10 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
10 jaren geleden
11 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /******************************************************************************/
  2. /**
  3. \Author Krzysztof Kwiatkowski
  4. \File client.cpp
  5. \Description The SSL client which connects to the server.cpp
  6. and initiates renegotitaion after RENEG_INIT_LEN
  7. chars exchanged with the server
  8. *******************************************************************************/
  9. #include "client.h"
  10. #include <unistd.h>
  11. #include "defs.h"
  12. #include <sys/socket.h>
  13. #include <arpa/inet.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #include <iostream>
  18. #include <netinet/in.h>
  19. #include <boost/thread/thread.hpp>
  20. #include <boost/thread/mutex.hpp>
  21. #include <boost/thread/locks.hpp>
  22. #include <fcntl.h>
  23. #include <openssl/err.h>
  24. using namespace std;
  25. using namespace boost;
  26. SSL* SSLHandler = 0;
  27. int CharsRead = 0;
  28. // with this you can block sender thread during renegotiation
  29. mutex WriteReadMutex;
  30. bool handle_error_code(int& len, SSL* SSLHandler, int code, const char* func)
  31. {
  32. switch( SSL_get_error( SSLHandler, code ) )
  33. {
  34. case SSL_ERROR_NONE:
  35. len+=code;
  36. return false;
  37. case SSL_ERROR_ZERO_RETURN:
  38. cout << "CONNETION CLOSE ON WRITE" << endl;
  39. break;
  40. case SSL_ERROR_WANT_READ:
  41. cout << func << " WANT READ" << endl;
  42. return true;
  43. break;
  44. case SSL_ERROR_WANT_WRITE:
  45. cout << func << " WANT WRITE" << endl;
  46. return true;
  47. break;
  48. case SSL_ERROR_SYSCALL:
  49. cout << func << " ESYSCALL" << endl;
  50. // exit(1);
  51. break;
  52. case SSL_ERROR_SSL:
  53. cout << func << " ESSL" << endl;
  54. return true;
  55. exit(1);
  56. break;
  57. default:
  58. cout << func << " SOMETHING ELSE" << endl;
  59. return true;
  60. exit(1);
  61. }
  62. return true;
  63. }
  64. void Sender()
  65. {
  66. while(1)
  67. {
  68. string buf(EXCHANGE_STRING);
  69. int len = 0;
  70. do
  71. {
  72. while( 1 )
  73. {
  74. lock_guard<mutex> lock(WriteReadMutex);
  75. cout << "SSL_write: start" << endl;
  76. int code = SSL_write(SSLHandler, buf.c_str()+len, buf.size()-len);
  77. // cout << "SSL_write: stop" << endl;
  78. handle_error_code(len, SSLHandler, code, "SSL_write");
  79. }
  80. // for debugging re-neg
  81. cout << "SSL STATE: " << SSL_state_string(SSLHandler) << endl;
  82. } while( len != static_cast<int>(buf.size()) );
  83. sleep(10);
  84. }
  85. };
  86. void Client::receive()
  87. {
  88. char buf[MAX_PACKET_SIZE];
  89. // TODO: this way it takes 100% CPU, some signal would be usefull
  90. memset(buf,'\0',MAX_PACKET_SIZE);
  91. int len_rcv = 0;
  92. {
  93. bool flag = 1;
  94. while( flag )
  95. {
  96. lock_guard<mutex> lock(WriteReadMutex);
  97. // cout << "SSL_read: start" << endl;
  98. len_rcv = SSL_read(SSLHandler, buf, MAX_PACKET_SIZE);
  99. // cout << "SSL_read: stop" << endl;
  100. flag = handle_error_code(len_rcv, SSLHandler, len_rcv, "SSL_read");
  101. if( !flag )
  102. flag = SSL_pending(SSLHandler);
  103. cout << "PENDING: " << flag << endl;
  104. }
  105. }
  106. if( len_rcv != 0 )
  107. {
  108. CharsRead += len_rcv;
  109. // dirty thing - if it has \n on the end - remove it
  110. if( buf[len_rcv-1] == '\n' )
  111. buf[len_rcv-1] = '\0';
  112. cout << "RCVD: " << buf << endl;
  113. }
  114. else
  115. {
  116. cout << "Closing connection " << _handler << endl;
  117. ::close(_handler);
  118. }
  119. }
  120. void Client::connect()
  121. {
  122. lock_guard<mutex> lock(WriteReadMutex);
  123. struct sockaddr_in echoserver;
  124. _handler = socket(AF_INET, SOCK_STREAM, 0);
  125. memset(&echoserver, 0, sizeof(echoserver));
  126. echoserver.sin_family = AF_INET;
  127. echoserver.sin_addr.s_addr = inet_addr(IP);
  128. echoserver.sin_port = htons(PORT);
  129. /* Establish connection */
  130. if ( 0 > ::connect(_handler, (struct sockaddr *) &echoserver, sizeof(echoserver)) )
  131. {
  132. throw runtime_error("Can't connect to the server");
  133. }
  134. SSLHandler = SSL_new(_ctx);
  135. // if socket is blocking you can set this and forget about looking at SSL_get_error code on I/O calls
  136. // long mode = SSL_CTX_set_mode(_ctx, SSL_MODE_AUTO_RETRY);
  137. // if( ( mode & SSL_MODE_AUTO_RETRY) != SSL_MODE_AUTO_RETRY )
  138. // {
  139. // throw runtime_error("SSL_MODE_AUTO_RETRY couldn't be set");
  140. // }
  141. SSL_set_fd(SSLHandler, _handler);
  142. if( SSL_connect(SSLHandler) <= 0)
  143. {
  144. cerr << "Can't setup SSL session" << endl;
  145. exit(1);
  146. }
  147. // bug reproduces even if call is blocking, so not need to uncommet this line
  148. int opts = fcntl(_handler,F_GETFL);
  149. opts = opts & ( ~O_NONBLOCK );
  150. fcntl(_handler, F_SETFL, opts);
  151. }
  152. void Client::start()
  153. {
  154. // start sender thread first
  155. _sender =new thread( Sender );
  156. struct timeval tv;
  157. // go to select loop
  158. while(1)
  159. {
  160. // wait timer for select
  161. tv.tv_sec = 0;
  162. tv.tv_usec = 10;
  163. fd_set fd_read;
  164. FD_ZERO(&fd_read);
  165. FD_SET(_handler, &fd_read);
  166. select(_handler+1, &fd_read, NULL, NULL, (struct timeval *)&tv);
  167. if( FD_ISSET(_handler, &fd_read ) )
  168. {
  169. // this should be in other thread but... it works
  170. #ifdef _RENEG_ON_
  171. if( CharsRead > RENEG_INIT_LEN )
  172. {
  173. CharsRead = 0;
  174. renegotiate();
  175. }
  176. #endif
  177. receive();
  178. }
  179. }
  180. }
  181. void Client::renegotiate()
  182. {
  183. lock_guard<mutex> lock_reads(WriteReadMutex);
  184. if( SSL_renegotiate_pending(SSLHandler) == false )
  185. {
  186. cout << "Starting SSL renegotiation on SSL"
  187. << "client (initiating by SSL client)" << endl;
  188. cout << "SSL State: " << SSL_state_string(SSLHandler) << endl;
  189. if(SSL_renegotiate(SSLHandler) <= 0){
  190. cerr << "SSL_renegotiate() failed. STATE: "
  191. << SSL_state_string(SSLHandler) << endl;
  192. ERR_print_errors_fp(stderr);
  193. exit(1);
  194. }
  195. }
  196. cout << "SSL State: " << SSL_state_string(SSLHandler) << endl;
  197. // if(SSL_do_handshake(SSLHandler) <= 0){
  198. // cerr << "SSL_do_handshake() failed. STATE: "
  199. // << SSL_state_string(SSLHandler) << endl;
  200. // ERR_print_errors_fp(stderr);
  201. // exit(1);
  202. // }
  203. }
  204. void Client::init()
  205. {
  206. sslInit();
  207. }
  208. // --- MAIN --- //
  209. int main()
  210. {
  211. try
  212. {
  213. Client client;
  214. client.init();
  215. client.connect();
  216. client.start();
  217. }
  218. catch(std::runtime_error& e)
  219. {
  220. cerr << "ERROR " << e.what() << endl;
  221. }
  222. catch(...)
  223. {
  224. cerr << "Unknown exception" << endl;
  225. }
  226. return 0;
  227. }