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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (hide annotations)
Fri Feb 8 22:15:43 2002 UTC (22 years, 1 month ago) by lefcha
Branch: MAIN
Changes since 1.16: +7 -4 lines
File MIME type: text/plain
Allow ssl appear in config file, but fail with error message.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26