diff options
-rwxr-xr-x | vchat-tls.c | 90 |
1 files changed, 50 insertions, 40 deletions
diff --git a/vchat-tls.c b/vchat-tls.c index e6e4cc1..c4b014a 100755 --- a/vchat-tls.c +++ b/vchat-tls.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <stdlib.h> | 19 | #include <stdlib.h> |
20 | #include <string.h> | 20 | #include <string.h> |
21 | #include <assert.h> | 21 | #include <assert.h> |
22 | #include <errno.h> | ||
22 | 23 | ||
23 | #include <readline/readline.h> | 24 | #include <readline/readline.h> |
24 | 25 | ||
@@ -69,6 +70,52 @@ void vc_x509store_setcertfile(vc_x509store_t *store, char *file) { | |||
69 | store->flags |= VC_X509S_USE_CERTIFICATE; | 70 | store->flags |= VC_X509S_USE_CERTIFICATE; |
70 | } | 71 | } |
71 | 72 | ||
73 | static int verify_or_store_fingerprint(const char *fingerprint) { | ||
74 | char *fingerprint_file_path = tilde_expand(getstroption(CF_FINGERPRINT)); | ||
75 | if (!fingerprint_file_path) { | ||
76 | writecf(FS_ERR, "[SSL FINGERPRINT ] The CF_FINGERPRINT path is not set."); | ||
77 | return -1; | ||
78 | } | ||
79 | |||
80 | FILE *fingerprint_file = fopen(fingerprint_file_path, "r"); | ||
81 | if (fingerprint_file) { | ||
82 | /* Read fingerprint from file */ | ||
83 | char old_fingerprint[128]; | ||
84 | char * r = fgets(old_fingerprint, sizeof(old_fingerprint), fingerprint_file); | ||
85 | fclose(fingerprint_file); | ||
86 | |||
87 | if (r) { | ||
88 | /* chomp */ | ||
89 | char *nl = strchr(r, '\n'); | ||
90 | if (nl) *nl = 0; | ||
91 | |||
92 | /* verify fingerprint matches stored version */ | ||
93 | if (!strcmp(fingerprint, old_fingerprint)) | ||
94 | goto cleanup_happy; | ||
95 | } | ||
96 | |||
97 | snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] Found pinned fingerprint (in %s) %s but expected %s", r ? old_fingerprint : "<FILE READ ERROR>", getstroption(CF_FINGERPRINT), fingerprint); | ||
98 | writecf(FS_ERR, tmpstr); | ||
99 | writecf(FS_ERR, "[SSL CONNECT ERROR] Fingerprint mismatch! Server cert updated?"); | ||
100 | free(fingerprint_file_path); | ||
101 | return 1; | ||
102 | } else | ||
103 | writecf(FS_ERR, "[WARNING] No pinned Fingerprint found!"); | ||
104 | |||
105 | fingerprint_file = fopen(fingerprint_file_path, "w"); | ||
106 | if (!fingerprint_file) { | ||
107 | snprintf (tmpstr, TMPSTRSIZE, "[WARNING] Can't write fingerprint file, %s.", strerror(errno)); | ||
108 | writecf(FS_ERR, tmpstr); | ||
109 | } else { | ||
110 | fputs(fingerprint, fingerprint_file); | ||
111 | fclose(fingerprint_file); | ||
112 | writecf(FS_SERV, "Stored pinned fingerprint."); | ||
113 | } | ||
114 | cleanup_happy: | ||
115 | free(fingerprint_file_path); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
72 | #ifdef TLS_LIB_OPENSSL | 119 | #ifdef TLS_LIB_OPENSSL |
73 | 120 | ||
74 | #include <openssl/err.h> | 121 | #include <openssl/err.h> |
@@ -186,10 +233,9 @@ int vc_tls_connect( int serverfd, vc_x509store_t *vc_store ) | |||
186 | unsigned char fingerprint_bin[EVP_MAX_MD_SIZE]; | 233 | unsigned char fingerprint_bin[EVP_MAX_MD_SIZE]; |
187 | unsigned int fingerprint_len; | 234 | unsigned int fingerprint_len; |
188 | 235 | ||
189 | FILE *fingerprint_file = NULL; | ||
190 | char * fp = fingerprint; | 236 | char * fp = fingerprint; |
191 | 237 | ||
192 | long result, j; | 238 | long j; |
193 | 239 | ||
194 | if( !ctx ) | 240 | if( !ctx ) |
195 | goto all_errors; | 241 | goto all_errors; |
@@ -249,44 +295,8 @@ int vc_tls_connect( int serverfd, vc_x509store_t *vc_store ) | |||
249 | /* we don't need the peercert anymore */ | 295 | /* we don't need the peercert anymore */ |
250 | X509_free(peercert); | 296 | X509_free(peercert); |
251 | 297 | ||
252 | /* verify fingerprint */ | 298 | if (getintoption(CF_PINFINGER) && verify_or_store_fingerprint(fingerprint)) |
253 | if (getintoption(CF_PINFINGER)) { | 299 | return 1; |
254 | |||
255 | fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "r"); | ||
256 | if (fingerprint_file) { | ||
257 | |||
258 | /* Read fingerprint from file */ | ||
259 | char old_fingerprint[EVP_MAX_MD_SIZE*4]; | ||
260 | char * r = fgets(old_fingerprint, sizeof(old_fingerprint), fingerprint_file); | ||
261 | fclose(fingerprint_file); | ||
262 | |||
263 | if (r) { | ||
264 | /* chomp */ | ||
265 | char *nl = strchr(r, '\n'); | ||
266 | if (nl) *nl = 0; | ||
267 | |||
268 | /* verify fingerprint matches stored version */ | ||
269 | if (!strcmp(fingerprint, old_fingerprint)) | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] %s (from %s)", r ? old_fingerprint : "<FILE READ ERROR>", getstroption(CF_FINGERPRINT)); | ||
274 | writecf(FS_ERR, tmpstr); | ||
275 | writecf(FS_ERR, "[SSL CONNECT ERROR] Fingerprint mismatch! Server cert updated?"); | ||
276 | return 1; | ||
277 | } | ||
278 | |||
279 | fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "w"); | ||
280 | if (!fingerprint_file) { | ||
281 | snprintf (tmpstr, TMPSTRSIZE, "[WARNING] Can't write fingerprint file, %s.", strerror(errno)); | ||
282 | writecf(FS_ERR, tmpstr); | ||
283 | } else { | ||
284 | fputs(fingerprint, fingerprint_file); | ||
285 | fclose(fingerprint_file); | ||
286 | writecf(FS_SERV, "Stored fingerprint."); | ||
287 | } | ||
288 | return 0; | ||
289 | } | ||
290 | 300 | ||
291 | /* If verify of x509 chain was requested, do the check here */ | 301 | /* If verify of x509 chain was requested, do the check here */ |
292 | if (X509_V_OK == SSL_get_verify_result(sslp)) | 302 | if (X509_V_OK == SSL_get_verify_result(sslp)) |