From ddc90b6f74481d89d0191c85a2b21bbd5d6278e6 Mon Sep 17 00:00:00 2001 From: Ryan Bunker Date: Sat, 30 Nov 2024 13:04:55 -0600 Subject: [PATCH] Allow selecting client cert when multiple match --- qutebrowser/browser/webengine/webenginetab.py | 76 ++++++++++++++----- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 04ed7c409..98b6609de 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -1635,27 +1635,67 @@ class WebEngineTab(browsertab.AbstractTab): Currently, we simply pick the first available certificate and show an additional note if there are multiple matches. """ - certificate = selection.certificates()[0] - text = ('Subject: {subj}
' - 'Issuer: {issuer}
' - 'Serial: {serial}'.format( - subj=html_utils.escape(certificate.subjectDisplayName()), - issuer=html_utils.escape(certificate.issuerDisplayName()), - serial=bytes(certificate.serialNumber()).decode('ascii'))) - if len(selection.certificates()) > 1: - text += ('

Note: Multiple matching certificates ' - 'were found, but certificate selection is not ' - 'implemented yet!') urlstr = selection.host().host() + if len(selection.certificates()) > 1: + errmsg = "" + while True: + text = "Multiple matching certificates were found, select the one to present.

" + for index, cert in enumerate(selection.certificates()): + text += ('Certificate #{index}
' + 'Subject: {subj}
' + 'Issuer: {issuer}
' + 'Serial: {serial}

'.format( + index=index+1, + subj=html_utils.escape(cert.subjectDisplayName()), + issuer=html_utils.escape(cert.issuerDisplayName()), + serial=bytes(cert.serialNumber()).decode('ascii'))) - present = message.ask( - title='Present client certificate to {}?'.format(urlstr), - text=text, - mode=usertypes.PromptMode.yesno, - abort_on=[self.abort_questions], - url=urlstr) + text += errmsg + "Enter the number of the certificate to present." - if present: + select = message.ask( + title='Select client certificate', + text=text, + mode=usertypes.PromptMode.text, + abort_on=[self.abort_questions], + url=urlstr) + + if select is not None and select.startswith("#"): + select = select[1:] + + if select is None: + index = None + break + elif select.isdigit(): + index = int(select) + if index > 0 and index <= len(selection.certificates()): + break + + errmsg = "Invalid selection, try again. " + + if index is not None: + certificate = selection.certificates()[index - 1] + else: + certificate = None + + else: + certificate = selection.certificates()[0] + text = ('Subject: {subj}
' + 'Issuer: {issuer}
' + 'Serial: {serial}'.format( + subj=html_utils.escape(certificate.subjectDisplayName()), + issuer=html_utils.escape(certificate.issuerDisplayName()), + serial=bytes(certificate.serialNumber()).decode('ascii'))) + + present = message.ask( + title='Present client certificate to {}?'.format(urlstr), + text=text, + mode=usertypes.PromptMode.yesno, + abort_on=[self.abort_questions], + url=urlstr) + + certificate = None if not present else certificate + + if certificate is not None: selection.select(certificate) else: selection.selectNone()