diff options
| author | Jimmy Yuen Ho Wong | 2018-07-10 14:23:20 +0100 |
|---|---|---|
| committer | Jimmy Yuen Ho Wong | 2018-07-14 17:50:44 +0100 |
| commit | 682578fcf74d4598e39eca81e09d81810d3fc28d (patch) | |
| tree | d8a8f54c778a831229405cd9706066ac582d3826 | |
| parent | 534a3d5d3a99a6b86a47b3d91840ce8771ee0ae6 (diff) | |
| download | emacs-682578fcf74d4598e39eca81e09d81810d3fc28d.tar.gz emacs-682578fcf74d4598e39eca81e09d81810d3fc28d.zip | |
Add option to bypass NSM TLS checks on local networks
* lisp/net/net-utils.el (nslookup-host-ipv4, nslookup-host-ipv6,
ipv6-expand): New functions to lookup IPv4 and IPv6 addresses from
DNS.
* lisp/net/nsm.el (nsm-trust-local-network, nsm-should-check,
nsm-check-tls-connection, nsm-check-plain-connection): New defcustom
`nsm-trust-local-network' lets users customize whether NSM should
check for TLS problems when connecting to the hosts on their local
networks. `nsm-should-check' determines whether
`nsm-check-tls-connection' and `nsm-check-plain-connection' should
perform checks. localhost is implicitly trusted, thus checks are
never performed there.
| -rw-r--r-- | lisp/net/net-utils.el | 75 | ||||
| -rw-r--r-- | lisp/net/nsm.el | 76 |
2 files changed, 148 insertions, 3 deletions
diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index c9e80804bd3..0ba4aae0ae0 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el | |||
| @@ -43,6 +43,10 @@ | |||
| 43 | ;; still use them for queries). Actually the trend these | 43 | ;; still use them for queries). Actually the trend these |
| 44 | ;; days is for /sbin to be a symlink to /usr/sbin, but we still need to | 44 | ;; days is for /sbin to be a symlink to /usr/sbin, but we still need to |
| 45 | ;; search both for older systems. | 45 | ;; search both for older systems. |
| 46 | |||
| 47 | (require 'subr-x) | ||
| 48 | (require 'cl-lib) | ||
| 49 | |||
| 46 | (defun net-utils--executable-find-sbin (command) | 50 | (defun net-utils--executable-find-sbin (command) |
| 47 | "Return absolute name of COMMAND if found in an sbin directory." | 51 | "Return absolute name of COMMAND if found in an sbin directory." |
| 48 | (let ((exec-path '("/sbin" "/usr/sbin" "/usr/local/sbin"))) | 52 | (let ((exec-path '("/sbin" "/usr/sbin" "/usr/local/sbin"))) |
| @@ -514,7 +518,11 @@ Optional argument NAME-SERVER says which server to use for | |||
| 514 | DNS resolution. | 518 | DNS resolution. |
| 515 | Interactively, prompt for NAME-SERVER if invoked with prefix argument. | 519 | Interactively, prompt for NAME-SERVER if invoked with prefix argument. |
| 516 | 520 | ||
| 517 | This command uses `nslookup-program' for looking up the DNS information." | 521 | This command uses `nslookup-program' for looking up the DNS information. |
| 522 | |||
| 523 | See also: `nslookup-host-ipv4', `nslookup-host-ipv6' for | ||
| 524 | non-interactive versions of this function more suitable for use | ||
| 525 | in Lisp code." | ||
| 518 | (interactive | 526 | (interactive |
| 519 | (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) | 527 | (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) |
| 520 | (if current-prefix-arg (read-from-minibuffer "Name server: ")))) | 528 | (if current-prefix-arg (read-from-minibuffer "Name server: ")))) |
| @@ -531,6 +539,71 @@ This command uses `nslookup-program' for looking up the DNS information." | |||
| 531 | options))) | 539 | options))) |
| 532 | 540 | ||
| 533 | ;;;###autoload | 541 | ;;;###autoload |
| 542 | (defun nslookup-host-ipv4 (host &optional name-server format) | ||
| 543 | "Return the IPv4 address for HOST (name or IP address). | ||
| 544 | Optional argument NAME-SERVER says which server to use for DNS | ||
| 545 | resolution. | ||
| 546 | |||
| 547 | If FORMAT is `string', returns the IP address as a | ||
| 548 | string (default). If FORMAT is `vector', returns a 4-integer | ||
| 549 | vector of octets. | ||
| 550 | |||
| 551 | This command uses `nslookup-program' to look up DNS records." | ||
| 552 | (let* ((args `(,nslookup-program "-type=A" ,host ,name-server)) | ||
| 553 | (output (shell-command-to-string | ||
| 554 | (string-join (cl-remove nil args) " "))) | ||
| 555 | (ip (or (and (string-match | ||
| 556 | "Name:.*\nAddress: *\\(\\([0-9]\\{1,3\\}\\.?\\)\\{4\\}\\)" | ||
| 557 | output) | ||
| 558 | (match-string 1 output)) | ||
| 559 | host))) | ||
| 560 | (cond ((memq format '(string nil)) | ||
| 561 | ip) | ||
| 562 | ((eq format 'vector) | ||
| 563 | (apply #'vector (mapcar #'string-to-number (split-string ip "\\.")))) | ||
| 564 | (t (error "Invalid format: %s" format))))) | ||
| 565 | |||
| 566 | (defun ipv6-expand (ipv6-vector) | ||
| 567 | (let ((len (length ipv6-vector))) | ||
| 568 | (if (< len 8) | ||
| 569 | (let* ((pivot (cl-position 0 ipv6-vector)) | ||
| 570 | (head (cl-subseq ipv6-vector 0 pivot)) | ||
| 571 | (tail (cl-subseq ipv6-vector (1+ pivot) len))) | ||
| 572 | (vconcat head (make-vector (- 8 (1- len)) 0) tail)) | ||
| 573 | ipv6-vector))) | ||
| 574 | |||
| 575 | ;;;###autoload | ||
| 576 | (defun nslookup-host-ipv6 (host &optional name-server format) | ||
| 577 | "Return the IPv6 address for HOST (name or IP address). | ||
| 578 | Optional argument NAME-SERVER says which server to use for DNS | ||
| 579 | resolution. | ||
| 580 | |||
| 581 | If FORMAT is `string', returns the IP address as a | ||
| 582 | string (default). If FORMAT is `vector', returns a 8-integer | ||
| 583 | vector of hextets. | ||
| 584 | |||
| 585 | This command uses `nslookup-program' to look up DNS records." | ||
| 586 | (let* ((args `(,nslookup-program "-type=AAAA" ,host ,name-server)) | ||
| 587 | (output (shell-command-to-string | ||
| 588 | (string-join (cl-remove nil args) " "))) | ||
| 589 | (hextet "[0-9a-fA-F]\\{1,4\\}") | ||
| 590 | (ip-regex (concat "\\(\\(" hextet "[:]\\)\\{1,6\\}\\([:]?\\(" hextet "\\)\\{1,6\\}\\)\\)")) | ||
| 591 | (ip (or (and (string-match | ||
| 592 | (if (eq system-type 'windows-nt) | ||
| 593 | (concat "Name:.*\nAddress: *" ip-regex) | ||
| 594 | (concat "has AAAA address " ip-regex)) | ||
| 595 | output) | ||
| 596 | (match-string 1 output)) | ||
| 597 | host))) | ||
| 598 | (cond ((memq format '(string nil)) | ||
| 599 | ip) | ||
| 600 | ((eq format 'vector) | ||
| 601 | (ipv6-expand (apply #'vector | ||
| 602 | (cl-loop for hextet in (split-string ip "[:]") | ||
| 603 | collect (string-to-number hextet 16))))) | ||
| 604 | (t (error "Invalid format: %s" format))))) | ||
| 605 | |||
| 606 | ;;;###autoload | ||
| 534 | (defun nslookup () | 607 | (defun nslookup () |
| 535 | "Run `nslookup-program'." | 608 | "Run `nslookup-program'." |
| 536 | (interactive) | 609 | (interactive) |
diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el index 50895bc0ad9..e4c52bc9c1c 100644 --- a/lisp/net/nsm.el +++ b/lisp/net/nsm.el | |||
| @@ -62,6 +62,26 @@ checked and warned against." | |||
| 62 | (when (eq network-security-level 'paranoid) | 62 | (when (eq network-security-level 'paranoid) |
| 63 | (setq network-security-level 'high)) | 63 | (setq network-security-level 'high)) |
| 64 | 64 | ||
| 65 | (defcustom nsm-trust-local-network nil | ||
| 66 | "Disable warnings when visiting trusted hosts on local networks. | ||
| 67 | |||
| 68 | The default suite of TLS checks in NSM is designed to follow the | ||
| 69 | most current security best practices. Under some situations, | ||
| 70 | such as attempting to connect to an email server that do not | ||
| 71 | follow these practices inside a school or corporate network, NSM | ||
| 72 | may produce warnings for such occasions. Setting this option to | ||
| 73 | a non-nil value, or a zero-argument function that returns non-nil | ||
| 74 | tells NSM to skip checking for potential TLS vulnerabilities when | ||
| 75 | connecting to hosts on a local network. | ||
| 76 | |||
| 77 | Make sure you know what you are doing before enabling this | ||
| 78 | option." | ||
| 79 | :version "27.1" | ||
| 80 | :group 'nsm | ||
| 81 | :type '(choice (const :tag "On" t) | ||
| 82 | (const :tag "Off" nil) | ||
| 83 | (function :tag "Custom function"))) | ||
| 84 | |||
| 65 | (defcustom nsm-settings-file (expand-file-name "network-security.data" | 85 | (defcustom nsm-settings-file (expand-file-name "network-security.data" |
| 66 | user-emacs-directory) | 86 | user-emacs-directory) |
| 67 | "The file the security manager settings will be stored in." | 87 | "The file the security manager settings will be stored in." |
| @@ -184,6 +204,55 @@ SETTINGS are the same as those supplied to each check function. | |||
| 184 | RESULTS is an alist where the keys are the checks run and the | 204 | RESULTS is an alist where the keys are the checks run and the |
| 185 | values the results of the checks.") | 205 | values the results of the checks.") |
| 186 | 206 | ||
| 207 | (defun nsm-should-check (host) | ||
| 208 | "Determines whether NSM should check for TLS problems for HOST. | ||
| 209 | |||
| 210 | If `nsm-trust-local-network' is or returns non-nil, and if the | ||
| 211 | host address is a localhost address, a machine address, a direct | ||
| 212 | link or a private network address, this function returns | ||
| 213 | nil. Non-nil otherwise." | ||
| 214 | (let* ((address (or (nslookup-host-ipv4 host nil 'vector) | ||
| 215 | (nslookup-host-ipv6 host nil 'vector))) | ||
| 216 | (ipv4? (eq (length address) 4))) | ||
| 217 | (not | ||
| 218 | (or (if ipv4? | ||
| 219 | (or | ||
| 220 | ;; (0.x.x.x) this machine | ||
| 221 | (eq (aref address 0) 0) | ||
| 222 | ;; (127.x.x.x) localhost | ||
| 223 | (eq (aref address 0) 0)) | ||
| 224 | (or | ||
| 225 | ;; (::) IPv6 this machine | ||
| 226 | (not (cl-mismatch address [0 0 0 0 0 0 0 0])) | ||
| 227 | ;; (::1) IPv6 localhost | ||
| 228 | (not (cl-mismatch address [0 0 0 0 0 0 0 1])))) | ||
| 229 | (and (or (and (functionp nsm-trust-local-network) | ||
| 230 | (funcall nsm-trust-local-network)) | ||
| 231 | nsm-trust-local-network) | ||
| 232 | (if ipv4? | ||
| 233 | (or | ||
| 234 | ;; (10.x.x.x) private | ||
| 235 | (eq (aref address 0) 10) | ||
| 236 | ;; (172.16.x.x) private | ||
| 237 | (and (eq (aref address 0) 172) | ||
| 238 | (eq (aref address 0) 16)) | ||
| 239 | ;; (192.168.x.x) private | ||
| 240 | (and (eq (aref address 0) 192) | ||
| 241 | (eq (aref address 0) 168)) | ||
| 242 | ;; (198.18.x.x) private | ||
| 243 | (and (eq (aref address 0) 198) | ||
| 244 | (eq (aref address 0) 18)) | ||
| 245 | ;; (169.254.x.x) link-local | ||
| 246 | (and (eq (aref address 0) 169) | ||
| 247 | (eq (aref address 0) 254))) | ||
| 248 | (memq (aref address 0) | ||
| 249 | '( | ||
| 250 | 64512 ;; (fc00::) IPv6 unique local address | ||
| 251 | 64768 ;; (fd00::) IPv6 unique local address | ||
| 252 | 65152 ;; (fe80::) IPv6 link-local | ||
| 253 | ) | ||
| 254 | ))))))) | ||
| 255 | |||
| 187 | (defun nsm-check-tls-connection (process host port status settings) | 256 | (defun nsm-check-tls-connection (process host port status settings) |
| 188 | "Check TLS connection against potential security problems. | 257 | "Check TLS connection against potential security problems. |
| 189 | 258 | ||
| @@ -204,6 +273,7 @@ This function returns the process PROCESS if no problems are | |||
| 204 | found, and nil otherwise. | 273 | found, and nil otherwise. |
| 205 | 274 | ||
| 206 | See also: `nsm-tls-checks' and `nsm-noninteractive'" | 275 | See also: `nsm-tls-checks' and `nsm-noninteractive'" |
| 276 | (when (nsm-should-check host) | ||
| 207 | (let* ((results | 277 | (let* ((results |
| 208 | (cl-loop for check in nsm-tls-checks | 278 | (cl-loop for check in nsm-tls-checks |
| 209 | for type = (intern (format ":%s" | 279 | for type = (intern (format ":%s" |
| @@ -234,7 +304,7 @@ See also: `nsm-tls-checks' and `nsm-noninteractive'" | |||
| 234 | (delete-process process) | 304 | (delete-process process) |
| 235 | (setq process nil))) | 305 | (setq process nil))) |
| 236 | (run-hook-with-args 'nsm-tls-post-check-functions | 306 | (run-hook-with-args 'nsm-tls-post-check-functions |
| 237 | host port status settings results)) | 307 | host port status settings results))) |
| 238 | process) | 308 | process) |
| 239 | 309 | ||
| 240 | 310 | ||
| @@ -678,6 +748,7 @@ protocol." | |||
| 678 | 'nsm-fingerprint-ok-p '(status settings) "27.1") | 748 | 'nsm-fingerprint-ok-p '(status settings) "27.1") |
| 679 | 749 | ||
| 680 | (defun nsm-check-plain-connection (process host port settings warn-unencrypted) | 750 | (defun nsm-check-plain-connection (process host port settings warn-unencrypted) |
| 751 | (if (nsm-should-check host) | ||
| 681 | ;; If this connection used to be TLS, but is now plain, then it's | 752 | ;; If this connection used to be TLS, but is now plain, then it's |
| 682 | ;; possible that we're being Man-In-The-Middled by a proxy that's | 753 | ;; possible that we're being Man-In-The-Middled by a proxy that's |
| 683 | ;; stripping out STARTTLS announcements. | 754 | ;; stripping out STARTTLS announcements. |
| @@ -703,7 +774,8 @@ protocol." | |||
| 703 | (delete-process process) | 774 | (delete-process process) |
| 704 | nil) | 775 | nil) |
| 705 | (t | 776 | (t |
| 706 | process)))) | 777 | process))) |
| 778 | process)) | ||
| 707 | 779 | ||
| 708 | (defun nsm-query (host port status what problems message) | 780 | (defun nsm-query (host port status what problems message) |
| 709 | ;; If there is no user to answer queries, then say `no' to everything. | 781 | ;; If there is no user to answer queries, then say `no' to everything. |