Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New command x509-swoop #42

Merged
merged 7 commits into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Open a certificate, either PEM or DER encoded, in a buffer.

M-x x509-dwim

A new buffer should display the parsed certificate.
A new buffer displays the parsed certificate.

To view certificates, CRLs, private and public keys Diffie-Hellman parameters, certificate requests, pkcs7 files and parsed ASN.1 respectively:
To view certificates, CRLs, private and public keys Diffie-Hellman parameters, elliptic curve parameters, certificate requests, pkcs7 files and parsed ASN.1 respectively:

M-x x509-viewcert
M-x x509-viewcrl
Expand All @@ -31,7 +31,7 @@ back to `x509-viewasn1`.

M-x x509-dwim

The command line for all command can be edited with C-u prefix. Example:
The command line for all of the above commands can be edited with C-u prefix. Example:

C-u M-x x509-viewcert

Expand All @@ -40,6 +40,10 @@ Commands operate on PEM data around point by default. If point is in
is considered. If no PEM region is found, either around point or in buffer,
then the buffer is assumed to be DER encoded.

There is special command, `x509-swoop`, that has different semantics than those above. It searches the whole buffer for _all_ recognized PEM regions and parses them one by one. The output of all regions are sent to the same buffer. The result buffer does not have the capabilities of a normal `x509-buffer`. There is no way to edit command line argument, toggle to `x509-asn1-mode` or move to next/previous region. `x509-swoop` intended to be used on PEM-coded certificate chain files.

M-x x509-swoop

### Key bindings

**e** edit the current command.
Expand Down
7 changes: 5 additions & 2 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- eval: (ethan-wspace-mode -1); -*-
# openssl/crypto/x509/t_x509.c
Certificate:
Data:
Expand Down Expand Up @@ -154,10 +155,12 @@ DH Parameters:

# encode_key2text.c
EC-Parameters:
GROUP:

# eck_prn.c ECPKParameters_print
A:
B:
# NOTE: There is SPC after these so that they are not matched in hex strings
A:
B:

# openssl/crypto/x509v3/v3_bcons.c
# X509V3_add_value_bool
Expand Down
74 changes: 38 additions & 36 deletions testfiles/multi.pem
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,31 @@ Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEyDCCA7CgAwIBAgIQDPW9BitWAvR6uFAsI8zwZjANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0yMTAzMzAwMDAwMDBaFw0zMTAzMjkyMzU5NTlaMFkxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMzAxBgNVBAMTKkRpZ2lDZXJ0IEdsb2Jh
bCBHMiBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMz3EGJPprtjb+2QUlbFbSd7ehJWivH0+dbn4Y+9lavyYEEV
cNsSAPonCrVXOFt9slGTcZUOakGUWzUb+nv6u8W+JDD+Vu/E832X4xT1FE3LpxDy
FuqrIvAxIhFhaZAmunjZlx/jfWardUSVc8is/+9dCopZQ+GssjoP80j812s3wWPc
3kbW20X+fSP9kOhRBx5Ro1/tSUZUfyyIxfQTnJcVPAPooTncaQwywa8WV0yUR0J8
osicfebUTVSvQpmowQTCd5zWSOTOEeAqgJnwQ3DPP3Zr0UxJqyRewg2C/Uaoq2yT
zGJSQnWS+Jr6Xl6ysGHlHx+5fwmY6D36g39HaaECAwEAAaOCAYIwggF+MBIGA1Ud
EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHSFgMBmx9833s+9KTeqAx2+7c0XMB8G
A1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA4GA1UdDwEB/wQEAwIBhjAd
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYIKwYBBQUHAQEEajBoMCQG
CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQAYIKwYBBQUHMAKG
NGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RH
Mi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29t
L0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDA9BgNVHSAENjA0MAsGCWCGSAGG/WwC
ATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgGBmeBDAECAzANBgkqhkiG
9w0BAQsFAAOCAQEAkPFwyyiXaZd8dP3A+iZ7U6utzWX9upwGnIrXWkOH7U1MVl+t
wcW1BSAuWdH/SvWgKtiwla3JLko716f2b4gp/DA/JIS7w7d7kwcsr4drdjPtAFVS
slme5LnQ89/nD/7d+MS5EHKBCQRfz5eeLjJ1js+aWNJXMX43AYGyZm0pGrFmCW3R
bpD0ufovARTFXFZkAdl9h6g4U5+LXUZtXMYnhIHUfoyMo5tS58aI7Dd8KvvwVVo4
chDYABPPTHPbqjc1qCmBaZx2vN4Ye5DUys/vZwP9BFohFrH/6j/f3IL16/RZkiMN
JCqVJUzKoZHm1Lesh3Sz8W2jmdv51b2EQJ8HmA==
-----END CERTIFICATE-----

