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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (hide annotations)
Sun Nov 18 13:07:47 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.12: +15 -9 lines
File MIME type: text/plain
Added option to control server non-response timeout.

1 lefcha 1.1 #include <string.h>
2     #include <errno.h>
3     #include <unistd.h>
4 lefcha 1.10 #include <sys/time.h>
5 lefcha 1.1 #include <sys/types.h>
6     #include <sys/socket.h>
7     #include <netinet/in.h>
8     #include <netdb.h>
9     #include <fcntl.h>
10    
11     #include "config.h"
12     #include "imapfilter.h"
13    
14     #ifdef SSL_TLS
15     #include <openssl/ssl.h>
16     #include <openssl/err.h>
17 lefcha 1.3 #include <openssl/x509.h>
18 lefcha 1.13 #endif
19    
20 lefcha 1.1
21 lefcha 1.13 extern long timeout;
22 lefcha 1.1
23 lefcha 1.13 static int sock;
24    
25     #ifdef SSL_TLS
26 lefcha 1.1 static SSL *ssl;
27     #endif
28    
29    
30     /*
31     * Connect to mail server.
32     */
33     #ifndef SSL_TLS
34 lefcha 1.11 int init_connection(char *serv, unsigned short int port)
35 lefcha 1.1 #else
36 lefcha 1.11 int init_connection(char *serv, unsigned short int port, unsigned int protocol)
37 lefcha 1.1 #endif
38     {
39     struct sockaddr_in sa;
40     struct hostent *he;
41    
42     memset((char *) &sa, 0, sizeof(struct sockaddr_in));
43    
44     sock = socket(PF_INET, SOCK_STREAM, 0);
45    
46     if (sock < 0) {
47     error("imapfilter: create socket; %s\n", strerror(errno));
48     return ERROR_NETWORK;
49     }
50     if (!(he = gethostbyname(serv))) {
51 lefcha 1.12 error("imapfilter: get network host entry of %s; %s\n", serv,
52     strerror(errno));
53 lefcha 1.1 close_connection();
54     return ERROR_NETWORK;
55     }
56     sa.sin_family = AF_INET;
57     sa.sin_port = htons(port);
58     sa.sin_addr = *(struct in_addr *) he->h_addr;
59    
60 lefcha 1.9 xstrncpy(serv, he->h_name, SERVER_LEN - 1);
61    
62 lefcha 1.1 if (connect(sock, (struct sockaddr *) & sa, sizeof(struct sockaddr))) {
63 lefcha 1.9 error("imapfilter: initiating connection to %s; %s\n", serv, strerror(errno));
64 lefcha 1.1 close_connection();
65     return ERROR_NETWORK;
66     }
67     log_info(LOG_SERVER, serv);
68 lefcha 1.2
69 lefcha 1.1 #ifdef SSL_TLS
70 lefcha 1.11 if (protocol != SSL_DISABLED)
71     if (!ssl_init(protocol)) {
72     info("Connected to %s using %s.\n", serv, SSL_get_cipher(ssl));
73     return 0;
74     } else
75     return ERROR_SSL;
76     else
77 lefcha 1.1 ssl = NULL;
78     #endif
79    
80 lefcha 1.8 info("Connected to %s.\n", serv);
81 lefcha 1.10
82 lefcha 1.1 return 0;
83     }
84    
85    
86     #ifdef SSL_TLS
87     /*
88     * Initialize Secure Socket Layer connection.
89     */
90     int ssl_init(unsigned int protocol)
91     {
92     int e;
93 lefcha 1.7 unsigned int i, n = 0;
94 lefcha 1.1 SSL_CTX *ctx;
95     SSL_METHOD *method = NULL;
96 lefcha 1.3 X509 *cert;
97     char *c;
98     EVP_MD *evp;
99     unsigned char digest[EVP_MAX_MD_SIZE];
100 lefcha 1.2
101 lefcha 1.1 SSL_library_init();
102 lefcha 1.2
103 lefcha 1.1 switch (protocol) {
104     case SSL_SSL_V2:
105     method = SSLv2_client_method();
106     break;
107     case SSL_SSL_V3:
108     method = SSLv3_client_method();
109     break;
110     case SSL_TLS_V1:
111     method = TLSv1_client_method();
112     break;
113     }
114 lefcha 1.2
115 lefcha 1.1 if (!(ctx = SSL_CTX_new(method)))
116     return ERROR_SSL;
117 lefcha 1.2
118 lefcha 1.1 if (!(ssl = SSL_new(ctx)))
119     return ERROR_SSL;
120 lefcha 1.2
121 lefcha 1.1 SSL_set_fd(ssl, sock);
122    
123     e = SSL_connect(ssl);
124 lefcha 1.2
125 lefcha 1.13 if (e < 0) {
126 lefcha 1.1 error("imapfilter: initiating SSL connection; %s",
127     ERR_error_string(e, NULL));
128     return ERROR_SSL;
129     }
130 lefcha 1.3 /* Get server's certificate. */
131     if (!(cert = SSL_get_peer_certificate(ssl)))
132     return ERROR_SSL;
133    
134     if (!(c = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)))
135     return ERROR_SSL;
136     verbose("Server certificate subject: %s\n", c);
137     free(c);
138    
139     if (!(c = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)))
140     return ERROR_SSL;
141     verbose("Server certificate issuer: %s\n", c);
142     free(c);
143    
144     if (!(evp = EVP_md5()))
145     return ERROR_SSL;
146 lefcha 1.7 if (!(X509_digest(cert, evp, digest, &n)))
147 lefcha 1.3 return ERROR_SSL;
148    
149     verbose("Server key fingerprint: ");
150 lefcha 1.7 for (i = 0; i < n; i++)
151     verbose(i != n - 1 ? "%02X:" : "%02X\n", digest[i]);
152 lefcha 1.3
153     X509_free(cert);
154 lefcha 1.1 SSL_CTX_free(ctx);
155    
156     return 0;
157     }
158     #endif
159    
160    
161     /*
162     * Disconnect from mail server.
163     */
164     int close_connection(void)
165     {
166     #ifdef SSL_TLS
167     if (ssl) {
168     SSL_shutdown(ssl);
169     SSL_free(ssl);
170     }
171     #endif
172    
173     if (close(sock)) {
174     error("imapfilter: closing socket; %s\n", strerror(errno));
175     return ERROR_NETWORK;
176     } else
177     return 0;
178     }
179    
180    
181     /*
182     * Read data from socket.
183     */
184     int socket_read(char *buf)
185     {
186 lefcha 1.6 int flags, r, s;
187 lefcha 1.1 fd_set fds;
188     struct timeval tv;
189 lefcha 1.13 struct timeval *tvp = NULL;
190 lefcha 1.7
191 lefcha 1.8 r = 0;
192     s = 1;
193 lefcha 1.1
194 lefcha 1.5 memset(buf, 0, RESPONSE_BUF);
195 lefcha 1.1
196 lefcha 1.13 if (timeout) {
197     tv.tv_sec = timeout;
198     tv.tv_usec = 0;
199     tvp = &tv;
200     }
201 lefcha 1.1 flags = fcntl(sock, F_GETFL, 0);
202     fcntl(sock, F_SETFL, flags | O_NONBLOCK);
203    
204     FD_ZERO(&fds);
205     FD_SET(sock, &fds);
206    
207     #ifdef SSL_TLS
208 lefcha 1.6 if (ssl) {
209 lefcha 1.8 if (SSL_pending(ssl)
210 lefcha 1.13 || ((s = select(sock + 1, &fds, NULL, NULL, tvp)) > 0
211 lefcha 1.8 && FD_ISSET(sock, &fds)))
212 lefcha 1.6 r = SSL_read(ssl, buf, RESPONSE_BUF - 1);
213     } else
214 lefcha 1.1 #endif
215 lefcha 1.13 if ((s = select(sock + 1, &fds, NULL, NULL, tvp)) > 0
216 lefcha 1.6 && FD_ISSET(sock, &fds))
217     r = read(sock, buf, RESPONSE_BUF - 1);
218    
219     fcntl(sock, F_SETFL, flags);
220 lefcha 1.2
221 lefcha 1.8 if (s == -1)
222 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
223     strerror(errno));
224 lefcha 1.8 else if (!s)
225     fatal(ERROR_NETWORK,
226     "imapfilter: timeout period expired while waiting data\n");
227 lefcha 1.1
228     #ifdef SSL_TLS
229 lefcha 1.6 if (ssl) {
230 lefcha 1.8 if (r < 0)
231 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
232     ERR_error_string(r, NULL));
233     } else
234 lefcha 1.1 #endif
235 lefcha 1.6 if (r == -1)
236     fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
237     strerror(errno));
238 lefcha 1.1
239 lefcha 1.6 return 0;
240 lefcha 1.1 }
241    
242    
243     /*
244     * Write data to socket.
245     */
246     int socket_write(char *data)
247     {
248     #ifdef SSL_TLS
249     int e;
250    
251     if (ssl) {
252     e = SSL_write(ssl, data, strlen(data));
253     if (e <= 0)
254     fatal(ERROR_NETWORK,
255     "imapfilter: sending data; %s",
256     ERR_error_string(e, NULL));
257     } else
258     #endif
259     if (write(sock, data, strlen(data)) == -1)
260     fatal(ERROR_NETWORK, "imapfilter: sending data; %s",
261     strerror(errno));
262 lefcha 1.2
263 lefcha 1.1 return 0;
264     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26