talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 85e51d737624dc20140bca28ce35e11456b97cba
parent a2f80ff8b7ddd630c1f9ce675fc8d2742faa798a
Author: wwp <subscript@free.fr>
Date:   Mon, 17 Dec 2018 21:11:19 +0100

Fix parsing of cert filename, prevent the Tools / SSL/TLS Certificates dialog from crashing when cert filenames contain a fingerprint. Move the parser func to utils.[ch].

Diffstat:
Msrc/common/utils.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/common/utils.h | 2++
Msrc/ssl_manager.c | 81+++++++++++++++----------------------------------------------------------------
3 files changed, 74 insertions(+), 66 deletions(-)

diff --git a/src/common/utils.c b/src/common/utils.c @@ -4611,3 +4611,60 @@ get_random_bytes(void *buf, size_t count) return TRUE; } + +/* returns FALSE if parsing failed, otherwise returns TRUE and sets *server, *port + and eventually *fp from filename (if not NULL, they must be free'd by caller after + user. + filenames we expect: 'host.name.port.cert' or 'host.name.port.f:i:n:g:e:r:p:r:i:n:t.cert' */ +gboolean get_serverportfp_from_filename(const gchar *str, gchar **server, gchar **port, gchar **fp) +{ + const gchar *pos, *dotport_pos = NULL, *dotcert_pos = NULL, *dotfp_pos = NULL; + + g_return_val_if_fail(str != NULL, FALSE); + + pos = str + strlen(str) - 1; + while ((pos > str) && !dotport_pos) { + if (*pos == '.') { + if (!dotcert_pos) { + /* match the .cert suffix */ + if (strcmp(pos, ".cert") == 0) { + dotcert_pos = pos; + } + } else { + if (!dotfp_pos) { + /* match an eventual fingerprint */ + /* or the port number */ + if (strncmp(pos + 3, ":", 1) == 0) { + dotfp_pos = pos; + } else { + dotport_pos = pos; + } + } else { + /* match the port number */ + dotport_pos = pos; + } + } + } + pos--; + } + if (!dotport_pos || !dotcert_pos) { + g_warning("could not parse filename %s", str); + return FALSE; + } + + *server = g_strndup(str, dotport_pos - str); + if (dotfp_pos) { + *port = g_strndup(dotport_pos + 1, dotfp_pos - dotport_pos - 1); + *fp = g_strndup(dotfp_pos + 1, dotcert_pos - dotfp_pos - 1); + } else { + *port = g_strndup(dotport_pos + 1, dotcert_pos - dotport_pos - 1); + *fp = NULL; + } + + debug_print("filename='%s' => server='%s' port='%s' fp='%s'\n", str, *server, *port, *fp); + if (!*server || !*port) + return FALSE; + else + return TRUE; +} + diff --git a/src/common/utils.h b/src/common/utils.h @@ -541,4 +541,6 @@ gboolean get_random_bytes(void *buf, size_t count); } #endif +gboolean get_serverportfp_from_filename(const gchar *str, gchar **server, gchar **port, gchar **fp); + #endif /* __UTILS_H__ */ diff --git a/src/ssl_manager.c b/src/ssl_manager.c @@ -164,7 +164,6 @@ static GtkWidget *ssl_manager_list_view_create (void) ssl_manager_create_list_view_columns(GTK_WIDGET(list_view)); return GTK_WIDGET(list_view); - } void ssl_manager_create(void) @@ -240,58 +239,6 @@ void ssl_manager_create(void) gtk_widget_show(window); } -static gboolean get_serverport(const gchar *str, gchar **server, gchar **port) -{ - const gchar *pos, *prevpos; - - g_return_val_if_fail(str != NULL, FALSE); - - /* We expect 'host.name.port.cert' here, only set - * server and port if we find that. - * Validity of string in port should be checked by caller. */ - for (prevpos = str, pos = strstr(str, "."); - pos != NULL; - prevpos = pos, pos = strstr(pos+1, ".")) { - if (!strcmp(pos, ".cert")) { - if (prevpos > str) { - *server = g_strndup(str, prevpos - str); - *port = g_strndup(prevpos+1, pos - prevpos - 1); - } else { - *server = *port = NULL; - } - - return TRUE; - } - } - - return FALSE; -} - -static char *get_fingerprint(const char *str) -{ - char *ret = NULL, *tmp = g_strdup(str), *tmp2 = tmp; - char *previous_pos = NULL, *last_pos = NULL; - - if (!strchr(tmp, ':')) { - /* no fingerprint */ - if (strstr(tmp, ".cert")) - *(strstr(tmp, ".cert")+1) = '.'; - } - - while (tmp2 && (tmp2 = strstr(tmp2,".")) != NULL) { - tmp2++; - previous_pos = last_pos; - last_pos = tmp2; - } - if (last_pos && previous_pos && (int)(last_pos - previous_pos - 1) > 0) - ret = g_strndup(previous_pos, (int)(last_pos - previous_pos - 1)); - else - ret = NULL; - g_free(tmp); - return ret; - -} - static void ssl_manager_list_view_insert_cert(GtkWidget *list_view, GtkTreeIter *row_iter, gchar *host, @@ -307,6 +254,8 @@ static void ssl_manager_list_view_insert_cert(GtkWidget *list_view, GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(list_view))); + g_return_if_fail(cert != NULL); + exp_time_t = gnutls_x509_crt_get_expiration_time(cert->x509_cert); memset(buf, 0, sizeof(buf)); @@ -321,7 +270,7 @@ static void ssl_manager_list_view_insert_cert(GtkWidget *list_view, sig_status = ssl_certificate_check_signer(cert, cert->status); - if (sig_status==NULL) + if (sig_status == NULL) sig_status = g_strdup_printf(_("Correct%s"),exp_time_t < time(NULL)? _(" (expired)"): ""); else { weight = PANGO_WEIGHT_BOLD; @@ -380,21 +329,21 @@ static void ssl_manager_load_certs (void) if(strstr(d, ".cert") != d + (strlen(d) - strlen(".cert"))) continue; - get_serverport(d, &server, &port); - fp = get_fingerprint(d); + if (get_serverportfp_from_filename(d, &server, &port, &fp)) { - if (server != NULL && port != NULL) { - gint portnum = atoi(port); - if (portnum > 0 && portnum <= 65535) { - cert = ssl_certificate_find(server, portnum, fp); - ssl_manager_list_view_insert_cert(manager.certlist, NULL, - server, port, cert); + if (server != NULL && port != NULL) { + gint portnum = atoi(port); + if (portnum > 0 && portnum <= 65535) { + cert = ssl_certificate_find(server, portnum, fp); + ssl_manager_list_view_insert_cert(manager.certlist, NULL, + server, port, cert); + } } - } - g_free(server); - g_free(port); - g_free(fp); + g_free(server); + g_free(port); + g_free(fp); + } row++; } g_dir_close(dir);