Rewrite ssl_manager cert filename parsing to allow for ipv6 addresses.
authorAndrej Kacian <ticho@claws-mail.org>
Fri, 21 Apr 2017 15:57:04 +0000 (17:57 +0200)
committerAndrej Kacian <ticho@claws-mail.org>
Fri, 21 Apr 2017 15:57:04 +0000 (17:57 +0200)
src/ssl_manager.c

index d5086a9..fb6c4c5 100644 (file)
@@ -213,60 +213,44 @@ void ssl_manager_create(void)
        gtk_widget_show(window);
 }
 
-static char *get_server(const char *str)
+static gboolean get_serverport(const gchar *str, gchar **server, gchar **port)
 {
-       char *ret = NULL, *tmp = g_strdup(str);
-       char *first_pos = NULL, *last_pos = NULL;
-       char *previous_pos = NULL, *pre_previous_pos = NULL;
-       int previous_dot_pos;
-
-       if (!strchr(tmp, ':')) {
-               /* no fingerprint */
-               if (strstr(tmp, ".cert"))
-                       *(strstr(tmp, ".cert")+1) = '.';
+       const gchar *pos, *prevpos;
+
+       g_return_val_if_fail(str != NULL, FALSE);
+
+       for (prevpos = str, pos = strstr(str, ".") + 1;
+                       pos != NULL;
+                       prevpos = pos, pos = strstr(pos, ".") + 1) {
+               if (!strcmp(pos, "cert") || !strcmp(pos, "cert.chain")) {
+                       *server = strndup(str, prevpos - str - 1);
+                       *port = strndup(prevpos, pos - prevpos - 1);
+                       return TRUE;
+               }
        }
 
-       first_pos = tmp;
-       while (tmp && (tmp = strstr(tmp,".")) != NULL) {
-               tmp++;
-               pre_previous_pos = previous_pos;
-               previous_pos = last_pos;
-               last_pos = tmp;
-       }
-       previous_dot_pos = (pre_previous_pos - first_pos);
-       if (previous_dot_pos - 1 > 0)
-               ret = g_strndup(first_pos, previous_dot_pos - 1);
-       else 
-               ret = g_strdup(first_pos);
-       g_free(first_pos);
-       return ret;
+       return FALSE;
 }
 
 static char *get_port(const char *str)
 {
-       char *ret = NULL, *tmp = g_strdup(str);
-       char *last_pos = NULL;
-       char *previous_pos = NULL, *pre_previous_pos = NULL;
-
-       if (!strchr(tmp, ':')) {
-               /* no fingerprint */
-               if (strstr(tmp, ".cert"))
-                       *(strstr(tmp, ".cert")+1) = '.';
+       const char *pos, *prevpos;
+       char *port;
+
+       g_return_val_if_fail(str != NULL, NULL);
+
+       /* Iterate through all '.'-separated chunks, and the last one
+        * before the .cert or .cert.chain suffix is the port number. */
+       for (prevpos = str, pos = strstr(str, ".") + 1;
+                       pos != NULL;
+                       prevpos = pos, pos = strstr(pos, ".") + 1) {
+               if (!strcmp(pos, "cert") || !strcmp(pos, "cert.chain")) {
+                       port = strndup(prevpos, pos - prevpos - 1);
+                       return port;
+               }
        }
 
-       while (tmp && (tmp = strstr(tmp,".")) != NULL) {
-               tmp++;
-               pre_previous_pos = previous_pos;
-               previous_pos = last_pos;
-               last_pos = tmp;
-       }
-       if (previous_pos && pre_previous_pos && (int)(previous_pos - pre_previous_pos - 1) > 0)
-               ret = g_strndup(pre_previous_pos, (int)(previous_pos - pre_previous_pos - 1));
-       else
-               ret = g_strdup("0");
-       g_free(tmp);
-       return ret;
-       
+       return NULL;
 }
 
 static char *get_fingerprint(const char *str)
@@ -346,14 +330,13 @@ static void ssl_manager_load_certs (void)
        }
        
        while ((d = g_dir_read_name(dir)) != NULL) {
-               gchar *server, *port, *fp;
+               gchar *server = NULL, *port = NULL, *fp = NULL;
                SSLCertificate *cert;
 
                if(strstr(d, ".cert") != d + (strlen(d) - strlen(".cert"))) 
                        continue;
 
-               server = get_server(d);
-               port = get_port(d);
+               get_serverport(d, &server, &port);
                fp = get_fingerprint(d);
                
                cert = ssl_certificate_find(server, atoi(port), fp);