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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.19 - (hide annotations)
Fri Jul 26 14:42:01 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_8
Branch point for: release-0_8-patches
Changes since 1.18: +8 -4 lines
File MIME type: text/plain
Don't print connected message during rcopy/rmove.

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.19
40 lefcha 1.17 #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 lefcha 1.19 memset((char *)&sa, 0, sizeof(struct sockaddr_in));
48 lefcha 1.1
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.19 if (sock == &sockpri)
79     info("Connected to %s using %s.\n", serv,
80     SSL_get_cipher(ssl));
81 lefcha 1.11 return 0;
82     } else
83     return ERROR_SSL;
84     else
85 lefcha 1.1 ssl = NULL;
86     #endif
87    
88 lefcha 1.19 if (sock == &sockpri)
89     info("Connected to %s.\n", serv);
90 lefcha 1.10
91 lefcha 1.1 return 0;
92     }
93    
94    
95     #ifdef SSL_TLS
96     /*
97     * Initialize Secure Socket Layer connection.
98     */
99 lefcha 1.18 int ssl_init(int *sock, unsigned int protocol)
100 lefcha 1.1 {
101     int e;
102 lefcha 1.7 unsigned int i, n = 0;
103 lefcha 1.1 SSL_CTX *ctx;
104     SSL_METHOD *method = NULL;
105 lefcha 1.3 X509 *cert;
106     char *c;
107     EVP_MD *evp;
108     unsigned char digest[EVP_MAX_MD_SIZE];
109 lefcha 1.2
110 lefcha 1.1 SSL_library_init();
111 lefcha 1.2
112 lefcha 1.1 switch (protocol) {
113     case SSL_SSL_V2:
114     method = SSLv2_client_method();
115     break;
116     case SSL_SSL_V3:
117     method = SSLv3_client_method();
118     break;
119     case SSL_TLS_V1:
120     method = TLSv1_client_method();
121     break;
122     }
123 lefcha 1.2
124 lefcha 1.1 if (!(ctx = SSL_CTX_new(method)))
125     return ERROR_SSL;
126 lefcha 1.2
127 lefcha 1.1 if (!(ssl = SSL_new(ctx)))
128     return ERROR_SSL;
129 lefcha 1.2
130 lefcha 1.18 SSL_set_fd(ssl, *sock);
131 lefcha 1.1
132     e = SSL_connect(ssl);
133 lefcha 1.2
134 lefcha 1.13 if (e < 0) {
135 lefcha 1.1 error("imapfilter: initiating SSL connection; %s",
136     ERR_error_string(e, NULL));
137     return ERROR_SSL;
138     }
139 lefcha 1.3 /* Get server's certificate. */
140     if (!(cert = SSL_get_peer_certificate(ssl)))
141     return ERROR_SSL;
142    
143     if (!(c = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)))
144     return ERROR_SSL;
145     verbose("Server certificate subject: %s\n", c);
146 lefcha 1.15 xfree(c);
147 lefcha 1.3
148     if (!(c = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)))
149     return ERROR_SSL;
150     verbose("Server certificate issuer: %s\n", c);
151 lefcha 1.15 xfree(c);
152 lefcha 1.3
153     if (!(evp = EVP_md5()))
154     return ERROR_SSL;
155 lefcha 1.7 if (!(X509_digest(cert, evp, digest, &n)))
156 lefcha 1.3 return ERROR_SSL;
157    
158     verbose("Server key fingerprint: ");
159 lefcha 1.7 for (i = 0; i < n; i++)
160     verbose(i != n - 1 ? "%02X:" : "%02X\n", digest[i]);
161 lefcha 1.3
162     X509_free(cert);
163 lefcha 1.1 SSL_CTX_free(ctx);
164    
165     return 0;
166     }
167 lefcha 1.19
168 lefcha 1.1 #endif
169    
170    
171     /*
172     * Disconnect from mail server.
173     */
174 lefcha 1.18 int close_connection(int *sock)
175 lefcha 1.1 {
176     #ifdef SSL_TLS
177     if (ssl) {
178     SSL_shutdown(ssl);
179     SSL_free(ssl);
180     }
181     #endif
182    
183 lefcha 1.18 if (*sock >= 0 && close(*sock)) {
184 lefcha 1.1 error("imapfilter: closing socket; %s\n", strerror(errno));
185     return ERROR_NETWORK;
186 lefcha 1.16 } else {
187 lefcha 1.18 *sock = -1;
188 lefcha 1.1 return 0;
189 lefcha 1.16 }
190 lefcha 1.1 }
191    
192    
193     /*
194     * Read data from socket.
195     */
196 lefcha 1.18 int socket_read(int *sock, char *buf)
197 lefcha 1.1 {
198 lefcha 1.18 int f, r, s;
199 lefcha 1.1 fd_set fds;
200     struct timeval tv;
201 lefcha 1.13 struct timeval *tvp = NULL;
202 lefcha 1.7
203 lefcha 1.8 r = 0;
204     s = 1;
205 lefcha 1.1
206 lefcha 1.5 memset(buf, 0, RESPONSE_BUF);
207 lefcha 1.1
208 lefcha 1.14 if (timeout >= 0) {
209 lefcha 1.13 tv.tv_sec = timeout;
210     tv.tv_usec = 0;
211     tvp = &tv;
212     }
213 lefcha 1.18 f = fcntl(*sock, F_GETFL, 0);
214     fcntl(*sock, F_SETFL, f | O_NONBLOCK);
215 lefcha 1.1
216     FD_ZERO(&fds);
217 lefcha 1.18 FD_SET(*sock, &fds);
218 lefcha 1.1
219     #ifdef SSL_TLS
220 lefcha 1.6 if (ssl) {
221 lefcha 1.8 if (SSL_pending(ssl)
222 lefcha 1.18 || ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0
223     && FD_ISSET(*sock, &fds)))
224 lefcha 1.6 r = SSL_read(ssl, buf, RESPONSE_BUF - 1);
225     } else
226 lefcha 1.1 #endif
227 lefcha 1.18 if ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0
228     && FD_ISSET(*sock, &fds))
229     r = read(*sock, buf, RESPONSE_BUF - 1);
230 lefcha 1.6
231 lefcha 1.18 fcntl(*sock, F_SETFL, f);
232 lefcha 1.2
233 lefcha 1.8 if (s == -1)
234 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
235     strerror(errno));
236 lefcha 1.8 else if (!s)
237     fatal(ERROR_NETWORK,
238     "imapfilter: timeout period expired while waiting data\n");
239 lefcha 1.1
240     #ifdef SSL_TLS
241 lefcha 1.6 if (ssl) {
242 lefcha 1.8 if (r < 0)
243 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
244     ERR_error_string(r, NULL));
245     } else
246 lefcha 1.1 #endif
247 lefcha 1.6 if (r == -1)
248     fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
249     strerror(errno));
250 lefcha 1.1
251 lefcha 1.6 return 0;
252 lefcha 1.1 }
253    
254    
255     /*
256     * Write data to socket.
257     */
258 lefcha 1.18 int socket_write(int *sock, char *data)
259 lefcha 1.1 {
260     #ifdef SSL_TLS
261     int e;
262    
263     if (ssl) {
264     e = SSL_write(ssl, data, strlen(data));
265     if (e <= 0)
266     fatal(ERROR_NETWORK,
267     "imapfilter: sending data; %s",
268     ERR_error_string(e, NULL));
269     } else
270     #endif
271 lefcha 1.18 if (write(*sock, data, strlen(data)) == -1)
272 lefcha 1.1 fatal(ERROR_NETWORK, "imapfilter: sending data; %s",
273     strerror(errno));
274 lefcha 1.2
275 lefcha 1.1 return 0;
276     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26