-----BEGIN JUNK-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
-----BEGIN END-----

-----BEGIN CERTIFICATE REQUEST-----
MIICyDCCAbACAQAwPDEaMBgGA1UEAwwRQ0EgVGVzdFRvb2wgQ0EgMDExHjAcBgNV
BAoMFUNBIFRlc3RUb29sIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBANSZMZbKEIrK3B3O8T6pxctV+FT96RktoozzQoBZ+1DMSdAQZnpz
BHWPRZvjtgb/pZh9FeI5WvR1tjuaETxs+RbCrUfhSIdEa/FGt034A1RDkJRYyxgy
aflwiHcSm1ViQfB6MJVZpRqBqNwPr88URqbmjfBhCQISo7hknQYVcbrH78bWHOIE
kU1ZnB9xat1tLtjglPRdcj5iT7P2ENFrOGX1hBA0YRCkqSlNkJPNKBjl7XXhYlw8
Pad6pxxp8K6kpl1Fgp8LkR0r9yItoS+XgNfJ2fYnaW9xe/lp4oOMuLyklHzuvOqc
a8veq00vWKj5+ecCWU+RA8uvjAzI3xuUFzkCAwEAAaBHMEUGCSqGSIb3DQEJDjE4
MDYwCQYDVR0TBAIwADApBgNVHR8EIjAgMB6gHKAahhhodHRwOi8vY3JsLmNhdGVz
dHRvb2wuc2UwDQYJKoZIhvcNAQELBQADggEBAHeuVS8tmKZL8IQhpE6N2NBCRcCd
zX1P+ZpYf0vK05ueg/+6o7wujXxvb0g5yOXJE7/rlHdzAGTRKL7wvnpdiNLcK7fR
DSG12kpDurd83ADzDRj/FQLjOdo7Fvkihew4stajxETFmZvBvvnP9DvxyYzjD8jn
ftX+f0pYZLsU2Z+XokevXKp1MUQBGhCKwLmBiCx19tx0jvZHDqvE/jv8fhPJuXyx
EaMBwhWSmBlT7blPW7dLey6/HlZHLQDP8M/48IVrb/6a3C36juCR6aQg2ZLuFhPZ
Fhw3zp10Sj9cMWUQ2dLwpBUfQWtk9YuQpNuYlAM0xSsGrhZf6GqelWs7vEU=
-----END CERTIFICATE REQUEST-----

Nothing here to see

-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEAnc5+uXl2K09Nrp1oxN/KbIcIYLg8HXCu9UNW7gFknkHil7OVAKHR
Km0Dc8IjqhJpDfoNKFoDo2Vd0KB9moSkDmhFmidcXO7Q8zSq0Z4BXFTO61OMukdd
Expand All @@ -57,17 +53,23 @@ Njc9reFgL6Vua8HkOGkLB+EvRP1YT4v5hGGP/6A7WxRevx5EjF9VgojyDLMPN26C
3c17KY2jNV0W1GEcKEciWS61QInUDBDPYNuQzTl0LucbOpJyV3BFr6pokRBaO3bI
ZYUPhjA2WSxJUeeJboJfisr+CQa9kc1dYwIBAg==
-----END DH PARAMETERS-----

