Subject: Re: [bug#47155] [PATCH] gnu: Respect DataDirectoryGroupReadable option of tor.

From: raid5atemyhomework <[email-masked]>
Date: Sat, 27 Mar 2021 06:37:52 +0000

> > If you reconfigure your OS without restarting the tor service,
> > the directory permissions are reset due to the activation code being
> > re-run and resetting the directory permissions.
> > This change simply does not chmod if the directory already exists.
>
> I believe it would be more transparent to introduce a
> (data-directory-group-readable? #t/#f), with #f as default,
> to tor-configuration (adjusting tor-configuration->torrc)
> and change the permission bits passed to chmod appropriately.
>
> (Documentation & reproducible system configuration & one integrated
> system (in the software sense) and all that)

But really though, the primary reason for this is to use the "cookie" authentication scheme with a control port on 9051.  This is supported by most daemons, as the "control unix socket" (that is currently supported by `control-socket?` option) seems to be relatively new (Tor 0.2.7.1).

This requires adding:

    ControlPort 9051
    CookieAuthentication 1
    CookieAuthFileGroupReadable 1
    DataDirectoryGroupReadable 1

In https://issues.guix.gnu.org/46549 which implements `control-socket?` the author expressed doubt as to the safety of this mechanism.  Looking at the Tor manpage regarding `ControlPort`:

```
Note: unless you also specify one or more of HashedControlPassword or CookieAuthentication, setting this option will cause Tor to allow any process on the local
host to control it. (Setting both authentication methods means either method is sufficient to authenticate to Tor.) This option is required for many Tor controllers; most use
the value of 9051.
```

Basically, this is safe as long as you use *either* `HashedControlPassword` *or* `CookieAuthentication` *or* both; in the case of `CookieAuthentication` only users with read access to the cookie file can access it.  Nearly every daemon that needs control access over Tor (usually to set up their own hidden service using their own privkey) expects `CookieAuthentication` and reads from `/var/lib/tor/control_auth-_cookie`, which requires that `/var/lib/tor` be readable (else it can't look up the filename).  It becomes just as safe as the control-unix-socket option, as that is similarly gated by file permissions.

Note in particular that Bitcoin Core supports `ControlPort` and not `ControlSocket`, so this is needed for Bitcoin Core support.  From what I can see more daemons support `ControlPort` than `ControlSocket`.

Thanks
raid5atemyhomework

>From d9bea7635594654e1e631e4db55422c511f0220a Mon Sep 17 00:00:00 2001
From: raid5atemyhomework <[email-masked]>
Date: Sat, 27 Mar 2021 14:29:31 +0800
Subject: [PATCH] gnu: Add 'control-port?' setting to Tor.

* gnu/services/networking.scm (tor-configuration): Add `control-port?` field.
(tor-configuration->torrc): Support `control-port?` field.
(tor-activation): Allow group access to data directory if `control-port?`.
* doc/guix.texi (Networking Services)[Tor]: Describe new `control-port?` field.
---
 doc/guix.texi               | 13 +++++++++++++
 gnu/services/networking.scm | 24 +++++++++++++++++++++---
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index c23d044ff5..a9c8f930be 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -87,6 +87,7 @@ Copyright @copyright{} 2020 Daniel Brooks@*
 Copyright @copyright{} 2020 John Soo@*
 Copyright @copyright{} 2020 Jonathan Brielmaier@*
 Copyright @copyright{} 2020 Edgar Vincent@*
+Copyright @copyright{} 2021 raid5atemyhomework@*

 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -16676,6 +16677,18 @@ If @code{#t}, Tor will listen for control commands on the UNIX domain socket
 @file{/var/run/tor/control-sock}, which will be made writable by members of the
 @code{tor} group.

+@item @code{control-port?} (default: @code{#f})
+Whether or not to provide a ``control port'' by which Tor can be controlled
+to, for instance, dynamically instantiate tor onion services.  This is more
+commonly supported by Tor controllers than using a UNIX domain socket as
+above.  If @code{#t}, Tor will listen for authenticated control commands over
+the control port 9051.  In order to authenticate to this port, Tor controllers
+need to read the cookie file at @file{/var/lib/tor/control_auth_cookie}, which
+will be made readable by members of the @code{tor} group.
+
+This can be set to a number instead, which will make Tor listen for control
+commands over the specified port number rather than the default 9051.
+
 @end table
 @end deftp

diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index 231a9f66c7..a4fbeaadfe 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -747,7 +747,9 @@ demand.")))
   (socks-socket-type tor-configuration-socks-socket-type ; 'tcp or 'unix
                      (default 'tcp))
   (control-socket?  tor-control-socket-path
-                    (default #f)))
+                    (default #f))
+  (control-port?    tor-control-port?
+                    (default #f))) ; #f | #t | number

 (define %tor-accounts
   ;; User account and groups for Tor.
@@ -770,7 +772,8 @@ demand.")))
   "Return a 'torrc' file for CONFIG."
   (match config
     (($ <tor-configuration> tor config-file services
-                            socks-socket-type control-socket?)
+                            socks-socket-type control-socket?
+                            control-port?)
      (computed-file
       "torrc"
       (with-imported-modules '((guix build utils))
@@ -795,6 +798,16 @@ UnixSocksGroupWritable 1\n" port))
 ControlSocket unix:/var/run/tor/control-sock GroupWritable RelaxDirModeCheck
 ControlSocketsGroupWritable 1\n"
                            port))
+                (when #$control-port?
+                  (format port
+                          "\
+ControlPort ~a
+CookieAuthentication 1
+CookieAuthFileGroupReadable 1
+DataDirectoryGroupReadable 1\n"
+                          #$(if (eq? control-port? #t)
+                                9051
+                                control-port?)))

                 (for-each (match-lambda
                             ((service (ports hosts) ...)
@@ -884,7 +897,12 @@ HiddenServicePort ~a ~a~%"
       ;; Allow Tor to access the hidden services' directories.
       (mkdir-p "/var/lib/tor")
       (chown "/var/lib/tor" (passwd:uid %user) (passwd:gid %user))
-      (chmod "/var/lib/tor" #o700)
+      ;; Allow Tor controllers to access the cookie file if control-port?
+      ;; By default this is where Tor puts the cookie file, and most Tor
+      ;; controllers expect this file location (and not on `/var/run/tor`).
+      (chmod "/var/lib/tor" #$(if (tor-control-port? config)
+                                  #o750
+                                  #o700))

       ;; Make sure /var/lib is accessible to the 'tor' user.
       (chmod "/var/lib" #o755)
--
2.31.0