selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] Run tests in python/ with "make test"
@ 2019-01-05 19:37 Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 1/5] Travis-CI: download refpolicy and install headers Nicolas Iooss
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Nicolas Iooss @ 2019-01-05 19:37 UTC (permalink / raw)
  To: selinux

This patchset follows 4 patches that I sent in December,
https://lore.kernel.org/selinux/20181221204333.27445-1-nicolas.iooss@m4x.org/T/
and makes changes to python/audit2allow/ testsuite in order to make
"make test" work for a non-root user on a non-SELinux system in all
directories. The main addition from this patchset is a dummy SELinux
policy that has been written in order to be able to run audit2allow
on python/audit2allow/test.log.

Each patch describes what it modifies. The full patch series in available on
https://github.com/SELinuxProject/selinux/pull/126

Nicolas Iooss (5):
  Travis-CI: download refpolicy and install headers
  python/audit2allow: make the tests useful again
  python/audit2allow: use local sepolgen-ifgen-attr-helper for tests
  python/sepolgen: refpolicy installs its Makefile in include/Makefile
  python: run all the tests with "make test"

 .travis.yml                              | 14 +++--
 python/Makefile                          |  4 +-
 python/audit2allow/.gitignore            |  1 +
 python/audit2allow/Makefile              |  8 ++-
 python/audit2allow/sepolgen-ifgen        |  8 ++-
 python/audit2allow/test_audit2allow.py   | 19 ++++--
 python/audit2allow/test_dummy_policy.cil | 75 ++++++++++++++++++++++++
 python/chcat/Makefile                    |  2 +
 python/sepolgen/src/sepolgen/defaults.py |  5 +-
 9 files changed, 116 insertions(+), 20 deletions(-)
 create mode 100644 python/audit2allow/test_dummy_policy.cil

-- 
2.20.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] Travis-CI: download refpolicy and install headers
  2019-01-05 19:37 [PATCH 0/5] Run tests in python/ with "make test" Nicolas Iooss
@ 2019-01-05 19:37 ` Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 2/5] python/audit2allow: make the tests useful again Nicolas Iooss
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Nicolas Iooss @ 2019-01-05 19:37 UTC (permalink / raw)
  To: selinux

This is needed in order to run sepolgen-ifgen in audit2allow testsuite.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
 .travis.yml | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 00d0c54a68d7..08a29b2f5adc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -64,14 +64,16 @@ addons:
     - xmlto
 
 install:
-  # Download refpolicy Makefile for sepolgen tests
-  - sudo mkdir -p /usr/share/selinux/default
-  - sudo curl --retry 10 -o /usr/share/selinux/default/Makefile 'https://raw.githubusercontent.com/SELinuxProject/refpolicy/RELEASE_2_20180114/support/Makefile.devel'
-  - sudo sed "s,^PREFIX :=.*,PREFIX := $TRAVIS_BUILD_DIR/installdir/usr," -i /usr/share/selinux/default/Makefile
-  - sudo mkdir -p /usr/share/selinux/refpolicy/include
-  - sudo curl --retry 10 -o /usr/share/selinux/refpolicy/include/build.conf 'https://raw.githubusercontent.com/SELinuxProject/refpolicy/RELEASE_2_20180114/build.conf'
+  # Download and install refpolicy headers for sepolgen tests
+  - curl --location --retry 10 -o "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2" https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_2_20180701/refpolicy-2.20180701.tar.bz2
+  - tar -C "$TRAVIS_BUILD_DIR" -xvjf "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2"
+  # Make refpolicy Makefile use the new toolchain when building modules
+  - sed -e "s,^PREFIX :=.*,PREFIX := \$(DESTDIR)/usr," -i "$TRAVIS_BUILD_DIR/refpolicy/support/Makefile.devel"
+  - sudo make -C "$TRAVIS_BUILD_DIR/refpolicy" install-headers
+  - sudo rm -rf "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2" "$TRAVIS_BUILD_DIR/refpolicy"
   - sudo mkdir -p /etc/selinux
   - echo 'SELINUXTYPE=refpolicy' | sudo tee /etc/selinux/config
+  - echo 'SELINUX_DEVEL_PATH = /usr/share/selinux/refpolicy' | sudo tee /etc/selinux/sepolgen.conf
 
   # Make sepolgen tests work without really installing anything in the real root (doing this would conflict with Ubuntu packages)
   - sed -e "s,\"\(/usr/bin/[cs]\),\"$TRAVIS_BUILD_DIR/installdir\1," -i python/sepolgen/src/sepolgen/module.py
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] python/audit2allow: make the tests useful again
  2019-01-05 19:37 [PATCH 0/5] Run tests in python/ with "make test" Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 1/5] Travis-CI: download refpolicy and install headers Nicolas Iooss
@ 2019-01-05 19:37 ` Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 3/5] python/audit2allow: use local sepolgen-ifgen-attr-helper for tests Nicolas Iooss
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Nicolas Iooss @ 2019-01-05 19:37 UTC (permalink / raw)
  To: selinux