-----BEGIN RSA PUBLIC KEY-----
MEgCQQCo9+BpMRYQ/dL3DS2CyJxRF+j6ctbT3/Qp84+KeFhnii7NT7fELilKUSnx
S30WAvQCCo2yU1orfgqr41mM70MBAgMBAAE=
-----END RSA PUBLIC KEY-----
xxx
static const char g_ffdhe2048_sz[] =
"-----BEGIN DH PARAMETERS-----\n"
"MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n"
"+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n"
"87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n"
"YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n"
"7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n"
"ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==\n"
"-----END DH PARAMETERS-----\n";
"-----BEGIN EC PARAMETERS-----\n"
"MIIB5gIBATBMBgcqhkjOPQEBAkEA2FXXx8/oQxG4Uhuic2YH2xXZqYDgYUyH/ogp\n"
"HnuCWS9grRn1v8AWCpEdwrloaH63oYQN/sKQAVfRf8k1J7nKpzCByARAAgK0Agsl\n"
"YcJvokRDUCnNloLbfHEya0rbeZNf6DPwc9T4mcU7/H1Hs9hjxC9bE/N2njtLpaR2\n"
"bykyE9Or5GOkngRAMyIQgOcnU06PyEY9CZG3b+i0hEOp9bHoVJnm6uhjwY/97aH8\n"
"mG/Pkr4N2B8ZzkaOmz5A4Ujejx4WR39TRlS0ywNCAAHG1Hq3nS8FBhpmZJGvWHmv\n"
"Bjj0RCCU9MtcFZU5Ncfralhq3kjrzbTVSmVU9m/QEHni+qDIawyMX4ktm7mcpJo8\n"
"BIGBBEJk6lNnM17uHfxPPFe6975BDgLoQW7cNbuVxF1ozxkuB8g75+iqTi+GerH9\n"
"RbsFraw2RPbwPH8fQzTLniHXHkEBVvoisBzZqI/Y4DzmDhQexeMcEk0QUw+NxA+k\n"
"wLYyb+gB9VH7G0RqnZuraqk5Y0+1wNbFiu3w0lBOSpdEGrJJAkEA2FXXx8/oQxG4\n"
"Uhuic2YH2xXZqYDgYUyH/ogpHnuCWS8oKmc+nL5CRANkM1N1byv/8WsUio+aJDqR\n"
"MY2SccEWYQIBAQ==\n"
"-----END EC PARAMETERS-----\n";
110 changes: 78 additions & 32 deletions x509-mode-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -176,38 +176,45 @@ When `x509-warn-near-expire-days' is nil."
(ert-deftest x509--pem-region ()
"Find region delimited by BEGIN/END."
(with-temp-buffer
;; 54
;; v
;; 22 53
;; v v
(insert
"-----BEGIN TYPE----- -----END BOGUS-----END TYPE----- -----END TYPE-----")
"-----BEGIN PKCS7----- -----END XX-----END PKCS7----- -----END PKCS7-----")
(goto-char (point-min))
(let ((region (x509--pem-region)))
(should region)
(should (equal 1 (car region)))
(should (equal 54 (cdr region))))
(should (equal 53 (cdr region))))
(goto-char 22)
(let ((region (x509--pem-region)))
(should region)
(should (equal 1 (car region)))
(should (equal 54 (cdr region))))))
(should (equal 53 (cdr region))))))

(ert-deftest x509--pem-region-negative ()
"Behave when there is no region."
(with-temp-buffer
(insert "-----BEGIN TYPE----- -----END BOGUS-----")
(insert "-----BEGIN PKCS7----- -----END XZY-----")
(goto-char (point-min))
(should-not (x509--pem-region)))
(with-temp-buffer
(insert "-----END TYPE-----")
(insert "-----END PKCS7-----")
(goto-char (point-min))
(should-not (x509--pem-region))))

(ert-deftest x509--pem-region-known-types ()
(dolist (type x509--known-pki-types)
(with-temp-buffer
(insert (format "-----BEGIN %s----- -----END %s-----" type type))
(goto-char (point-min))
(should (x509--pem-region)))))

(ert-deftest x509--pem-region-type ()
"Get type of region, e.g. \"CERTIFICATE\"."
(with-temp-buffer
(insert "-----BEGIN my type----- -----END my type-----")
(insert "-----BEGIN PKCS7----- -----END PKCS7-----")
(goto-char (point-min))
(should (equal "my type" (x509--pem-region-type))))
(should (equal "PKCS7" (x509--pem-region-type))))
(with-temp-buffer
(insert "-----END TYPE-----")
(goto-char (point-min))
Expand All @@ -216,20 +223,25 @@ When `x509-warn-near-expire-days' is nil."
(ert-deftest x509--pem-region-next/prev ()
(with-temp-buffer
(insert
"-----BEGIN my type-----\n-----END my type-----\n"
"-----BEGIN my type-----\n-----END my type-----\n")
;; This is the initial valid region
"-----BEGIN PKCS7-----\n-----END PKCS7-----\n"
;; This region with unknown type should be ignored.
"-----BEGIN xxxxx-----\n-----END xxxxx-----\n"
;; This is the next valid region
"-----BEGIN PKCS7-----\n-----END PKCS7-----\n")
;;^ point after next
(goto-char (point-min))
(let ((first-region (x509--pem-region)))
(let ((first-region (x509--pem-region))
(expected-next-point 85))
(should first-region)
(should (= 1 (car first-region)))
(let ((next-region (x509--pem-region-next/prev (current-buffer) 'next)))
(should next-region)
(should (= 47 (car next-region)))
(should (= 47 (point)))
(should (= expected-next-point (car next-region)))
(should (= expected-next-point (point)))
;; Next again should leave point unchanged
(should-not (x509--pem-region-next/prev (current-buffer) 'next))
(should (= 47 (point))))
(should (= expected-next-point (point))))
;; Prev 1
(let ((prev-region (x509--pem-region-next/prev (current-buffer) 'prev)))
(should prev-region)
Expand All @@ -245,10 +257,10 @@ When `x509-warn-near-expire-days' is nil."
(with-temp-buffer
(let ((q-pem-data
(concat
"const char* pem = \"-----BEGIN XX-----\"\n"
"const char* pem = \"-----BEGIN PKCS7-----\"\n"
" \"data\"\n"
" \"-----END XX-----\";\n"))
(clean-pem-data "-----BEGIN XX-----\ndata\n-----END XX-----"))
" \"-----END PKCS7-----\";\n"))
(clean-pem-data "-----BEGIN PKCS7-----\ndata\n-----END PKCS7-----"))
(insert q-pem-data)
(goto-char 20)
(let ((buf (x509--generate-input-buffer)))
Expand Down Expand Up @@ -377,14 +389,20 @@ When `x509-warn-near-expire-days' is nil."
(expand-file-name file-name "testfiles"))

(defun view-test-helper
(test-files view-command expected-mode expected-strings)
(test-files
view-command expected-mode expected-strings &optional anti-strings)
"Run VIEW-COMMAND on all TEST-FILES.
Check that buffer has EXPECTED-MODE and contains EXPECTED-STRINGS.
Check that buffer does _not_ contain ANTI-STRINGS.
Repeat with `x509-dwim' which should produce the same result."
(let ((regexes
(if (listp expected-strings)
expected-strings
(list expected-strings)))
(anti-regexes
(if (listp anti-strings)
anti-strings
(list anti-strings)))
(files
(if (listp test-files)
test-files
Expand All @@ -401,7 +419,9 @@ Repeat with `x509-dwim' which should produce the same result."
(point-min) (point-max))))
(should (derived-mode-p expected-mode))
(dolist (regex regexes)
(should (string-match-p regex content)))))
(should (string-match-p regex content)))
(dolist (regex anti-regexes)
(should-not (string-match-p regex content)))))
(kill-buffer view-buffer))))))))

