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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (hide annotations)
Sat Dec 8 14:44:16 2001 UTC (22 years, 3 months ago) by lefcha
Branch: MAIN
Changes since 1.13: +6 -4 lines
File MIME type: text/plain
Corrected checking of the timeout variable.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26