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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Tue Nov 6 17:41:27 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.3: +6 -3 lines
File MIME type: text/plain
Dynamically allocate response buffer.

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     strncpy(serv, he->h_name, SERVER_LEN - 1);
60    
61     log_info(LOG_SERVER, serv);
62 lefcha 1.2
63 lefcha 1.1 #ifdef SSL_TLS
64     if (protocol != SSL_DISABLED) {
65     ssl_init(protocol);
66     info("Connected to %s using %s.\n", serv, SSL_get_cipher(ssl));
67     } else {
68     ssl = NULL;
69     #endif
70     info("Connected to %s.\n", serv);
71     #ifdef SSL_TLS
72     }
73     #endif
74 lefcha 1.2
75 lefcha 1.1
76     return 0;
77     }
78    
79    
80     #ifdef SSL_TLS
81     /*
82     * Initialize Secure Socket Layer connection.
83     */
84     int ssl_init(unsigned int protocol)
85     {
86     int e;
87     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     int s, i;
94 lefcha 1.2
95 lefcha 1.1 SSL_library_init();
96 lefcha 1.2
97 lefcha 1.1 switch (protocol) {
98     case SSL_SSL_V2:
99     method = SSLv2_client_method();
100     break;
101     case SSL_SSL_V3:
102     method = SSLv3_client_method();
103     break;
104     case SSL_TLS_V1:
105     method = TLSv1_client_method();
106     break;
107     }
108 lefcha 1.2
109 lefcha 1.1 if (!(ctx = SSL_CTX_new(method)))
110     return ERROR_SSL;
111 lefcha 1.2
112 lefcha 1.1 if (!(ssl = SSL_new(ctx)))
113     return ERROR_SSL;
114 lefcha 1.2
115 lefcha 1.1 SSL_set_fd(ssl, sock);
116    
117     e = SSL_connect(ssl);
118 lefcha 1.2
119 lefcha 1.1 if (e <= 0) {
120     error("imapfilter: initiating SSL connection; %s",
121     ERR_error_string(e, NULL));
122     return ERROR_SSL;
123     }
124 lefcha 1.3 /* Get server's certificate. */
125     if (!(cert = SSL_get_peer_certificate(ssl)))
126     return ERROR_SSL;
127    
128     if (!(c = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)))
129     return ERROR_SSL;
130     verbose("Server certificate subject: %s\n", c);
131     free(c);
132    
133     if (!(c = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)))
134     return ERROR_SSL;
135     verbose("Server certificate issuer: %s\n", c);
136     free(c);
137    
138     if (!(evp = EVP_md5()))
139     return ERROR_SSL;
140     if (!(X509_digest(cert, evp, digest, &s)))
141     return ERROR_SSL;
142    
143     verbose("Server key fingerprint: ");
144     for (i = 0; i < s; i++)
145     verbose(i != s - 1 ? "%02X:" : "%02X\n", digest[i]);
146    
147     X509_free(cert);
148 lefcha 1.1 SSL_CTX_free(ctx);
149    
150     return 0;
151     }
152     #endif
153    
154    
155     /*
156     * Disconnect from mail server.
157     */
158     int close_connection(void)
159     {
160     #ifdef SSL_TLS
161     if (ssl) {
162     SSL_shutdown(ssl);
163     SSL_free(ssl);
164     }
165     #endif
166    
167     if (close(sock)) {
168     error("imapfilter: closing socket; %s\n", strerror(errno));
169     return ERROR_NETWORK;
170     } else
171     return 0;
172     }
173    
174    
175     /*
176     * Read data from socket.
177     */
178     int socket_read(char *buf)
179     {
180 lefcha 1.4 char b[SOCKET_READ_BUF + 1];
181 lefcha 1.1 int flags, e;
182     fd_set fds;
183     struct timeval tv;
184    
185 lefcha 1.4 memset(b, 0, SOCKET_READ_BUF + 1);
186 lefcha 1.1
187     tv.tv_sec = 20;
188     tv.tv_usec = 0;
189    
190     flags = fcntl(sock, F_GETFL, 0);
191     fcntl(sock, F_SETFL, flags | O_NONBLOCK);
192    
193     FD_ZERO(&fds);
194     FD_SET(sock, &fds);
195    
196     if ((select(sock + 1, &fds, NULL, NULL, &tv) > 0)
197     && FD_ISSET(sock, &fds)) {
198    
199     #ifdef SSL_TLS
200     if (ssl)
201 lefcha 1.4 e = SSL_read(ssl, b, SOCKET_READ_BUF);
202 lefcha 1.1 else
203     #endif
204 lefcha 1.4 e = read(sock, b, SOCKET_READ_BUF);
205    
206     strncat(buf, b, SOCKET_READ_BUF);
207 lefcha 1.2
208 lefcha 1.1 fcntl(sock, F_SETFL, flags);
209    
210     #ifdef SSL_TLS
211     if (ssl) {
212     if (e <= 0)
213     fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
214     ERR_error_string(e, NULL));
215     } else
216     #endif
217 lefcha 1.2 if (e == -1)
218     fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
219     strerror(errno));
220    
221 lefcha 1.1 return 0;
222     }
223     fcntl(sock, F_SETFL, flags);
224    
225     fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
226     strerror(errno));
227    
228     return ERROR_NETWORK; /* NEVER REACHED. */
229     }
230    
231    
232     /*
233     * Write data to socket.
234     */
235     int socket_write(char *data)
236     {
237     #ifdef SSL_TLS
238     int e;
239    
240     if (ssl) {
241     e = SSL_write(ssl, data, strlen(data));
242     if (e <= 0)
243     fatal(ERROR_NETWORK,
244     "imapfilter: sending data; %s",
245     ERR_error_string(e, NULL));
246     } else
247     #endif
248     if (write(sock, data, strlen(data)) == -1)
249     fatal(ERROR_NETWORK, "imapfilter: sending data; %s",
250     strerror(errno));
251 lefcha 1.2
252 lefcha 1.1 return 0;
253     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26