/[imapfilter]/imapfilter/socket.c
ViewVC logotype

Diff of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.30 by lefcha, Sun Jul 27 10:10:03 2003 UTC revision 1.31 by lefcha, Sun Jul 27 17:39:45 2003 UTC
# Line 18  Line 18 
18  #endif  #endif
19    
20  extern unsigned int options;  extern unsigned int options;
21    extern conn_t connpri, connaux;
22    
23  long timeout = -1;              /* Server non-response timeout in seconds. */  long timeout = -1;              /* Server non-response timeout in seconds. */
24    
 int sockpri = -1;               /* Main socket used mostly. */  
 int sockaux = -1;               /* Auxiliary socked used when another  
                                  * connection is needed. */  
   
 #ifdef SSL_TLS  
 static SSL *sslpri = NULL;  
 static SSL *sslaux = NULL;  
   
 #endif  
   
   
25    
26  /*  /*
27   * Connect to mail server.   * Connect to mail server.
28   */   */
29  int  int
30  init_connection(int *sock, char *serv, unsigned short int port,  init_connection(conn_t * conn, char *serv, unsigned short int port,
31      unsigned int protocol)      unsigned int protocol)
32  {  {
33          struct sockaddr_in sa;          struct sockaddr_in sa;
34          struct hostent *he;          struct hostent *he;
35    
 #ifdef SSL_TLS  
         SSL **ssl;  
   
         ssl = (sock == &sockpri ? &sslpri : &sslaux);  
 #else  
36          if (protocol != SSL_DISABLED) {          if (protocol != SSL_DISABLED) {
37                  error("SSL not supported by this build\n");                  error("SSL not supported by this build\n");
38                  return ERROR_SSL;                  return ERROR_SSL;
39          }          }
 #endif  
   
40          memset((char *)&sa, 0, sizeof(struct sockaddr_in));          memset((char *)&sa, 0, sizeof(struct sockaddr_in));
41    
42          *sock = socket(PF_INET, SOCK_STREAM, 0);          conn->sock = socket(PF_INET, SOCK_STREAM, 0);
43    
44          if (*sock < 0) {          if (conn->sock < 0) {
45                  error("create socket; %s\n", strerror(errno));                  error("create socket; %s\n", strerror(errno));
46                  return ERROR_NETWORK;                  return ERROR_NETWORK;
47          }          }
48          if (!(he = gethostbyname(serv))) {          if (!(he = gethostbyname(serv))) {
49                  error("get network host entry of %s; %s\n", serv,                  error("get network host entry of %s; %s\n", serv,
50                      strerror(errno));                      strerror(errno));
51                  close_connection(sock);                  close_connection(conn);
52                  return ERROR_NETWORK;                  return ERROR_NETWORK;
53          }          }
54          sa.sin_family = AF_INET;          sa.sin_family = AF_INET;
55          sa.sin_port = htons(port);          sa.sin_port = htons(port);
56          sa.sin_addr = *(struct in_addr *) he->h_addr;          sa.sin_addr = *(struct in_addr *) he->h_addr;
57    
58          if (connect(*sock, (struct sockaddr *) & sa, sizeof(struct sockaddr))) {          if (connect(conn->sock, (struct sockaddr *) & sa,
59                    sizeof(struct sockaddr))) {
60                  error("initiating connection to %s; %s\n", serv,                  error("initiating connection to %s; %s\n", serv,
61                      strerror(errno));                      strerror(errno));
62                  close_connection(sock);                  close_connection(conn);
63                  return ERROR_NETWORK;                  return ERROR_NETWORK;
64          }          }
65          info("Connected to %s.\n", he->h_name);          info("Connected to %s.\n", he->h_name);
66    
67  #ifdef SSL_TLS  #ifdef SSL_TLS
68          if (protocol != SSL_DISABLED)          if (protocol != SSL_DISABLED)
69                  if (!imf_ssl_init(sock, protocol))                  if (!imf_ssl_init(conn, protocol))
70                          return 0;                          return 0;
71                  else                  else
72                          return ERROR_SSL;                          return ERROR_SSL;
73          else          else
74                  *ssl = NULL;                  conn->ssl = NULL;
75  #endif  #endif
76    
77          return 0;          return 0;
# Line 99  init_connection(int *sock, char *serv, u Line 83  init_connection(int *sock, char *serv, u
83   * Initialize Secure Socket Layer connection.   * Initialize Secure Socket Layer connection.
84   */   */
85  int  int
86  imf_ssl_init(int *sock, unsigned int protocol)  imf_ssl_init(conn_t * conn, unsigned int protocol)
87  {  {
88          int e;          int e;
89          SSL_CTX *ctx;          SSL_CTX *ctx;
90          SSL_METHOD *method;          SSL_METHOD *method;
         SSL **ssl;  
91          SSL_CIPHER *cipher;          SSL_CIPHER *cipher;
92          char *ver;          char *ver;
93          const char *name;          const char *name;
94          int usebits, algbits;          int usebits, algbits;
95    
96          method = NULL;          method = NULL;
         ssl = (sock == &sockpri ? &sslpri : &sslaux);  
97    
98          SSL_library_init();          SSL_library_init();
99          SSL_load_error_strings();          SSL_load_error_strings();
# Line 129  imf_ssl_init(int *sock, unsigned int pro Line 111  imf_ssl_init(int *sock, unsigned int pro
111          if (!(ctx = SSL_CTX_new(method)))          if (!(ctx = SSL_CTX_new(method)))
112                  goto fail;                  goto fail;
113    
114          if (!(*ssl = SSL_new(ctx)))          if (!(conn->ssl = SSL_new(ctx)))
115                  goto fail;                  goto fail;
116    
117          SSL_set_fd(*ssl, *sock);          SSL_set_fd(conn->ssl, conn->sock);
118    
119          if ((e = SSL_connect(*ssl)) <= 0) {          if ((e = SSL_connect(conn->ssl)) <= 0) {
120                  SSL_get_error(*ssl, e);                  SSL_get_error(conn->ssl, e);
121                  error("initiating SSL connection; %s\n",                  error("initiating SSL connection; %s\n",
122                      ERR_error_string(ERR_get_error(), NULL));                      ERR_error_string(ERR_get_error(), NULL));
123                  goto fail;                  goto fail;
124          }          }
125          cipher = SSL_get_current_cipher(*ssl);          cipher = SSL_get_current_cipher(conn->ssl);
126          ver = SSL_CIPHER_get_version(cipher);          ver = SSL_CIPHER_get_version(cipher);
127          name = SSL_CIPHER_get_name(cipher);          name = SSL_CIPHER_get_name(cipher);
128          usebits = SSL_CIPHER_get_bits(cipher, &algbits);          usebits = SSL_CIPHER_get_bits(cipher, &algbits);
129          verbose("SSL/TLS handshake completed: %s with cipher %s (%d/%d bits).\n",          verbose("SSL/TLS handshake completed: %s with cipher %s (%d/%d bits).\n",
130              ver, name, usebits, algbits);              ver, name, usebits, algbits);
131    
132          if (imf_ssl_cert(*ssl))          if (imf_ssl_cert(conn))
133                  goto fail;                  goto fail;
134    
135          SSL_CTX_free(ctx);          SSL_CTX_free(ctx);
# Line 155  imf_ssl_init(int *sock, unsigned int pro Line 137  imf_ssl_init(int *sock, unsigned int pro
137          return 0;          return 0;
138    
139  fail:  fail:
140          *ssl = NULL;          conn->ssl = NULL;
141          SSL_CTX_free(ctx);          SSL_CTX_free(ctx);
142    
143          return ERROR_SSL;          return ERROR_SSL;
# Line 168  fail: Line 150  fail:
150   * Disconnect from mail server.   * Disconnect from mail server.
151   */   */
152  int  int
153  close_connection(int *sock)  close_connection(conn_t * conn)
154  {  {
155  #ifdef SSL_TLS          if (conn->ssl) {
156          SSL **ssl;                  SSL_shutdown(conn->ssl);
157                    SSL_free(conn->ssl);
158          ssl = (sock == &sockpri ? &sslpri : &sslaux);                  conn->ssl = NULL;
   
         if (*ssl) {  
                 SSL_shutdown(*ssl);  
                 SSL_free(*ssl);  
                 *ssl = NULL;  
159          }          }
160  #endif          if (conn->sock >= 0 && close(conn->sock) == -1) {
   
         if (*sock >= 0 && close(*sock) == -1) {  
161                  error("closing socket; %s\n", strerror(errno));                  error("closing socket; %s\n", strerror(errno));
162                  return ERROR_NETWORK;                  return ERROR_NETWORK;
163          } else {          } else {
164                  *sock = -1;                  conn->sock = -1;
165                  return 0;                  return 0;
166          }          }
167  }  }
# Line 196  close_connection(int *sock) Line 171  close_connection(int *sock)
171   * Read data from socket.   * Read data from socket.
172   */   */
173  int  int
174  socket_read(int *sock, char *buf)  socket_read(conn_t * conn, char *buf)
175  {  {
176          int f, e, s;          int f, e, s;
177          fd_set fds;          fd_set fds;
178          struct timeval tv;          struct timeval tv;
179          struct timeval *tvp;          struct timeval *tvp;
180    
 #ifdef SSL_TLS  
         SSL **ssl;  
   
 #endif  
   
181          e = 0;          e = 0;
182          s = 1;          s = 1;
183          tvp = NULL;          tvp = NULL;
 #ifdef SSL_TLS  
         ssl = (sock == &sockpri ? &sslpri : &sslaux);  
 #endif  
184    
185          memset(buf, 0, RESPONSE_BUF + 1);          memset(buf, 0, RESPONSE_BUF + 1);
186    
# Line 222  socket_read(int *sock, char *buf) Line 189  socket_read(int *sock, char *buf)
189                  tv.tv_usec = 0;                  tv.tv_usec = 0;
190                  tvp = &tv;                  tvp = &tv;
191          }          }
192          f = fcntl(*sock, F_GETFL, 0);          f = fcntl(conn->sock, F_GETFL, 0);
193          fcntl(*sock, F_SETFL, f | O_NONBLOCK);          fcntl(conn->sock, F_SETFL, f | O_NONBLOCK);
194    
195          FD_ZERO(&fds);          FD_ZERO(&fds);
196          FD_SET(*sock, &fds);          FD_SET(conn->sock, &fds);
197    
198  #ifdef SSL_TLS  #ifdef SSL_TLS
199          if (*ssl) {          if (conn->ssl) {
200                  while (SSL_pending(*ssl) > 0 ||                  while (SSL_pending(conn->ssl) > 0 ||
201                      ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0 &&                      ((s = select(conn->sock + 1, &fds, NULL, NULL, tvp)) > 0 &&
202                          FD_ISSET(*sock, &fds))) {                          FD_ISSET(conn->sock, &fds))) {
203                          e = SSL_read(*ssl, buf, RESPONSE_BUF);                          e = SSL_read(conn->ssl, buf, RESPONSE_BUF);
204    
205                          if (e > 0)                          if (e > 0)
206                                  break;                                  break;
207    
208                          switch (SSL_get_error(*ssl, e)) {                          switch (SSL_get_error(conn->ssl, e)) {
209                          case SSL_ERROR_WANT_READ:                          case SSL_ERROR_WANT_READ:
210                          case SSL_ERROR_WANT_WRITE:                          case SSL_ERROR_WANT_WRITE:
211                                  continue;                                  continue;
# Line 256  socket_read(int *sock, char *buf) Line 223  socket_read(int *sock, char *buf)
223          } else          } else
224  #endif  #endif
225          {          {
226                  if ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0 &&                  if ((s = select(conn->sock + 1, &fds, NULL, NULL, tvp)) > 0 &&
227                      FD_ISSET(*sock, &fds))                      FD_ISSET(conn->sock, &fds))
228                          e = read(*sock, buf, RESPONSE_BUF);                          e = read(conn->sock, buf, RESPONSE_BUF);
229    
230                  if (e == -1)                  if (e == -1)
231                          fatal(ERROR_NETWORK, "reading data; %s",                          fatal(ERROR_NETWORK, "reading data; %s",
# Line 267  socket_read(int *sock, char *buf) Line 234  socket_read(int *sock, char *buf)
234                          return ERROR_NETWORK;                          return ERROR_NETWORK;
235          }          }
236    
237          fcntl(*sock, F_SETFL, f);          fcntl(conn->sock, F_SETFL, f);
238    
239          if (s == -1)          if (s == -1)
240                  fatal(ERROR_NETWORK, "waiting to read from socket; %s\n",                  fatal(ERROR_NETWORK, "waiting to read from socket; %s\n",
# Line 285  socket_read(int *sock, char *buf) Line 252  socket_read(int *sock, char *buf)
252   * Write data to socket.   * Write data to socket.
253   */   */
254  int  int
255  socket_write(int *sock, char *data)  socket_write(conn_t * conn, char *data)
256  {  {
257          int f, e, s;          int f, e, s;
258          fd_set fds;          fd_set fds;
259          struct timeval tv;          struct timeval tv;
260          struct timeval *tvp = NULL;          struct timeval *tvp = NULL;
261    
 #ifdef SSL_TLS  
         SSL **ssl;  
   
 #endif  
   
262          e = 0;          e = 0;
263          s = 1;          s = 1;
 #ifdef SSL_TLS  
         ssl = (sock == &sockpri ? &sslpri : &sslaux);  
 #endif  
264    
265          if (timeout >= 0) {          if (timeout >= 0) {
266                  tv.tv_sec = timeout;                  tv.tv_sec = timeout;
267                  tv.tv_usec = 0;                  tv.tv_usec = 0;
268                  tvp = &tv;                  tvp = &tv;
269          }          }
270          f = fcntl(*sock, F_GETFL, 0);          f = fcntl(conn->sock, F_GETFL, 0);
271          fcntl(*sock, F_SETFL, f | O_NONBLOCK);          fcntl(conn->sock, F_SETFL, f | O_NONBLOCK);
272    
273          FD_ZERO(&fds);          FD_ZERO(&fds);
274          FD_SET(*sock, &fds);          FD_SET(conn->sock, &fds);
275    
276  #ifdef SSL_TLS  #ifdef SSL_TLS
277          if (*ssl) {          if (conn->ssl) {
278                  while ((s = select(*sock + 1, NULL, &fds, NULL, tvp) > 0 &&                  while ((s = select(conn->sock + 1, NULL, &fds, NULL, tvp) > 0 &&
279                          FD_ISSET(*sock, &fds))) {                          FD_ISSET(conn->sock, &fds))) {
280                          e = SSL_write(*ssl, data, strlen(data));                          e = SSL_write(conn->ssl, data, strlen(data));
281    
282                          if (e > 0)                          if (e > 0)
283                                  break;                                  break;
284    
285                          switch (SSL_get_error(*ssl, e)) {                          switch (SSL_get_error(conn->ssl, e)) {
286                          case SSL_ERROR_WANT_READ:                          case SSL_ERROR_WANT_READ:
287                          case SSL_ERROR_WANT_WRITE:                          case SSL_ERROR_WANT_WRITE:
288                                  continue;                                  continue;
# Line 341  socket_write(int *sock, char *data) Line 300  socket_write(int *sock, char *data)
300          } else          } else
301  #endif  #endif
302          {          {
303                  if ((s = select(*sock + 1, NULL, &fds, NULL, tvp)) > 0 &&                  if ((s = select(conn->sock + 1, NULL, &fds, NULL, tvp)) > 0 &&
304                      FD_ISSET(*sock, &fds))                      FD_ISSET(conn->sock, &fds))
305                          e = write(*sock, data, strlen(data));                          e = write(conn->sock, data, strlen(data));
306    
307                  if (e == -1)                  if (e == -1)
308                          fatal(ERROR_NETWORK, "writing data; %s",                          fatal(ERROR_NETWORK, "writing data; %s",
309                              strerror(errno));                              strerror(errno));
310          }          }
311    
312          fcntl(*sock, F_SETFL, f);          fcntl(conn->sock, F_SETFL, f);
313    
314          if (s == -1)          if (s == -1)
315                  fatal(ERROR_NETWORK, "waiting to write to socket; %s\n",                  fatal(ERROR_NETWORK, "waiting to write to socket; %s\n",

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.31

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26