]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
openconnect_check_peer_cert_hash: allow partial server hash matches
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 1 Nov 2016 08:32:31 +0000 (09:32 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Tue, 13 Dec 2016 10:42:07 +0000 (10:42 +0000)
That is allow the user specifying a small part of the hash (e.g., 'sha256:6429')
in order to be able to connect. This is to ease test connections, when copy-paste
is not possible.

[dwmw2: Fix man page to say 'at least 4 characters' not 'more than']

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
library.c
openconnect.8.in

index 3fb8cb3319ce3d7f9ecf68bf356ef439817c4e36..824338e10937a501c05c5103070477909e332ed8 100644 (file)
--- a/library.c
+++ b/library.c
@@ -941,12 +941,17 @@ int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo,
 {
        char sha1_text[41];
        const char *fingerprint;
+       unsigned min_match_len;
+       unsigned real_min_match_len = 4;
+       unsigned old_len, fingerprint_len;
 
        if (strchr(old_hash, ':')) {
                if (strncmp(old_hash, "sha1:", 5) == 0) {
                        fingerprint = vpninfo->peer_cert_sha1;
+                       min_match_len = real_min_match_len + sizeof("sha1:")-1;
                } else if (strncmp(old_hash, "sha256:", 7) == 0) {
                        fingerprint = vpninfo->peer_cert_sha256;
+                       min_match_len = real_min_match_len + sizeof("sha256:")-1;
                } else {
                        vpn_progress(vpninfo, PRG_ERR, _("Unknown certificate hash: %s.\n"), old_hash);
                        return -EIO;
@@ -970,10 +975,24 @@ int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo,
                        sprintf(&sha1_text[i*2], "%02x", sha1_bin[i]);
 
                fingerprint = sha1_text;
+               min_match_len = real_min_match_len;
        }
 
-       if (strcasecmp(old_hash, fingerprint))
-               return 1;
+       old_len = strlen(old_hash);
+       fingerprint_len = strlen(fingerprint);
+
+       /* allow partial matches */
+       if (old_len < fingerprint_len) {
+               if (strncasecmp(old_hash, fingerprint, MAX(min_match_len, old_len))) {
+                       if (old_len < min_match_len) {
+                               vpn_progress(vpninfo, PRG_ERR, _("The size of the provided fingerprint is less than the minimum required (%u).\n"), real_min_match_len);
+                       }
+                       return 1;
+               }
+       } else {
+               if (strcasecmp(old_hash, fingerprint))
+                       return 1;
+       }
 
        return 0;
 }
index d36026cf0ed2e2db338fe41e53642b5b79328daf..b7e2bfc0be6583bfa2fea611398ff1d59f94be09 100644 (file)
@@ -475,9 +475,15 @@ to
 .IR IP
 instead of using the normal resolver to look it up.
 .TP
-.B \-\-servercert=SHA1
-Accept server's SSL certificate only if its fingerprint matches
-.IR SHA1 .
+.B \-\-servercert=HASH
+Accept server's SSL certificate only if the provided fingerprint matches.
+The allowed fingerprint types are
+.IR SHA1 ,
+and
+.IR SHA256 .
+They are distinguished by the 'sha1:' or 'sha256:' prefixes to the hex encoded
+hash. To ease certain testing use-cases, a partial match of the hash will also
+be accepted, if it is at least 4 characters.
 .TP
 .B \-\-useragent=STRING
 Use