audit2allow testsuite requires a system which uses SELinux with a MLS
policy. This is a lot to ask for a continuous integretation system.
Thankfully this can be worked around by using option -p to run the tools
with a specific configuration. Doing this, the testsuite can even be run
on a system without SELinux.

This approach requires building a custom policy for parsing test.log.
Add a minimal policy written in CIL for this need.

While at it:
* Do not invoke "sudo sepolgen-ifgen" but produce a file in a writable
  directory (instead of /var/lib/sepolgen/interface_info)
* Use sys.executable instead of 'python', in order to really test
  python3 and python2 when calling the test script with one of these
  interpreters.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
 python/audit2allow/.gitignore            |  1 +
 python/audit2allow/Makefile              |  8 ++-
 python/audit2allow/test_audit2allow.py   | 16 +++--
 python/audit2allow/test_dummy_policy.cil | 75 ++++++++++++++++++++++++
 4 files changed, 93 insertions(+), 7 deletions(-)
 create mode 100644 python/audit2allow/test_dummy_policy.cil

diff --git a/python/audit2allow/.gitignore b/python/audit2allow/.gitignore
index 3816d2e0e6ea..2cd46afd0fe7 100644
--- a/python/audit2allow/.gitignore
+++ b/python/audit2allow/.gitignore
@@ -1 +1,2 @@
 sepolgen-ifgen-attr-helper
+test_dummy_policy
diff --git a/python/audit2allow/Makefile b/python/audit2allow/Makefile
index 513bb2b6252a..06fc3b692136 100644
--- a/python/audit2allow/Makefile
+++ b/python/audit2allow/Makefile
@@ -1,4 +1,5 @@
 PYTHON ?= python
+SECILC ?= secilc
 
 # Installation directories.
 PREFIX ?= /usr
@@ -22,9 +23,12 @@ sepolgen-ifgen-attr-helper: sepolgen-ifgen-attr-helper.o $(LIBSEPOLA)
 audit2why:
 	ln -sf audit2allow audit2why
 
-test: all
+test: all test_dummy_policy
 	@$(PYTHON) test_audit2allow.py -v
 
+test_dummy_policy: test_dummy_policy.cil
+	$(SECILC) -o $@ -f /dev/null $<
+
 install: all
 	-mkdir -p $(DESTDIR)$(BINDIR)
 	install -m 755 audit2allow $(DESTDIR)$(BINDIR)
@@ -36,7 +40,7 @@ install: all
 	install -m 644 audit2why.1 $(DESTDIR)$(MANDIR)/man1/
 
 clean:
-	rm -f *~ *.o sepolgen-ifgen-attr-helper
+	rm -f *~ *.o sepolgen-ifgen-attr-helper test_dummy_policy
 
 indent:
 	../../scripts/Lindent $(wildcard *.[ch])
diff --git a/python/audit2allow/test_audit2allow.py b/python/audit2allow/test_audit2allow.py
index 4427dea763b2..0320c6dd5c1b 100644
--- a/python/audit2allow/test_audit2allow.py
+++ b/python/audit2allow/test_audit2allow.py
@@ -1,6 +1,7 @@
 import unittest
 import os
-import shutil
+import os.path
+import sys
 from tempfile import mkdtemp
 from subprocess import Popen, PIPE
 
@@ -25,15 +26,19 @@ class Audit2allowTests(unittest.TestCase):
 
     def test_sepolgen_ifgen(self):
         "Verify sepolgen-ifgen works"
-        p = Popen(['sudo', 'sepolgen-ifgen'], stdout=PIPE)
+        temp_directory = mkdtemp(suffix='audit2allow_test')
+        output_file = os.path.join(temp_directory, 'interface_info')
+        p = Popen([sys.executable, './sepolgen-ifgen', '-p', 'test_dummy_policy', '-o', output_file], stdout=PIPE)
         out, err = p.communicate()
         if err:
             print(out, err)
         self.assertSuccess("sepolgen-ifgen", p.returncode, err)
