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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations)
Fri Nov 9 16:55:15 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.7: +18 -14 lines
File MIME type: text/plain
A fix about select() timeout period.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26