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

Annotation of /imapfilter/cert.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Thu Jul 31 15:46:02 2003 UTC (20 years, 8 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_9
Branch point for: release-0_9-patches
File MIME type: text/plain
Broke up program files and created some new header files.

1 lefcha 1.1 #include <stdio.h>
2     #include <string.h>
3     #include <ctype.h>
4     #include <limits.h>
5     #include <sys/types.h>
6     #include <sys/stat.h>
7     #include <fcntl.h>
8    
9     #include "config.h"
10     #include "imapfilter.h"
11     #include "pathnames.h"
12    
13     #ifdef SSL_TLS
14     #include <openssl/ssl.h>
15     #include <openssl/x509.h>
16     #include <openssl/pem.h>
17    
18    
19     extern unsigned int options;
20     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     get_cert(conn_t * conn)
35     {
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     case SSL_CERT_NONEXISTENT:
50     print_cert(cert, md, &mdlen);
51     if (flags & FLAG_DAEMON_MODE ||
52     write_cert(cert) == SSL_CERT_ACTION_REJECT)
53     goto abort;
54     break;
55     case SSL_CERT_MISMATCH:
56     print_cert(cert, md, &mdlen);
57     if (flags & FLAG_DAEMON_MODE ||
58     mismatch_cert() == SSL_CERT_ACTION_ABORT)
59     goto abort;
60     break;
61     case SSL_CERT_OK:
62     if (options & OPTION_DETAILS_VERBOSE)
63     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     X509 *cert;
84     unsigned char md[EVP_MAX_MD_SIZE];
85     unsigned int mdlen;
86    
87     r = SSL_CERT_NONEXISTENT;
88     cert = NULL;
89    
90     if (!exists_file(PATHNAME_CERT_FILE))
91     return SSL_CERT_NONEXISTENT;
92    
93     fd = fopen(PATHNAME_CERT_FILE, "r");
94     if (fd == NULL)
95     return ERROR_FILE_OPEN;
96    
97     while ((cert = PEM_read_X509(fd, &cert, NULL, NULL)) != NULL) {
98     if (X509_subject_name_cmp(cert, pcert) != 0 ||
99     X509_issuer_name_cmp(cert, pcert) != 0)
100     continue;
101    
102     if (!X509_digest(cert, EVP_md5(), md, &mdlen) ||
103     *pmdlen != mdlen)
104     continue;
105    
106     if (memcmp(pmd, md, mdlen) != 0) {
107     r = SSL_CERT_MISMATCH;
108     break;
109     }
110     r = SSL_CERT_OK;
111     break;
112     }
113    
114     fclose(fd);
115     X509_free(cert);
116    
117     return r;
118     }
119    
120    
121     /*
122     * Print information about the SSL/TLS certificate.
123     */
124     void
125     print_cert(X509 * cert, unsigned char *md, unsigned int *mdlen)
126     {
127     unsigned int i;
128     char *c;
129    
130     c = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
131     printf("Server certificate subject: %s\n", c);
132     xfree(c);
133    
134     c = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
135     printf("Server certificate issuer: %s\n", c);
136     xfree(c);
137    
138     printf("Server key fingerprint: ");
139     for (i = 0; i < *mdlen; i++)
140     printf(i != *mdlen - 1 ? "%02X:" : "%02X\n", md[i]);
141     }
142    
143    
144     /*
145     * Write the SSL/TLS certificate after asking the user to accept/reject it.
146     */
147     int
148     write_cert(X509 * cert)
149     {
150     FILE *fd;
151     char c, buf[LINE_MAX];
152    
153     do {
154     printf("(R)eject, accept (t)emporarily or "
155     "accept (p)ermanently? ");
156     fgets(buf, LINE_MAX, stdin);
157     c = tolower(*buf);
158     } while (c != 'r' && c != 't' && c != 'p');
159    
160     if (c == 'r')
161     return SSL_CERT_ACTION_REJECT;
162     else if (c == 't')
163     return SSL_CERT_ACTION_ACCEPT;
164    
165     create_file(PATHNAME_CERT_FILE, S_IRUSR | S_IWUSR);
166    
167     fd = fopen(PATHNAME_CERT_FILE, "a");
168     if (fd == NULL)
169     return SSL_CERT_ACTION_REJECT;
170    
171     PEM_write_X509(fd, cert);
172    
173     fclose(fd);
174    
175     return SSL_CERT_ACTION_ACCEPT;
176     }
177    
178    
179     /*
180     * Ask user to proceed, while a fingerprint mismatch in the SSL/TLS
181     * certificate was found.
182     */
183     int
184     mismatch_cert(void)
185     {
186     char c, buf[LINE_MAX];
187    
188     do {
189     printf("WARNING: SSL/TLS certificate fingerprint mismatch.\n"
190     "Proceed with the connection (y/n)? ");
191     fgets(buf, LINE_MAX, stdin);
192     c = tolower(*buf);
193     } while (c != 'y' && c != 'n');
194    
195     if (c == 'y')
196     return SSL_CERT_ACTION_CONTINUE;
197     else
198     return SSL_CERT_ACTION_ABORT;
199     }
200     #endif /* SSL_TLS */

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26