(ert-deftest x509-viewcert ()
Expand All @@ -410,14 +430,15 @@ Repeat with `x509-dwim' which should produce the same result."
'("CA/pki/crt/jobbflykt.crt" "CA/pki/crt/jobbflykt.cer")
'x509-viewcert
'x509-mode
"Certificate:"))
"Certificate:"
"Warning"))

(ert-deftest x509-viewreq ()
"View cert request."
(view-test-helper
'("CA/ca/request/jobbflykt.pem"
"CA/ca/request/jobbflykt_req.der")
'x509-viewreq 'x509-mode "Certificate Request:"))
'x509-viewreq 'x509-mode "Certificate Request:" "Warning"))

(ert-deftest x509-viewcrl ()
"View CRL."
Expand Down Expand Up @@ -672,11 +693,11 @@ SEQUENCE 30 0C
(goto-char (point-min))
(let ((view-buffer (x509-dwim)))
(should view-buffer)
(check-content-helper view-buffer "1d:09:fa:e5")
(check-content-helper view-buffer "Certificate:")
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-next)))
(should view-buffer)
(check-content-helper view-buffer "23:cc:f0:66")
(check-content-helper view-buffer "Certificate Request:")
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-next)))
(should view-buffer)
Expand All @@ -688,11 +709,11 @@ SEQUENCE 30 0C
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-next)))
(should view-buffer)
(check-content-helper view-buffer "GROUP: ffdhe2048")
(check-content-helper view-buffer "EC-Parameters: (512 bit)")
;; At end, next should fail
(with-current-buffer view-buffer
(should-not (x509-dwim-next)))
(check-content-helper view-buffer "GROUP: ffdhe2048")
(check-content-helper view-buffer "EC-Parameters: (512 bit)")
;; Go backward
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-prev)))
Expand All @@ -705,15 +726,15 @@ SEQUENCE 30 0C
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-prev)))
(should view-buffer)
(check-content-helper view-buffer "23:cc:f0:66")
(check-content-helper view-buffer "Certificate Request:")
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-prev)))
(should view-buffer)
(check-content-helper view-buffer "1d:09:fa:e5")
(check-content-helper view-buffer "Certificate:")
;; At beginning, prev should fail
(with-current-buffer view-buffer
(should-not (x509-dwim-prev)))
(check-content-helper view-buffer "1d:09:fa:e5")
(check-content-helper view-buffer "Certificate:")
;; Kill it
(with-current-buffer view-buffer
(x509-mode-kill-buffer)))))
Expand All @@ -725,21 +746,46 @@ SEQUENCE 30 0C
(goto-char (point-min))
(let ((view-buffer (x509-viewasn1)))
(should view-buffer)
(check-content-helper view-buffer "1D09FAE5")
(check-content-helper view-buffer ":033AF1E6A711A9A0BB2864B11D09FAE5")
;; Go next and verify we are still in asn1 mode looking at the next
;; section.
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-next)))
(should view-buffer)
(check-content-helper view-buffer "CCF066")
(check-content-helper view-buffer ":Extension Request")
;; Go back again
(with-current-buffer view-buffer
(setq view-buffer (x509-dwim-prev)))
(should view-buffer)
(check-content-helper view-buffer "1D09FAE5")
(check-content-helper view-buffer ":033AF1E6A711A9A0BB2864B11D09FAE5")
;; Kill it
(with-current-buffer view-buffer
(x509-mode-kill-buffer)))))

(ert-deftest x509-swoop ()
"Multiple dwim in all regions in buffer."
(let ((x509-swoop-separator "7iyefiaeo7bf")))
(with-temp-buffer
(insert-file-contents-literally (find-testfile "multi.pem"))
;; Goto some random point in src buffer and check that it's unchanged
;; after swooping.
(let ((src-buffer (current-buffer)))
(goto-char 1322)
(let ((swoop-buffer (x509-swoop)))
(should swoop-buffer)
(with-current-buffer swoop-buffer
(check-content-helper swoop-buffer "Certificate:")
(check-content-helper swoop-buffer "Certificate Request:")
(check-content-helper swoop-buffer "DH Parameters:")
(check-content-helper swoop-buffer "Public-Key:")
(check-content-helper swoop-buffer "EC-Parameters: (512 bit)")
(check-content-helper swoop-buffer x509-swoop-separator)
(x509-mode-kill-buffer)))
(with-current-buffer src-buffer
(should (= (point) 1322)))))
(with-temp-buffer
(insert "-----BEGIN nothing----- -----END nothing-----")
(should-not (x509-swoop))))

(provide 'x509-mode-tests)
;;; x509-mode-tests.el ends here
Loading
Loading