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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (hide annotations)
Tue Jun 18 21:21:58 2002 UTC (21 years, 10 months ago) by lefcha
Branch: MAIN
Changes since 1.17: +28 -27 lines
File MIME type: text/plain
Changes to reflect rcopy/rmove capability.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26