您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

10 年前
10 年前
10 年前
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. }