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

Contents of /imapfilter/cert.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show 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 #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