From 97f2cb52b73d5c0bd7409044fef5469b914a9ec9 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 8 Sep 2023 06:06:35 -0700 Subject: [PATCH 0/4] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (4): Don't hard code server ports in SOCKS tests Improve SOCKS error handling and add support for 4a [POC] Simplify network-stream openers in socks.el [POC] Integrate the socks and url libraries doc/misc/url.texi | 8 +- etc/NEWS | 7 ++ lisp/net/socks.el | 141 ++++++++++++++++++++++++++++------- lisp/url/url-gw.el | 8 +- lisp/url/url-http.el | 16 ++-- lisp/url/url-proxy.el | 18 ++++- lisp/url/url-vars.el | 11 ++- test/lisp/net/socks-tests.el | 84 ++++++++++++++++----- 8 files changed, 231 insertions(+), 62 deletions(-) Interdiff: diff --git a/doc/misc/url.texi b/doc/misc/url.texi index e6636e32507..6517f858324 100644 --- a/doc/misc/url.texi +++ b/doc/misc/url.texi @@ -1083,16 +1083,18 @@ Gateways in general @defopt socks-server This specifies the default server, it takes the form @w{@code{("Default server" @var{server} @var{port} @var{version})}} -where @var{version} can be either 4 or 5. +where @var{version} can be 4, 4a, or 5. @end defopt @defvar socks-password If this is @code{nil} then you will be asked for the password, otherwise it will be used as the password for authenticating you to -the @sc{socks} server. +the @sc{socks} server. You can often set this to @code{""} for +servers on your local network. @end defvar @defvar socks-username This is the username to use when authenticating yourself to the -@sc{socks} server. By default this is your login name. +@sc{socks} server. By default, this is your login name. In versions +4 and 4a, ERC uses this for the @samp{ID} field. @end defvar @defvar socks-timeout This controls how long, in seconds, to wait for responses from the diff --git a/etc/NEWS b/etc/NEWS index f6be603294e..55bcf957021 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -756,6 +756,13 @@ neither of which have been supported by Emacs since version 23.1. The user option 'url-gateway-nslookup-program' and the function 'url-gateway-nslookup-host' are consequently also obsolete. +** socks + ++++ +*** SOCKS supports version 4a. +The 'socks-server' option now accepts '4a' as a valid value for its +version field. + * New Modes and Packages in Emacs 30.1 diff --git a/lisp/net/socks.el b/lisp/net/socks.el index 1bb78113d52..f5820e7968c 100644 --- a/lisp/net/socks.el +++ b/lisp/net/socks.el @@ -444,7 +444,7 @@ socks-send-command (ash port -8) ; port, high byte (logand port #xff)) ; port, low byte addr ; address - (user-full-name) ; username + socks-username ; username "\0" ; terminate username trailing))) ; optional host to look up ((equal version 5) @@ -582,8 +582,8 @@ socks-open-network-stream (socks-server (if url (list name (url-host url) (url-port url) (pcase (url-type url) - ("socks4://" 4) - ("socks4a://" '4a) + ("socks4" 4) + ("socks4a" '4a) (_ 5))) socks-server)) (socks-username (or (and url (url-user url)) @@ -604,9 +604,9 @@ socks-open-network-stream (progn (gnutls-negotiate :process proc :hostname host :keylist (and certs (list certs))) - ;; FIXME skip when TLD is .onion. - (nsm-verify-connection proc host port)) - proc)) + (unless (string-suffix-p ".onion" host) + (nsm-verify-connection proc host port)))) + proc) (apply socks-connect-function name buffer host service params)))) (defun socks--initiate-command-connect (proc buffer host service) diff --git a/lisp/url/url-proxy.el b/lisp/url/url-proxy.el index 1a278bb1673..c9c5a7aacac 100644 --- a/lisp/url/url-proxy.el +++ b/lisp/url/url-proxy.el @@ -37,13 +37,11 @@ url-default-find-proxy-for-url host)) (equal "www" (url-type urlobj))) "DIRECT") - ((cdr (assoc (url-type urlobj) url-proxy-services)) - (let ((found (alist-get (url-type urlobj) url-proxy-services - nil nil #'equal))) - (concat (if (string-match url-proxy--socks-scheme-regexp found) + ((and-let* ((found (assoc (url-type urlobj) url-proxy-services))) + (concat (if (string-match url-proxy--socks-scheme-regexp (cdr found)) "SOCKS " "PROXY ") - found))) + (cdr found)))) ;; ;; Should check for socks ;; @@ -65,8 +63,8 @@ url-find-proxy-for-url ((string-match "^PROXY +" proxy) (concat "http://" (substring proxy (match-end 0)) "/")) ((string-match "^SOCKS +" proxy) - (if-let* ((m (substring proxy (match-end 0))) - ((string-match url-proxy--socks-scheme-regexp m))) + (if-let ((m (substring proxy (match-end 0))) + ((string-match url-proxy--socks-scheme-regexp m))) m (concat "socks://" m))) (t diff --git a/test/lisp/net/socks-tests.el b/test/lisp/net/socks-tests.el index df69fb2f5cf..1a4bac37bf9 100644 --- a/test/lisp/net/socks-tests.el +++ b/test/lisp/net/socks-tests.el @@ -139,7 +139,7 @@ socks-tests-canned-server-create (filt (lambda (proc line) (pcase-let ((`(,pat . ,resp) (pop pats))) (unless (or (and (vectorp pat) (equal pat (vconcat line))) - (string-match-p pat line)) + (and (stringp pat) (string-match-p pat line))) (error "Unknown request: %s" line)) (setq resp (apply #'unibyte-string (append resp nil))) (let ((print-escape-control-characters t)) @@ -197,6 +197,7 @@ socks-tests-v4-basic "Show correct preparation of SOCKS4 connect command (Bug#46342)." (let ((socks-server '("server" "127.0.0.1" t 4)) (url-user-agent "Test/4-basic") + (socks-username "foo") (socks-tests-canned-server-patterns `(([4 1 0 80 93 184 216 34 ?f ?o ?o 0] . [0 90 0 0 0 0 0 0]) ,socks-tests--hello-world-http-request-pattern)) @@ -205,23 +206,34 @@ socks-tests-v4-basic (cl-letf (((symbol-function 'socks-nslookup-host) (lambda (host) (should (equal host "example.com")) - (list 93 184 216 34))) - ((symbol-function 'user-full-name) - (lambda (&optional _) "foo"))) + (list 93 184 216 34)))) (socks-tests-perform-hello-world-http-request))))) (ert-deftest socks-tests-v4a-basic () "Show correct preparation of SOCKS4a connect command." (let ((socks-server '("server" "127.0.0.1" t 4a)) + (socks-username "foo") (url-user-agent "Test/4a-basic") (socks-tests-canned-server-patterns `(([4 1 0 80 0 0 0 1 ?f ?o ?o 0 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0] . [0 90 0 0 0 0 0 0]) ,socks-tests--hello-world-http-request-pattern))) (ert-info ("Make HTTP request over SOCKS4A") - (cl-letf (((symbol-function 'user-full-name) - (lambda (&optional _) "foo"))) - (socks-tests-perform-hello-world-http-request))))) + (socks-tests-perform-hello-world-http-request)))) + +(ert-deftest socks-tests-v4a-error () + "Show error signaled when destination address rejected." + (let ((socks-server '("server" "127.0.0.1" t 4a)) + (url-user-agent "Test/4a-basic") + (socks-username "") + (socks-tests-canned-server-patterns + `(([4 1 0 80 0 0 0 1 0 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0] + . [0 91 0 0 0 0 0 0]) + ,socks-tests--hello-world-http-request-pattern))) + (ert-info ("Make HTTP request over SOCKS4A") + (let ((err (should-error + (socks-tests-perform-hello-world-http-request)))) + (should (equal err '(error "SOCKS: Rejected or failed"))))))) ;; Replace first pattern below with ([5 3 0 1 2] . [5 2]) to validate ;; against curl 7.71 with the following options: @@ -309,12 +321,9 @@ socks-override-functions (should-not (advice-member-p #'socks--open-network-stream 'open-network-stream)) (advice-add 'open-network-stream :around #'socks--open-network-stream) - (should (advice-member-p #'socks--open-network-stream 'open-network-stream)) - (unwind-protect (let ((socks-override-functions t)) (socks-tests-v5-auth-none 'native)) (advice-remove 'open-network-stream #'socks--open-network-stream)) - (should-not (advice-member-p #'socks--open-network-stream 'open-network-stream))) -- 2.41.0