+        os.unlink(output_file)
+        os.rmdir(temp_directory)
 
     def test_audit2allow(self):
         "Verify audit2allow works"
-        p = Popen(['python', './audit2allow', "-i", "test.log"], stdout=PIPE)
+        p = Popen([sys.executable, './audit2allow', '-p', 'test_dummy_policy', '-i', 'test.log'], stdout=PIPE)
         out, err = p.communicate()
         if err:
             print(out, err)
@@ -41,7 +46,7 @@ class Audit2allowTests(unittest.TestCase):
 
     def test_audit2why(self):
         "Verify audit2why works"
-        p = Popen(['python', './audit2why', "-i", "test.log"], stdout=PIPE)
+        p = Popen([sys.executable, './audit2why', '-p', 'test_dummy_policy', '-i', 'test.log'], stdout=PIPE)
         out, err = p.communicate()
         if err:
             print(out, err)
@@ -49,12 +54,13 @@ class Audit2allowTests(unittest.TestCase):
 
     def test_xperms(self):
         "Verify that xperms generation works"
-        p = Popen(['python', './audit2allow', "-x", "-i", "test.log"], stdout=PIPE)
+        p = Popen([sys.executable, './audit2allow', '-x', '-p', 'test_dummy_policy', '-i', 'test.log'], stdout=PIPE)
         out, err = p.communicate()
         if err:
             print(out, err)
         self.assertTrue(b"allowxperm" in out)
         self.assertSuccess("xperms", p.returncode, err)
 
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/python/audit2allow/test_dummy_policy.cil b/python/audit2allow/test_dummy_policy.cil
new file mode 100644
index 000000000000..795fedc3e746
--- /dev/null
+++ b/python/audit2allow/test_dummy_policy.cil
@@ -0,0 +1,75 @@
+; This is a dummy policy which main aim is to be compatible with test.log
+
+; Define one category and one sensitivity in order to make things work
+(mls true)
+(category c0)
+(categoryorder (c0))
+(sensitivity s0)
+(sensitivityorder (s0))
+(sensitivitycategory s0 (c0))
+
+; Define some users and roles
+(user system_u)
+(user root)
+(user unconfined_u)
+(role system_r)
+(role unconfined_r)
+(userrole root system_r)
+(userrole system_u system_r)
+(userrole unconfined_u unconfined_r)
+(userlevel system_u (s0))
+(userlevel root (s0))
+(userlevel unconfined_u (s0))
+(userrange system_u ((s0)(s0 (c0))))
+(userrange root ((s0)(s0 (c0))))
+(userrange unconfined_u ((s0)(s0 (c0))))
+
+; Define domain types
+(type automount_t)
+(type ftpd_t)
+(type httpd_t)
+(type kernel_t)
+(type nsplugin_t)
+(type postfix_local_t)
+(type qemu_t)
+(type smbd_t)
+
+(roletype system_r automount_t)
+(roletype system_r ftpd_t)
+(roletype system_r httpd_t)
+(roletype system_r kernel_t)
+(roletype system_r postfix_local_t)
+(roletype system_r qemu_t)
+(roletype system_r smbd_t)
+(roletype unconfined_r nsplugin_t)
+
+; Define file types
+(type automount_lock_t)
+(type default_t)
+(type fixed_disk_device_t)
+(type home_root_t)
+(type httpd_sys_content_t)
+(type httpd_sys_script_exec_t)
+(type mail_spool_t)
+(type ssh_home_t)
+(type usr_t)
+(type var_t)
+
+; Define port types
+(type mysqld_port_t)
+(type reserved_port_t)
+
+; Define initial SID
+(sid kernel)
+(sidorder (kernel))
+(sidcontext kernel (system_u system_r kernel_t ((s0) (s0))))
+
+; Define classes
+(class blk_file (getattr open read write))
+(class dir (append open search))
+(class file (execute execute_no_trans getattr open read write))
+(class tcp_socket (ioctl name_bind name_connect))
+(classorder (blk_file file dir tcp_socket))
+
+; The policy compiler requires at least one rule
+(allow kernel_t default_t (file (open read write)))
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] python/audit2allow: use local sepolgen-ifgen-attr-helper for tests
  2019-01-05 19:37 [PATCH 0/5] Run tests in python/ with "make test" Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 1/5] Travis-CI: download refpolicy and install headers Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 2/5] python/audit2allow: make the tests useful again Nicolas Iooss
