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

Annotation of /imapfilter/cert.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations)
Sat Feb 14 19:14:43 2004 UTC (20 years, 1 month ago) by lefcha
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +3 -3 lines
File MIME type: text/plain
Indentation.

1 lefcha 1.1 #include <stdio.h>
2     #include <string.h>
3     #include <ctype.h>
4     #include <limits.h>
5     #include <sys/stat.h>
6    
7     #include "config.h"
8     #include "imapfilter.h"
9     #include "pathnames.h"
10    
11     #ifdef SSL_TLS
12 lefcha 1.2 #include <openssl/x509.h>
13 lefcha 1.1 #include <openssl/ssl.h>
14     #include <openssl/pem.h>
15 lefcha 1.2 #include <openssl/evp.h>
16 lefcha 1.1
17    
18 lefcha 1.2 extern char *home;
19 lefcha 1.5 extern options_t opts;
20 lefcha 1.1 extern unsigned int flags;
21    
22    
23     int check_cert(X509 * pcert, unsigned char *pmd, unsigned int *pmdlen);
24     void print_cert(X509 * cert, unsigned char *md, unsigned int *mdlen);
25     int write_cert(X509 * cert);
26     int mismatch_cert(void);
27    
28    
29     /*
30     * Get SSL/TLS certificate check it, maybe ask user about it and act
31     * accordingly.
32     */
33     int
34 lefcha 1.5 get_cert(connection_t * conn)
35 lefcha 1.1 {
36     X509 *cert;
37     unsigned char md[EVP_MAX_MD_SIZE];
38     unsigned int mdlen;
39    
40     mdlen = 0;
41    
42     if (!(cert = SSL_get_peer_certificate(conn->ssl)))
43     return ERROR_SSL;
44    
45     if (!(X509_digest(cert, EVP_md5(), md, &mdlen)))
46     return ERROR_SSL;
47    
48     switch (check_cert(cert, md, &mdlen)) {
49 lefcha 1.5 case CERT_NONE:
50 lefcha 1.1 print_cert(cert, md, &mdlen);
51 lefcha 1.5 if (flags & FLAG_DAEMON ||
52     write_cert(cert) == CERT_ACTION_REJECT)
53 lefcha 1.1 goto abort;
54     break;
55 lefcha 1.5 case CERT_MISMATCH:
56 lefcha 1.1 print_cert(cert, md, &mdlen);
57 lefcha 1.5 if (flags & FLAG_DAEMON ||
58     mismatch_cert() == CERT_ACTION_ABORT)
59 lefcha 1.1 goto abort;
60     break;
61 lefcha 1.5 case CERT_OK:
62 lefcha 1.4 if (opts.verbosity >= 1)
63 lefcha 1.1 print_cert(cert, md, &mdlen);
64     }
65    
66     X509_free(cert);
67     return 0;
68    
69     abort:
70     X509_free(cert);
71     return ERROR_SSL;
72     }
73    
74    
75     /*
76     * Check if the SSL/TLS certificate exists in the certificates file.
77     */
78     int
79     check_cert(X509 * pcert, unsigned char *pmd, unsigned int *pmdlen)
80     {
81     int r;
82     FILE *fd;
83 lefcha 1.2 char certf[PATH_MAX];
84 lefcha 1.1 X509 *cert;
85     unsigned char md[EVP_MAX_MD_SIZE];
86     unsigned int mdlen;
87    
88 lefcha 1.5 r = CERT_NONE;
89 lefcha 1.1 cert = NULL;
90    
91 lefcha 1.5 snprintf(certf, PATH_MAX, "%s/%s", home, PATHNAME_CERTS);
92 lefcha 1.2 if (!exists_file(certf))
93 lefcha 1.5 return CERT_NONE;
94 lefcha 1.1
95 lefcha 1.2 fd = fopen(certf, "r");
96 lefcha 1.1 if (fd == NULL)
97 lefcha 1.5 return ERROR_FILEOPEN;
98 lefcha 1.1
99     while ((cert = PEM_read_X509(fd, &cert, NULL, NULL)) != NULL) {
100     if (X509_subject_name_cmp(cert, pcert) != 0 ||
101     X509_issuer_name_cmp(cert, pcert) != 0)
102     continue;
103    
104     if (!X509_digest(cert, EVP_md5(), md, &mdlen) ||
105     *pmdlen != mdlen)
106     continue;
107    
108     if (memcmp(pmd, md, mdlen) != 0) {
109 lefcha 1.5 r = CERT_MISMATCH;
110 lefcha 1.1 break;
111     }
112 lefcha 1.5 r = CERT_OK;
113 lefcha 1.1 break;
114     }
115    
116     fclose(fd);
117     X509_free(cert);
118    
119     return r;
120     }
121    
122    
123     /*
124     * Print information about the SSL/TLS certificate.
125     */
126     void
127     print_cert(X509 * cert, unsigned char *md, unsigned int *mdlen)
128     {
129     unsigned int i;
130     char *c;
131    
132     c = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
133     printf("Server certificate subject: %s\n", c);
134     xfree(c);
135    
136     c = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
137     printf("Server certificate issuer: %s\n", c);
138     xfree(c);
139    
140     printf("Server key fingerprint: ");
141     for (i = 0; i < *mdlen; i++)
142     printf(i != *mdlen - 1 ? "%02X:" : "%02X\n", md[i]);
143     }
144    
145    
146     /*
147     * Write the SSL/TLS certificate after asking the user to accept/reject it.
148     */
149     int
150     write_cert(X509 * cert)
151     {
152     FILE *fd;
153     char c, buf[LINE_MAX];
154 lefcha 1.2 char certf[PATH_MAX];
155 lefcha 1.1
156     do {
157     printf("(R)eject, accept (t)emporarily or "
158     "accept (p)ermanently? ");
159     fgets(buf, LINE_MAX, stdin);
160     c = tolower(*buf);
161     } while (c != 'r' && c != 't' && c != 'p');
162    
163     if (c == 'r')
164 lefcha 1.5 return CERT_ACTION_REJECT;
165 lefcha 1.1 else if (c == 't')
166 lefcha 1.5 return CERT_ACTION_ACCEPT;
167 lefcha 1.1
168 lefcha 1.5 snprintf(certf, PATH_MAX, "%s/%s", home, PATHNAME_CERTS);
169 lefcha 1.2 create_file(certf, S_IRUSR | S_IWUSR);
170 lefcha 1.1
171 lefcha 1.2 fd = fopen(certf, "a");
172 lefcha 1.1 if (fd == NULL)
173 lefcha 1.5 return CERT_ACTION_REJECT;
174 lefcha 1.1
175     PEM_write_X509(fd, cert);
176    
177     fclose(fd);
178    
179 lefcha 1.5 return CERT_ACTION_ACCEPT;
180 lefcha 1.1 }
181    
182    
183     /*
184 lefcha 1.6 * Ask user to proceed, while a fingerprint mismatch in the SSL/TLS certificate
185     * was found.
186 lefcha 1.1 */
187     int
188     mismatch_cert(void)
189     {
190     char c, buf[LINE_MAX];
191    
192     do {
193 lefcha 1.6 printf("ATTENTION: SSL/TLS certificate fingerprint mismatch.\n"
194 lefcha 1.1 "Proceed with the connection (y/n)? ");
195     fgets(buf, LINE_MAX, stdin);
196     c = tolower(*buf);
197     } while (c != 'y' && c != 'n');
198    
199     if (c == 'y')
200 lefcha 1.5 return CERT_ACTION_CONTINUE;
201 lefcha 1.1 else
202 lefcha 1.5 return CERT_ACTION_ABORT;
203 lefcha 1.1 }
204     #endif /* SSL_TLS */

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26