summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kotes <count@flatline.de>2014-04-16 16:27:00 +0200
committerAndreas Kotes <count@flatline.de>2014-04-16 16:27:00 +0200
commit3297473435ad53b6691d6c772f83457a72134c48 (patch)
tree9692f248fc19db010839f6c943a9c40809dcc340
parentedba804a0cbd19e5c971c55661bcf83967573906 (diff)
store & verify server cert fingerprint
-rwxr-xr-xvchat-config.h1
-rwxr-xr-xvchat-ssl.c75
-rwxr-xr-xvchat.h2
3 files changed, 72 insertions, 6 deletions
diff --git a/vchat-config.h b/vchat-config.h
index 2628dc1..0291100 100755
--- a/vchat-config.h
+++ b/vchat-config.h
@@ -38,6 +38,7 @@ static volatile configoption configoptions[] = {
38 {CF_KEYFILE, CO_STR, "keyfile", "~/.vchat/key", NULL, { NULL } }, 38 {CF_KEYFILE, CO_STR, "keyfile", "~/.vchat/key", NULL, { NULL } },
39 {CF_FORMFILE, CO_STR, "formatfile", "~/.vchat/formats", NULL, { NULL } }, 39 {CF_FORMFILE, CO_STR, "formatfile", "~/.vchat/formats", NULL, { NULL } },
40 {CF_LOGINSCRIPT, CO_STR, "loginscript","~/.vchat/loginscript", NULL, { NULL } }, 40 {CF_LOGINSCRIPT, CO_STR, "loginscript","~/.vchat/loginscript", NULL, { NULL } },
41 {CF_FINGERPRINT, CO_STR, "fingerprint","~/.vchat/fingerprint", NULL, { NULL } },
41 {CF_ENCODING, CO_STR, "encoding", NULL, NULL, { .pstr = &encoding }}, 42 {CF_ENCODING, CO_STR, "encoding", NULL, NULL, { .pstr = &encoding }},
42 {CF_USESSL, CO_INT, "usessl", (char *) 1, (char *)-1, { NULL } }, 43 {CF_USESSL, CO_INT, "usessl", (char *) 1, (char *)-1, { NULL } },
43 {CF_VERIFYSSL, CO_INT, "verifyssl", (char *) 2, (char *)-1, { NULL } }, 44 {CF_VERIFYSSL, CO_INT, "verifyssl", (char *) 2, (char *)-1, { NULL } },
diff --git a/vchat-ssl.c b/vchat-ssl.c
index 68e3699..d240cbd 100755
--- a/vchat-ssl.c
+++ b/vchat-ssl.c
@@ -153,16 +153,81 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store )
153 cipher = SSL_get_current_cipher(sslp); 153 cipher = SSL_get_current_cipher(sslp);
154 if (cipher) { 154 if (cipher) {
155 char cipher_desc[TMPSTRSIZE]; 155 char cipher_desc[TMPSTRSIZE];
156 snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); 156 snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE));
157 writecf(FS_SERV, tmpstr); 157 writecf(FS_SERV, tmpstr);
158 } else { 158 } else {
159 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] Cipher not known / SSL object can't be queried!"); 159 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR ] Cipher not known / SSL object can't be queried!");
160 writecf(FS_ERR, tmpstr); 160 writecf(FS_ERR, tmpstr);
161 } 161 }
162 162
163 /* Accept being connected, _if_ verification passed */ 163 /* Accept being connected, _if_ verification passed */
164 if (sslp && SSL_get_verify_result(sslp) == X509_V_OK) 164 if (sslp) {
165 return 0; 165 long result = SSL_get_verify_result(sslp);
166
167 /* show & verify fingerprint */
168 if (result == X509_V_OK) {
169 X509 *peercert = SSL_get_peer_certificate(sslp);
170
171 /* FIXME: this IS bad code */
172 char new_fingerprint[TMPSTRSIZE] = "";
173 char old_fingerprint[TMPSTRSIZE] = "";
174 FILE *fingerprint_file = NULL;
175
176 unsigned int fingerprint_len;
177 unsigned char fingerprint_bin[EVP_MAX_MD_SIZE];
178
179 /* show basic information about peer cert */
180 snprintf(tmpstr, TMPSTRSIZE, "[SSL SUBJECT ] %s", X509_NAME_oneline(X509_get_subject_name(peercert),0,0));
181 writecf(FS_SERV, tmpstr);
182 snprintf(tmpstr, TMPSTRSIZE, "[SSL ISSUER ] %s", X509_NAME_oneline(X509_get_issuer_name(peercert),0,0));
183 writecf(FS_SERV, tmpstr);
184
185 /* calculate fingerprint */
186 if (X509_digest(peercert,EVP_sha1(),fingerprint_bin,&fingerprint_len)) {
187 char shorttmpstr[3] = "XX";
188 int j;
189 for (j=0; j<(int)fingerprint_len; j++) {
190 if (j)
191 strncat(new_fingerprint, ":", TMPSTRSIZE);
192 snprintf(shorttmpstr, 3, "%02X", fingerprint_bin[j]);
193 strncat(new_fingerprint, shorttmpstr, TMPSTRSIZE);
194 }
195 snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] from server: %s", new_fingerprint);
196 writecf(FS_SERV, tmpstr);
197 }
198
199 // we don't need the peercert anymore
200 X509_free(peercert);
201
202 fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "r");
203 if (fingerprint_file) {
204 fgets(old_fingerprint, TMPSTRSIZE, fingerprint_file);
205 fclose(fingerprint_file);
206
207 /* verify fingerprint matches stored version */
208 if (!strncmp(new_fingerprint, old_fingerprint, TMPSTRSIZE))
209 return 0;
210 else {
211 snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] from %s: %s", getstroption(CF_FINGERPRINT), old_fingerprint);
212 writecf(FS_ERR, tmpstr);
213 writecf(FS_ERR, "[SSL CONNECT ERROR] Fingerprint mismatch! Server cert updated?");
214 return 1;
215 }
216 } else {
217 /* FIXME: there might be other errors than missing file */
218 fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "w");
219 if (!fingerprint_file) {
220 snprintf (tmpstr, TMPSTRSIZE, "Can't write fingerprint file, %s.", strerror(errno));
221 writecf(FS_ERR, tmpstr);
222 } else {
223 fputs(new_fingerprint, fingerprint_file);
224 fclose(fingerprint_file);
225 writecf(FS_SERV, "Stored fingerprint.");
226 return 0;
227 }
228 }
229 }
230 }
166 } 231 }
167 } 232 }
168 233
@@ -236,7 +301,7 @@ X509_STORE *vc_x509store_create(vc_x509store_t *vc_store)
236int vc_verify_callback(int ok, X509_STORE_CTX *store) 301int vc_verify_callback(int ok, X509_STORE_CTX *store)
237{ 302{
238 if(!ok) { 303 if(!ok) {
239 snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR] %s", 304 snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR ] %s",
240 X509_verify_cert_error_string(store->error)); 305 X509_verify_cert_error_string(store->error));
241 writecf(FS_ERR, tmpstr); 306 writecf(FS_ERR, tmpstr);
242 } 307 }
diff --git a/vchat.h b/vchat.h
index a0797d5..16ee181 100755
--- a/vchat.h
+++ b/vchat.h
@@ -30,7 +30,7 @@ typedef struct servermessage servermessage;
30/* configuration types and variable numbers */ 30/* configuration types and variable numbers */
31typedef enum { CO_NIL, CO_STR, CO_INT } conftype; 31typedef enum { CO_NIL, CO_STR, CO_INT } conftype;
32typedef enum { CF_NIL, CF_NICK, CF_FROM, CF_SERVERHOST, CF_SERVERPORT, 32typedef enum { CF_NIL, CF_NICK, CF_FROM, CF_SERVERHOST, CF_SERVERPORT,
33CF_CIPHERSUITE, CF_CONFIGFILE, CF_CERTFILE, CF_KEYFILE, CF_FORMFILE, CF_LOGINSCRIPT, 33CF_CIPHERSUITE, CF_CONFIGFILE, CF_CERTFILE, CF_KEYFILE, CF_FORMFILE, CF_LOGINSCRIPT, CF_FINGERPRINT,
34CF_USESSL, CF_VERIFYSSL, CF_USECERT, CF_PRIVHEIGHT, CF_PRIVCOLLAPS, CF_HSCROLL, CF_CHANNEL, CF_USETIME, 34CF_USESSL, CF_VERIFYSSL, CF_USECERT, CF_PRIVHEIGHT, CF_PRIVCOLLAPS, CF_HSCROLL, CF_CHANNEL, CF_USETIME,
35CF_USETOPIC, CF_SCROLLBPRIV, CF_SCROLLBACK, CF_SCROLLBPRIVT, CF_SCROLLBACKT, 35CF_USETOPIC, CF_SCROLLBPRIV, CF_SCROLLBACK, CF_SCROLLBPRIVT, CF_SCROLLBACKT,
36CF_ENCODING, CF_BELLPRIV, CF_CASEFIRST, CF_AUTORECONN, CF_KEEPALIVE } confopt; 36CF_ENCODING, CF_BELLPRIV, CF_CASEFIRST, CF_AUTORECONN, CF_KEEPALIVE } confopt;