@ 2019-01-05 19:37 ` Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 4/5] python/sepolgen: refpolicy installs its Makefile in include/Makefile Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 5/5] python: run all the tests with "make test" Nicolas Iooss
  4 siblings, 0 replies; 7+ messages in thread
From: Nicolas Iooss @ 2019-01-05 19:37 UTC (permalink / raw)
  To: selinux

Introduce option --attr-helper to sepolgen-ifgen to make it possible to
override /usr/bin/sepolgen-ifgen-attr-helper and use it in the testuite
in order to test the helper which has been compiled from the project
instead of the one installed on the system.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
 python/audit2allow/sepolgen-ifgen      | 8 +++++---
 python/audit2allow/test_audit2allow.py | 5 ++++-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/python/audit2allow/sepolgen-ifgen b/python/audit2allow/sepolgen-ifgen
index e3f67d430647..c482f227193f 100644
--- a/python/audit2allow/sepolgen-ifgen
+++ b/python/audit2allow/sepolgen-ifgen
@@ -56,6 +56,8 @@ def parse_options():
                       help="print debuging output")
     parser.add_option("-d", "--debug", action="store_true", default=False,
                       help="extra debugging output")
+    parser.add_option("--attr-helper", default=ATTR_HELPER,
+                      help="path to sepolgen-ifgen-attr-helper")
     parser.add_option("--no_attrs", action="store_true", default=False,
                       help="do not retrieve attribute access from kernel policy")
     options, args = parser.parse_args()
@@ -77,7 +79,7 @@ def get_policy():
     return None
 
 
-def get_attrs(policy_path):
+def get_attrs(policy_path, attr_helper):
     try:
         if not policy_path:
             policy_path = get_policy()
@@ -93,7 +95,7 @@ def get_attrs(policy_path):
         return None
 
     fd = open("/dev/null", "w")
-    ret = subprocess.Popen([ATTR_HELPER, policy_path, outfile.name], stdout=fd).wait()
+    ret = subprocess.Popen([attr_helper, policy_path, outfile.name], stdout=fd).wait()
     fd.close()
     if ret != 0:
         sys.stderr.write("could not run attribute helper\n")
@@ -127,7 +129,7 @@ def main():
     # Get the attibutes from the binary
     attrs = None
     if not options.no_attrs:
-        attrs = get_attrs(options.policy_path)
+        attrs = get_attrs(options.policy_path, options.attr_helper)
         if attrs is None:
             return 1
 
diff --git a/python/audit2allow/test_audit2allow.py b/python/audit2allow/test_audit2allow.py
index 0320c6dd5c1b..87e5504ada47 100644
--- a/python/audit2allow/test_audit2allow.py
+++ b/python/audit2allow/test_audit2allow.py
@@ -28,7 +28,10 @@ class Audit2allowTests(unittest.TestCase):
         "Verify sepolgen-ifgen works"
         temp_directory = mkdtemp(suffix='audit2allow_test')
         output_file = os.path.join(temp_directory, 'interface_info')
-        p = Popen([sys.executable, './sepolgen-ifgen', '-p', 'test_dummy_policy', '-o', output_file], stdout=PIPE)
+        p = Popen([
+            sys.executable, './sepolgen-ifgen', '-p', 'test_dummy_policy', '-o', output_file,
+            '--attr-helper', './sepolgen-ifgen-attr-helper'
+            ], stdout=PIPE)
         out, err = p.communicate()
         if err:
             print(out, err)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] python/sepolgen: refpolicy installs its Makefile in include/Makefile
  2019-01-05 19:37 [PATCH 0/5] Run tests in python/ with "make test" Nicolas Iooss
                   ` (2 preceding siblings ...)
  2019-01-05 19:37 ` [PATCH 3/5] python/audit2allow: use local sepolgen-ifgen-attr-helper for tests Nicolas Iooss
@ 2019-01-05 19:37 ` Nicolas Iooss
  2019-01-05 19:37 ` [PATCH 5/5] python: run all the tests with "make test" Nicolas Iooss
  4 siblings, 0 replies; 7+ messages in thread
From: Nicolas Iooss @ 2019-01-05 19:37 UTC (permalink / raw)
  To: selinux

When running "make install-headers" on refpolicy,
/usr/share/selinux/refpolicy/Makefile does not exist but
/usr/share/selinux/refpolicy/include/Makefile does. Use it when
available.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
 python/sepolgen/src/sepolgen/defaults.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/python/sepolgen/src/sepolgen/defaults.py b/python/sepolgen/src/sepolgen/defaults.py
index 533a90412475..6e800695b60f 100644
--- a/python/sepolgen/src/sepolgen/defaults.py
+++ b/python/sepolgen/src/sepolgen/defaults.py
@@ -70,7 +70,10 @@ def attribute_info():
 
 def refpolicy_makefile():
     chooser = PathChooser("/etc/selinux/sepolgen.conf")
-    return chooser("Makefile")
+    result = chooser("Makefile")
+    if not os.path.exists(result):
+        result = chooser("include/Makefile")
+    return result
 
 def headers():
     chooser = PathChooser("/etc/selinux/sepolgen.conf")
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] python: run all the tests with "make test"
  2019-01-05 19:37 [PATCH 0/5] Run tests in python/ with "make test" Nicolas Iooss
                   ` (3 preceding siblings ...)
  2019-01-05 19:37 ` [PATCH 4/5] python/sepolgen: refpolicy installs its Makefile in include/Makefile Nicolas Iooss
@ 2019-01-05 19:37 ` Nicolas Iooss
  2019-01-08 11:04   ` Petr Lautrbach
  4 siblings, 1 reply; 7+ messages in thread
From: Nicolas Iooss @ 2019-01-05 19:37 UTC (permalink / raw)
  To: selinux

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
 python/Makefile       | 4 +---
 python/chcat/Makefile | 2 ++
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/python/Makefile b/python/Makefile
index 80bc124b6233..9b66d52fbd4d 100644
--- a/python/Makefile
+++ b/python/Makefile
@@ -1,8 +1,6 @@
 SUBDIRS = sepolicy audit2allow semanage sepolgen chcat
 
-all install relabel clean indent:
+all install relabel clean indent test:
 	@for subdir in $(SUBDIRS); do \
 		(cd $$subdir && $(MAKE) $@) || exit 1; \
 	done
-
-test:
diff --git a/python/chcat/Makefile b/python/chcat/Makefile
index 290b9a6ec7dc..79620f60ca27 100644
--- a/python/chcat/Makefile
+++ b/python/chcat/Makefile
@@ -17,3 +17,5 @@ clean:
 indent:
 
 relabel:
+
+test:
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 5/5] python: run all the tests with "make test"
  2019-01-05 19:37 ` [PATCH 5/5] python: run all the tests with "make test" Nicolas Iooss
