@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
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 accepts '4a' as a value for its version
+field.
+
** Edmacro
+++
(radio-button-choice :tag "SOCKS Version"
:format "%t: %v"
(const :tag "SOCKS v4 " :format "%t" :value 4)
+ (const :tag "SOCKS v4a" :format "%t" :value 4a)
(const :tag "SOCKS v5" :format "%t" :value 5))))
"Command not supported"
"Address type not supported"))
+(defconst socks--errors-4
+ '("Granted"
+ "Rejected or failed"
+ "Cannot connect to identd on the client"
+ "Client and identd report differing user IDs"))
+
;; The socks v5 address types
(defconst socks-address-type-v4 1)
(defconst socks-address-type-name 3)
((pred (= socks-address-type-name))
(if (< (length string) 5)
255
- (+ 1 (aref string 4)))))))
+ (+ 1 (aref string 4))))
+ (0 0))))
(if (< (length string) desired-len)
nil ; Need to spin some more
(process-put proc 'socks-state socks-state-connected)
(format "%c%s" (length address) address))
(t
(error "Unknown address type: %d" atype))))
+ trailing
request version)
(or (process-get proc 'socks)
(error "socks-send-command called on non-SOCKS connection %S" proc))
(t
(error "Unsupported address type for HTTP: %d" atype)))
port)))
+ ((and (eq version '4a)
+ (setf addr "\0\0\0\1"
+ trailing (concat address "\0")
+ version 4 ; become version 4
+ (process-get proc 'socks-server-protocol) 4)
+ nil)) ; fall through
((equal version 4)
(setq request (concat
(unibyte-string
(ash port -8) ; port, high byte
(logand port #xff)) ; port, low byte
addr ; address
- (user-full-name) ; username
- "\0"))) ; terminate username
+ socks-username ; username
+ "\0" ; terminate username
+ trailing))) ; optional host to look up
((equal version 5)
(setq request (concat
(unibyte-string
nil ; Sweet sweet success!
(delete-process proc)
(error "SOCKS: %s"
- (nth (or (process-get proc 'socks-reply) 1) socks-errors)))
+ (let ((err (process-get proc 'socks-reply)))
+ (if (eql version 5)
+ (nth (or err 1) socks-errors)
+ ;; The defined error codes for v4 range from
+ ;; 90-93, but we store them in a simple list.
+ (nth (pcase err (90 0) (92 2) (93 3) (_ 1))
+ socks--errors-4)))))
proc))
\f
"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))
(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")
+ (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:
;; $ curl --verbose -U foo:bar --proxy socks5h://127.0.0.1:10080 example.com