@ 2019-01-08 11:04   ` Petr Lautrbach
  0 siblings, 0 replies; 7+ messages in thread
From: Petr Lautrbach @ 2019-01-08 11:04 UTC (permalink / raw)
  To: selinux; +Cc: Nicolas Iooss

Nicolas Iooss <nicolas.iooss@m4x.org> writes:

> Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>

All 5 merged. Thanks!

> ---
>  python/Makefile       | 4 +---
>  python/chcat/Makefile | 2 ++
>  2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/python/Makefile b/python/Makefile
> index 80bc124b6233..9b66d52fbd4d 100644
> --- a/python/Makefile
> +++ b/python/Makefile
> @@ -1,8 +1,6 @@
>  SUBDIRS = sepolicy audit2allow semanage sepolgen chcat
>  
> -all install relabel clean indent:
> +all install relabel clean indent test:
>  	@for subdir in $(SUBDIRS); do \
>  		(cd $$subdir && $(MAKE) $@) || exit 1; \
>  	done
> -
> -test:
> diff --git a/python/chcat/Makefile b/python/chcat/Makefile
> index 290b9a6ec7dc..79620f60ca27 100644
> --- a/python/chcat/Makefile
> +++ b/python/chcat/Makefile
> @@ -17,3 +17,5 @@ clean:
>  indent:
>  
>  relabel:
> +
> +test:

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-01-08 11:04 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-05 19:37 [PATCH 0/5] Run tests in python/ with "make test" Nicolas Iooss
2019-01-05 19:37 ` [PATCH 1/5] Travis-CI: download refpolicy and install headers Nicolas Iooss
2019-01-05 19:37 ` [PATCH 2/5] python/audit2allow: make the tests useful again Nicolas Iooss
2019-01-05 19:37 ` [PATCH 3/5] python/audit2allow: use local sepolgen-ifgen-attr-helper for tests Nicolas Iooss
2019-01-05 19:37 ` [PATCH 4/5] python/sepolgen: refpolicy installs its Makefile in include/Makefile Nicolas Iooss
2019-01-05 19:37 ` [PATCH 5/5] python: run all the tests with "make test" Nicolas Iooss
2019-01-08 11:04   ` Petr Lautrbach

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).