From debbugs-submit-bounces@debbugs.gnu.org Sat Apr 17 16:04:50 2021 Received: (at submit) by debbugs.gnu.org; 17 Apr 2021 20:04:50 +0000 Received: from localhost ([127.0.0.1]:44720 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lXrBS-0001hf-FQ for submit@debbugs.gnu.org; Sat, 17 Apr 2021 16:04:50 -0400 Received: from lists.gnu.org ([209.51.188.17]:36578) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lXrBQ-0001hX-I1 for submit@debbugs.gnu.org; Sat, 17 Apr 2021 16:04:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43044) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lXrBQ-0004YN-Ba for guix-patches@gnu.org; Sat, 17 Apr 2021 16:04:48 -0400 Received: from mail-qv1-xf30.google.com ([2607:f8b0:4864:20::f30]:42801) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lXrBO-0004JP-O3 for guix-patches@gnu.org; Sat, 17 Apr 2021 16:04:48 -0400 Received: by mail-qv1-xf30.google.com with SMTP id 30so15083268qva.9 for ; Sat, 17 Apr 2021 13:04:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=MdPRAevReTF2QIlUaehKg32z0ego2tRBi0lDbBj+lcY=; b=BlUBgjiEBcTfPcT71KIj79dA4VPDlfDDtN+GbVZZXR+EctcSFIxHFKpdo06fw+tFOu MfM0R2Lr+c+ewWlguv0+iRlQYMeO0Pa49i/U4rU4k3i6UB8XO01EdVJUZA3A3uoJZQBB SEXQwXXTLpAXSRr9mkDakxl1sNB5ilwSkPH25aXJEMbsTDBJyFCYFkeEXfuwxyLT0lPH GiS5ZfY2KCuPOYTRSQ0MBfvp8EXIUrhVeljnFiw8X2ynnFS90eZqNWtmSI9e2O2xfSqJ vK+dsT50579c9ZFCDTLE4RrVTYZgXz9z2pDWcdy6otQHssz1GmE2cC+hP+f8bolimcoa oLQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=MdPRAevReTF2QIlUaehKg32z0ego2tRBi0lDbBj+lcY=; b=AczyBLofjAQpn0GUupQQPpxLQfPWQKhZ6uKgFGYNHYna3Ww1jBoqI5NhH8+kqM+gaG V5odWmmYsSyb8G51BIeKSag7R3ZZmAp7aCmeRtlneX+GUVFhLC6iVnL7O0FT66pWaKQJ hBnVq+KXkQcQv08D5dFp6YvriAazpbBVKA9dhnRbA8B9FQL+kGuWAmun3FEt7jy4XTSw WQ5epbEhqrwZAjPyFFDXgjHcTxxivJATIJ3Qf3vfonz6dgwhQbVgNSB5hlfRiMVI/1U7 EsZ3QRDJ1kgPN9LiBKZsXksJqlAdKmY4N4blyXX0M9bSni3WtSK6q0x5h1wXCgzh65XC qzSQ== X-Gm-Message-State: AOAM533ndkhhRbkevD8e5pmmauwBb9fho402rtbEZm2fOSzuiB8caCQU er6ZxPUjpR8/IP+vBGU9okpQyxtpkFs= X-Google-Smtp-Source: ABdhPJwrArYOYsfQ1RQ/Ztpfo/3YPC2P/9l1nREHXBJ6HAgVelt57gJX/BrcJ3C6xGAEBIgYv0fTwQ== X-Received: by 2002:ad4:538a:: with SMTP id i10mr14296693qvv.9.1618689885300; Sat, 17 Apr 2021 13:04:45 -0700 (PDT) Received: from localhost.localdomain (dsl-152-210.b2b2c.ca. [66.158.152.210]) by smtp.gmail.com with ESMTPSA id l4sm6508084qtn.89.2021.04.17.13.04.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Apr 2021 13:04:45 -0700 (PDT) From: Maxim Cournoyer To: guix-patches@gnu.org Subject: [PATCH 0/1] [preview] Add a jami-daemon service. Date: Sat, 17 Apr 2021 16:04:14 -0400 Message-Id: <20210417200414.18050-1-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=2607:f8b0:4864:20::f30; envelope-from=maxim.cournoyer@gmail.com; helo=mail-qv1-xf30.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.3 (-) X-Debbugs-Envelope-To: submit Cc: Maxim Cournoyer X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) Hello, This is an early version of a jami-daemon service that can be used to host rendezvous points easily on servers, the conferencing feature of Jami. It seems to work well in practice, but I've been struggling to fix a remaining test failure with the stop action. It's proving difficult to pinpoint what the problem is. Another thing that will need to be addressed is adding the documentation. Thanks, Maxim Maxim Cournoyer (1): services: Add a service for the Jami daemon. gnu/local.mk | 6 +- gnu/services/telephony.scm | 283 ++++++++++++++++++- gnu/tests/data/jami-dummy-account.dat | 391 ++++++++++++++++++++++++++ gnu/tests/telephony.scm | 202 +++++++++++++ 4 files changed, 878 insertions(+), 4 deletions(-) create mode 100644 gnu/tests/data/jami-dummy-account.dat create mode 100644 gnu/tests/telephony.scmb -- 2.31.1 From debbugs-submit-bounces@debbugs.gnu.org Sat Apr 17 16:06:48 2021 Received: (at 47849) by debbugs.gnu.org; 17 Apr 2021 20:06:48 +0000 Received: from localhost ([127.0.0.1]:44729 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lXrDF-0001l9-7J for submit@debbugs.gnu.org; Sat, 17 Apr 2021 16:06:48 -0400 Received: from mail-qv1-f52.google.com ([209.85.219.52]:45724) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lXrDB-0001ku-Uu for 47849@debbugs.gnu.org; Sat, 17 Apr 2021 16:06:40 -0400 Received: by mail-qv1-f52.google.com with SMTP id bs7so14601423qvb.12 for <47849@debbugs.gnu.org>; Sat, 17 Apr 2021 13:06:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=U9UD1qqvyDFrvfbHrN7KiOeyUhnT3sNUIFaNgOO2ocA=; b=iYQ/I+O/Dfjv6LdV1xUxSIHalQBYn8aZOpApDcmoy4OED4wQiiwQ9yCh/Mjhb+2Go0 YyCQvbSSCCJhpFXg2HzlkGRdr+Tt3/Ei98PuPvSerxvBpHx6GyIdbTrmZid63yW6Imt6 Lxv21QYo38QeUC2QvMGM+jN4vYmDncdp1FXB0R78JuFafhUbMTxACFEP0zQyUS7nTEoM Z0o3bvsXakxaVYIfqQNhqzFiF734m5sc7F/SL3nWlPbuf18hVgMNTcu5UhpXYELk/bvn Qpv3GuDu/iig+CWx3GUJ8A+xzyE8oZbh6hJJZEfHPC2SHgNxkU5X9igadI9ubA59Ic9W QSWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=U9UD1qqvyDFrvfbHrN7KiOeyUhnT3sNUIFaNgOO2ocA=; b=hrDLCJLs9gV78sNwt9I1WV5RmnLwtwMEGWO04z38Wh5WJSahzQjMUELLixkpGGdTX9 Owoxgn2TEDHU+ZR3O+llIFCpyj8mPsAhF4hVgi+Bbju187Oq4Fk7VRRaCoZ7ltKPCN+B BnOelnku6MbD07C1yqhojQhdkCnbseWA4j27SVDBmlC0eYQkSNKQ9Mk8hlmP2/bcEKId ep9ufg2fI6QLo/PEqXCpeA9bvoZHVxNZOv6zbMZbwIwruReMVBWHrNIrgLezAobsZg6X yRWpPDigQnFaXDEbH2RAbxcilt/Ripwo6z/asr3eziHZVYi7o79UuXldc7syc+ripkZO XGDA== X-Gm-Message-State: AOAM5319ZKvOR1aSoEeG8b+EB8gNkXtOzLWVGHVdvF0kWBKgs4KflvN3 /Fn9wKECMhREDpuRrjgvA2Kd/Dj5H7w= X-Google-Smtp-Source: ABdhPJzR3+6ywinG4fzZYyErGiiKqyYv5M/ULMddnF2NxiNz5KlSxRAoR38HZ6T9+38XEbtqT4wF0w== X-Received: by 2002:a0c:c352:: with SMTP id j18mr14441637qvi.12.1618689991581; Sat, 17 Apr 2021 13:06:31 -0700 (PDT) Received: from localhost.localdomain (dsl-152-210.b2b2c.ca. [66.158.152.210]) by smtp.gmail.com with ESMTPSA id o25sm2517476qtl.37.2021.04.17.13.06.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Apr 2021 13:06:31 -0700 (PDT) From: Maxim Cournoyer To: 47849@debbugs.gnu.org Subject: [PATCH 1/1] services: Add a service for the Jami daemon. Date: Sat, 17 Apr 2021 16:06:17 -0400 Message-Id: <20210417200617.18182-1-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849 Cc: Maxim Cournoyer X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) * gnu/services/telephony.scm (serialize-boolean) (serialize-string-list, string-list?): New variables. (maybe-string-list, jami-daemon-configuration): New syntax. (%jami-daemon-accounts): New variable. (jami-daemon-configuration->command-line-arguments): New procedure. (jami-dbus-session-activation): Likewise. (define-with-retries, define-send-dbus) (jami-daemon-shepherd-services, jami-daemon-service-type): New variables. * gnu/tests/data/jami-dummy-account.dat: New file. * gnu/tests/telephony.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Register the new test file. (dist_patch_DATA): Register the new data file. --- gnu/local.mk | 6 +- gnu/services/telephony.scm | 283 ++++++++++++++++++- gnu/tests/data/jami-dummy-account.dat | 391 ++++++++++++++++++++++++++ gnu/tests/telephony.scm | 202 +++++++++++++ 4 files changed, 878 insertions(+), 4 deletions(-) create mode 100644 gnu/tests/data/jami-dummy-account.dat create mode 100644 gnu/tests/telephony.scm diff --git a/gnu/local.mk b/gnu/local.mk index 50b11a8ca2..4a412f5a69 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -19,7 +19,7 @@ # Copyright © 2018 Amirouche Boubekki # Copyright © 2018, 2019, 2020, 2021 Oleg Pykhalov # Copyright © 2018 Stefan Stefanović -# Copyright © 2018, 2020 Maxim Cournoyer +# Copyright © 2018, 2020, 2021 Maxim Cournoyer # Copyright © 2019, 2020 Guillaume Le Vaillant # Copyright © 2019, 2020 John Soo # Copyright © 2019 Jonathan Brielmaier @@ -710,6 +710,7 @@ GNU_SYSTEM_MODULES = \ %D%/tests/security-token.scm \ %D%/tests/singularity.scm \ %D%/tests/ssh.scm \ + %D%/tests/telephony.scm \ %D%/tests/version-control.scm \ %D%/tests/virtualization.scm \ %D%/tests/web.scm @@ -1829,7 +1830,8 @@ dist_patch_DATA = \ %D%/packages/patches/ytnef-CVE-2021-3403.patch \ %D%/packages/patches/ytnef-CVE-2021-3404.patch \ %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch \ - %D%/packages/patches/zziplib-CVE-2018-16548.patch + %D%/packages/patches/zziplib-CVE-2018-16548.patch \ + %D%/tests/data/jami-dummy-account.dat MISC_DISTRO_FILES = \ %D%/packages/ld-wrapper.in diff --git a/gnu/services/telephony.scm b/gnu/services/telephony.scm index e1259cc2df..9e821f7286 100644 --- a/gnu/services/telephony.scm +++ b/gnu/services/telephony.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 nee +;;; Copyright © 2021 Maxim Cournoyer ;;; ;;; This file is part of GNU Guix. ;;; @@ -17,16 +18,31 @@ ;;; along with GNU Guix. If not, see . (define-module (gnu services telephony) - #:use-module (gnu services) + #:use-module ((gnu services) #:hide (delete)) + #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (gnu packages admin) + #:use-module (gnu packages glib) + #:use-module (gnu packages jami) #:use-module (gnu packages telephony) #:use-module (guix records) + #:use-module (guix modules) + #:use-module (guix packages) #:use-module (guix gexp) #:use-module (srfi srfi-1) #:use-module (ice-9 match) - #:export (murmur-configuration + #:export (jami-daemon-configuration + jami-daemon-configuration-jami-daemon + jami-daemon-configuration-dbus + jami-daemon-configuration-enable-logging? + jami-daemon-configuration-debug? + jami-daemon-configuration-auto-answer? + jami-daemon-configuration-account-archives + + jami-daemon-service-type + + murmur-configuration make-murmur-configuration murmur-configuration? murmur-configuration-package @@ -74,6 +90,269 @@ murmur-service-type)) + + +;;; +;;; Jami daemon. +;;; + +;;; XXX: These dummy definitions is because there's no way to disable the +;;; serialization code from define-configuration. +(define (serialize-boolean option value) "") +(define (serialize-string-list field-name val) "") + +;;; Copied from (gnu services messaging). +(define (string-list? val) + (and (list? val) + (and-map (lambda (x) + (or (computed-file? x) ;XXX: for tests + (and (string? x) (not (string-index x #\,))))) + val))) +(define-maybe string-list) + +(define-configuration jami-daemon-configuration + (jami-daemon + (package libring) + "The Jami daemon package to use.") + (dbus + (package dbus) + "The D-Bus package to use to start the required D-Bus session.") + (enable-logging? + (boolean #true) + "Whether to enable logging to syslog.") + (debug? + (boolean #false) + "Whether to enable debug level messages.") + (auto-answer? + (boolean #false) + "Whether to force automatic answer to incoming calls.") + (account-archives + (maybe-string-list 'disabled) + "A list of Jami account archive (backup) file names to be (re-)provisioned +every time the Jami daemon service starts. These Jami account backups should +@emp{not} be encrypted and their file should be made readable only to the +@samp{jami} user (i.e., not in the store), to guard against leaking the secret +key material of the Jami accounts they contain. When providing this field, +the account directories under @file{/var/lib/jami/} are recreated every time +the service starts, ensuring a consistent state.")) + +(define %jami-daemon-accounts + (list (user-group (name "jami") (system? #t)) + (user-account + (name "jami") + (group "jami") + (system? #t) + (comment "Jami daemon user") + (home-directory "/var/lib/jami")))) + +(define (jami-daemon-configuration->command-line-arguments config) + "Derive the command line arguments to used to launch the Jami daemon from +CONFIG, a object." + (match-record config + (jami-daemon dbus enable-logging? debug? auto-answer?) + `(,(file-append jami-daemon "/lib/ring/dring") + "--persistent" ;stay alive after client quits + ,@(if enable-logging? + '() ;logs go to syslog by default + (list "--console")) ;else stdout/stderr + ,@(if debug? + (list "--debug") + '()) + ,@(if auto-answer? + (list "--auto-answer") + '())))) + +(define (jami-dbus-session-activation config) + "Create a directory to hold the Jami D-Bus session socket." + (with-imported-modules (source-module-closure '((gnu build activation))) + #~(begin + (use-modules (gnu build activation)) + (let ((user (getpwnam "jami"))) + (mkdir-p/perms "/var/run/jami" user #o700))))) + +;; Local definitions to expand in source form in G-exps. +(define define-with-retries + '(define-syntax-rule (with-retries n delay body ...) + "Retry the code in BODY up to N times until it returns #t, +else #f. A delay of DELAY seconds is inserted before each retry." + (let loop ((attempts 0)) + (if (< attempts n) + (or (begin + body ...) ;return #t on success + (begin + (sleep delay) ;else wait and retry + (loop (+ 1 attempts)))) + #f)))) ;maximum number of attempts reached + +(define define-send-dbus + '(define (send-dbus dbus-send interface method . arguments) + "Print the response and return #t on success, else #f." + (let* ((command `(,dbus-send + "--bus=unix:path=/var/run/jami/bus" + "--print-reply" + "--dest=cx.ring.Ring" + "/cx/ring/Ring/ConfigurationManager" ;object path + ,(string-append interface "." method) + ,@arguments)) + (pid (fork+exec-command command + #:user "jami" + #:group "jami"))) + (zero? (cdr (waitpid pid)))))) + +(define (jami-daemon-shepherd-services config) + "Return a running the Jami daemon." + (let* ((jami-daemon (jami-daemon-configuration-jami-daemon config)) + (dbus (jami-daemon-configuration-dbus config)) + (dbus-daemon (file-append dbus "/bin/dbus-daemon")) + (dbus-send (file-append dbus "/bin/dbus-send")) + (accounts (jami-daemon-configuration-account-archives config)) + (declarative-mode? (not (eq? 'disabled accounts)))) + + (list (shepherd-service + (documentation "Run a D-Bus session for the Jami daemon.") + (provision '(jami-daemon-dbus-session)) + ;; The requirement on dbus-system is to ensure other required + ;; activation for D-Bus, such as a /etc/machine-id file. + (requirement '(dbus-system syslogd)) + (start + #~(lambda args + #$define-with-retries + + (define pid (fork+exec-command + (list #$dbus-daemon "--session" + "--address=unix:path=/var/run/jami/bus" + "--nofork" "--syslog-only" "--nopidfile") + #:user "jami" + #:group "jami" + #:environment-variables + ;; This is so that the cx.ring.Ring service D-Bus + ;; definition is found by dbus-send. + (list (string-append "XDG_DATA_DIRS=" + #$jami-daemon "/share")))) + + ;; XXX: This manual synchronization probably wouldn't be + ;; needed if we were using a PID file, but providing it via a + ;; customized config file with the would not + ;; override the one inherited from the base config of D-Bus. + (let ((sock (socket PF_UNIX SOCK_STREAM 0))) + (with-retries 20 1 (catch 'system-error + (lambda () + (connect sock AF_UNIX + "/var/run/jami/bus") + (close-port sock) + #t) + (lambda args + #f)))) + + pid)) + (stop #~(make-kill-destructor))) + + (shepherd-service + (documentation "Run the Jami daemon.") + (provision '(jami-daemon dring)) + (requirement '(jami-daemon-dbus-session)) + (modules `((ice-9 ftw) + (srfi srfi-1) + (srfi srfi-26) + ,@%default-modules)) + (start + #~(lambda args + #$define-with-retries + #$define-send-dbus + + (when #$declarative-mode? + ;; Clear the Jami configuration and accounts, to enforce the + ;; declared state. + (catch #t + (lambda () + (delete-file-recursively "/var/lib/jami/.cache/jami") + (delete-file-recursively "/var/lib/jami/.config/jami") + (delete-file-recursively "/var/lib/jami/.local/share/jami") + (delete-file-recursively "/var/lib/jami/accounts")) + (lambda args + #t)) + ;; Copy the Jami accounts from somewhere readable by root to + ;; a place only the jami user can read. + (let* ((accounts-dir "/var/lib/jami/accounts/") + (pwd (getpwnam "jami")) + (user (passwd:uid pwd)) + (group (passwd:gid pwd))) + (mkdir-p accounts-dir) + (chown accounts-dir user group) + (for-each (lambda (f) + (let ((dest (string-append accounts-dir + (basename f)))) + (copy-file f dest) + (chown dest user group))) + '#$accounts))) + + ;; Start the daemon. + (define daemon-pid + (fork+exec-command + '#$(jami-daemon-configuration->command-line-arguments config) + #:user "jami" + #:group "jami" + #:environment-variables + (list (string-append "DBUS_SESSION_BUS_ADDRESS=" + "unix:path=/var/run/jami/bus")))) + + ;; Wait until it's reachable via D-Bus. + (with-retries 20 1 (send-dbus #$dbus-send + "org.freedesktop.DBus.Peer" + "Ping")) + + ;; Provision the accounts. + (when #$declarative-mode? + (or (every identity + (map (lambda (archive) + (send-dbus + #$dbus-send + "cx.ring.Ring.ConfigurationManager" + "addAccount" + (string-append + "dict:string:string:Account.archivePath," + archive + ",Account.type,RING"))) + (map (cut string-append + "/var/lib/jami/accounts/" <>) + (scandir "/var/lib/jami/accounts/" + (lambda (f) + (not (member f '("." "..")))))))) + (format (current-error-port) + "error: failed provisioning the jami accounts"))) + + ;; Finally, return the PID of the dring process. + daemon-pid)) + (stop + #~(lambda (pid . args) + (kill pid SIGTERM) + ;; Wait for the process to exit; this prevents overlapping + ;; processes when issuing 'herd restart'. + (waitpid pid) + #f)))))) + +(define jami-daemon-service-type + (service-type + (name 'jami-daemon) + (default-value (jami-daemon-configuration)) + (extensions + (list (service-extension shepherd-root-service-type + jami-daemon-shepherd-services) + (service-extension account-service-type + (const %jami-daemon-accounts)) + (service-extension activation-service-type + jami-dbus-session-activation))) + (description "Run the Jami daemon (@command{dring}). This service is +geared toward the use case of hosting Jami rendezvous points over a headless +server. If you use Jami on your local machine, you may prefer to setup a user +Shepherd service for it instead; this way, the daemon will be shared via your +normal user D-Bus session bus."))) + + +;;; +;;; Murmur. +;;; + ;; https://github.com/mumble-voip/mumble/blob/master/scripts/murmur.ini (define-record-type* murmur-configuration diff --git a/gnu/tests/data/jami-dummy-account.dat b/gnu/tests/data/jami-dummy-account.dat new file mode 100644 index 0000000000..026890052d --- /dev/null +++ b/gnu/tests/data/jami-dummy-account.dat @@ -0,0 +1,391 @@ +;;; JSON extracted from an actual Jami account and processed with +;;; Emacs/guile-json. +(define %jami-account-content-sexp + '(("RINGCAKEY" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQURBTkJna3F\ +oa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRQzBxWUozSkYvTzhQRGEKRnUwRnpRcHBCaD\ +gybGJMdURrNTlVU0I0MUJSaS9kdDZGV1BRN29YOVpsY25vNGZzM2dmUHQ0dU1hRVBkVFBGKwowbGN2Q\ +jc2cytQTEFlcjlOZGpVQzQ2ZXp0UnNiNE9aQXc4ZUk1M3EwSU04QWJFd0o0ZjllLzBmQUFueHgrK3Qw\ +CmZDeGV1YTBUaVBqVHBpZVJMNmpwQkd5UGI2Qk5pU2ViTkZCNzJOMTBnbzI4REVQYlhkNE9CNkN1blZ\ +5RGZKSU0KOC9PRy8rMndNamI4WkRwT3JrYy93U2ZHbnQyZXA3U0xKSkgwOFIzV1FKWklsSndrcGdLTH\ +FRakVwWFNpclN4dAozSkdtdXdBdE9LaXFFTXh1R043elV3ZlNINEtHdkRaUFNkZklZVXJ3eEp4aDJZZ\ +3lobG5RRC9SSnhRN3d4YlJBCjFhMUZVV0FzbDhLODk5cEtESk1GL09VOWZMRUx6QlViblpaRDRmSlg1\ +NmcyTlluUnJobS94NG9FbFk0MFNYMUUKcHYzb01hNnZrVGN5RjJnUFhKL2FkUVJoS0dFaGRjaHBpeDl\ +5UVphaDFCUFBGYW5jNzBMcjhOaDZJeHFNQ1hiMQozMG9vWHpWZmZNMVFOd28rL3hzRnBlRkRqUTAxQ0\ +9pdWZocitKREcyc0txb0o0V0JwYVhubWI1YXVrVWUvV1RKCjAxVmRyaEkvSVExd3V4QzNMMnpac3dVU\ +1NTaDk0aXg1M0hpU3pWbkI5UkxmaVhZUUVCcFEyNHVoRTdiYlo0bm0KZTczZC9zenpPTXMzYUt3OWtW\ +a2VLMTVtYWhSVWZjdEdhSVQxTkhGWUNYYXByaWExakdNdVpmSk1pSUtZUzNidQpMbUhZckF6dEptNDZ\ +0aHpjdnN3NHlhMnFoa2xUUlFJREFRQUJBb0lDQVFDaHZaUm85KzZ5aFhFTHZ6U3FXZHcxCkZGOERibG\ +hIMmhVWkNuV0kxMDM5SmdyRkxMczFSU1krSzg1aFZYMk9hV1VTNk44TmNCYzUyL1hrdFltS09HUFQKM\ +WZqMnE2M3pPcDNSSFdGNWVPMXhNeExRN3JZSDhqMGZZTFFTUytKemdwb3ZRVnJLSXkrb21JSSt3aUN6\ +R1laRApGQUM0ODJzL0J5MHdtRjVjdC9JTEdIeVY3ZXNVUlo1Vi9iL0ltQzUwQ1lDUWpQR2xBb3JkeUx\ +1MHp2NjZZUXc2CkQycTg0VHAyVUg3SExEVmhFNytUbDg4Q04xWll0VGtpSkthbkNpMFVmbStPKzJFM0\ +5HM01hajk1aDl2NktqYkoKUlkxeTNDRTVmQmkyUFNLbVVzRjN3SzdhbzJDRks5MTgybmlxL2FaNm5WO\ +Xc3NmVrRjhEOWUvS1pqUE5ZT0xkaApFczBSL2laV3RpbUx2RHdXQWNWNFNnSFFjNXJvNU9yOEFUS1ZK\ +VmlzZGFuWXkvdUhmVXZWN3U5cDVLK2E4SHU2CllabW13ZTh4bnF5M3V2M0VabE9LY20zTnZvWllVMnJ\ +HUUFQQW1sWWQ4WlRsZGxPa1JCSGxxYzllMmJuSnNTQW8KNUhhS0N3aDJsWmZpalVGNXFrMXNQcm1kN3\ +BlMld2VVV3QmVuSjJnS1ZoTE5VVGtHWmtTWGhzNlV3WWRRMjVtRQppQzl6WjhXNkQ2OXBvb0lsTTVXT\ +01ySEs0Rng1ck9vT05kUHQ4NEk1bTI3cnpnbXM4QnJXVUlGLytZZjJ0bGdmClBIR0V4c3ZCK3JRQk52\ +WHU3dXoxcVdFTlJTL2YwR2E3dVF4ZW5sZ2dubHc5M1pNOW1GWXpXb1RpdWFmdnphTnAKWEsrTEVrV2F\ +RYUs1Q0VaNEhmUlhBUUtDQVFFQTUyK240OUxQODlyQkR2bFdsTkxNanJqTDdSb0xyQ3FVZGpQWQpyT1\ +hZS3ZkTkxyS2NTc1hNdkY4YW5HQng1UG5oVDZGY05ic2dzQ3BUUXowMThZYmcrbUUxQno5ZTdFNTJGZ\ +i9NCk9BbWZqSllXUnZueUtiNnB3SGlvOHlXUXlVVk1zZU1CcmpvWk1kNkpPZEZ0K2JITHBWOS9iSkdR\ +a3NTRE04WTkKbWxGQUlUL0gyNTh1K1ZKTWsrT0prU28zZmJQSk5Ja1Q2WVBKVmNaSnZTRGI5QU83WDF\ +lendCOXVRL0FEblZ6YwpSQkJOUVZaTStZS2ZNWFJBdmFuWnlmWFFwaUxCQW8rRVRPSHJCR1dDRUhtSF\ +RCaEZIMTkyamtxNlcrTStvS0R1Cm1xMitMc2hZWTVFc2NpL2hPOVZjK2FCM0hhaGliME03M092MHFNc\ +WZoTncyU1BncHdRS0NBUUVBeDlaR1gxQnQKL3MwdGtNcGV1QWhlWjFqTklnZmFEY0RRTWlmU0k4QjRx\ +WUhiL1hOREQ5NjFQME9zMDdCN2wzNE1iZ3U2QlNwcwpXdSt0Y1hjSFlqQVJUc0Qzd0pSaVRIb0RSQzR\ +YYkxEa2pHRUVCVzRKbFVqZTA1QWZrU0QrdkZSMkJwZStxQlBLCm5yb3Mwd1BWL3RXa3MzY2VFOUlBTV\ +pWWDhQeFA3RVNXbitVZDJEWkZhcVFLb0JybHZXRXhxelpYUEJSVjhoS3QKcFBqWnFkZXFQLzhUZTBtS\ +zh5MEVreXVXOWhFdGZ2Sm5HWXhMNStrSG9xd2hQVk1tODZ5YlZNVHRQYWJTdCtPUwp0WHhJTE9RMWRN\ +QkFabzRxSnNkUUZJcTJnSHA5WFYwa2ZNUms1ajdJT1Q4c2Z6TlpKVkRNK1k5VHVlSGJXSnduCnZsWld\ +VZ2NVZTlBaWhRS0NBUUVBbFJaK2h1ckUvNGdLR2dWUld5bTRrTEJHM2dTTFJHdGhuQXVtSnlzaFoveE\ +wKZ2l1Wk55bll5L2hRQWpDMjdoUnlxb04rRFRid3hjdGVPOUJ3c1poNzBZOVJROHYwOERGVExMVE43O\ +E56UG5OcApBbXY5TGhzZTYxaFBMZU1qTkNVcVZPV3hyWFRMeWk1YkpCM2Z4SnhlWGJmNU5BMUpudUpz\ +eXF1SC82TWJ0cytKCmhkY3p3WFRjMCtBZVBKOS9nOENQZXdKYkMzRFVBQ2R1VlNHWHo4ZWZxcm1xbDd\ +jbnB5ZzBpK2pJRkNpVU8rVEcKVFcxeDg3KzUvUFF2MGtSQ0Z1UUloZ2ZCNkcwWW9vcHBrUWRZdXhKZl\ +pPaHdUUldpbTVMMlF5K294WWZySGVQOQozSlltbGFCMmJiN3kxL1FoQjcvek9VMk1nTEtYdHl4Z09ve\ +EpoQlFwZ1FLQ0FRQkIwSUE4dy9CMkNuMEhRcDhQClhUSTZOelRZRUYzd1NhQkg1SFdBOE5MTWdNaERJ\ +TUxsWnlPcVFrK1pLSGFMM2llWjFxTGRNS3VmQjNESC9idWcKeXRQb2JBVXNsN0lJSGVjVmZWaVpvMml\ +pRXhHUCtEMlB2UUFtRFVGWU90V3FrT2FPSlV2VmJ5ODhOM1NyeW9lZgo5aHpZUGxMWmxFQWNGR055S3\ +FibjJXOENHaU5LSWhXYW1Zd21UclY3T1pkeUcrTi9GZk40Vms1NkZyc1pCTDQ5CmRYU2xGZ045TTBaZ\ +WNleTEvZEpPRE9lSHNuME5VK0gvNFZEUk1hR1NmelpwSkxJOXE4T2FiSWpVM0ttb24wQTcKdzFWeWNU\ +L1FwYlBxRUFVckt5dytvMzV3MlAyaUZ1czZiMlBvUUxFTGFTRVl6K3R6UEw5UTM1ejNRdGdMQytuagp\ +IUmxCQW9JQkFES0Q4NGhrYkphczlIQ00zanNNSU9kb213ZEMvcktxVUxKNHFWZU5QR0xDY2VpNEdocn\ +dlQnNICnNoN0hibFlZSDN2U2Y3RW1iZEVCb2xlWVJsaUx5ZzJDQU1ZOGpNK0lpUEwydk1yM2Y3SzZPT\ +mU0UkVPUFJSZkcKWlJDcTh4a0ZPQlg1SUJUbkVCV3QzdVdyb1NGY2x4RTdUa2I4VkUyVzExTG9ZNlkw\ +TUNPaHdxN21xYXRUVnNrawpTRDNySmkrTFR6a2Y4OEx1bjZZNjdiaFNOTWpKZkFaUXNQc0FTRkJBUTJ\ +rQnE5alRLZGVuaU4yYTJIbm0xNCtrCnJDeU9ZVE14Q2hQbWNpS25pVy9MWnFUL0U1dlNRUGdBVzc0dT\ +VLazJoSjRBajNjRW9NVEwxSytZbStWYWh2U0cKTi8xOFdYQ1JRQkg1d0p2eXJYczBtT29GQlRnTWg4d\ +z0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=") + ("ringAccountKey" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTk\ +Jna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRRDNCdDRnOUVUdk9EVnYKM3hWV0ZlS\ +1Nnbk5uVEF3S2dYa3IrQ1FhdU8vTGZWM01RenNSNHliL3hoaWhhb1Z2c2FtZ3ZRU1haL0M1R3I5QQpE\ +YlAxbHNHclRCK1pXMC9uMXVEb3hmVWdZRWY3SGtVanJtdVFjUGlFWGlUVkNiY002U0NzdVNrMnRxdE1\ +BNjBNClRacVo2LzAvbkEvblR5TnFNaUJNSmFRN0NUb2xOTTh2Z2tvd0tBRW14OGpJUG9YZEttMnd6MD\ +Z6SnhwU1d4WjUKc0FBTkdSSHU0b2ZXNWJiMERvamtnRzFBYUJ6Nm9uSmdKK1JFSWV1UkpNQWFHYmtzW\ +TQ4Z1Z1b21BVTU0UFNvUApFb3psVGdHd1k0cnhJTGE0V1Y0RVZMVExrR240ZTYrRUYrSjIvRURBUFdN\ +bXREdFpUeURCc2t5bStLaDRUT2xPCjdnN3JlUUhLdDd1R21YU0RnbzVKZ2hOOHNVRFUxL1Z2YmFFcUZ\ +tTDJrZWNGOVlVZmNsUWRGY1ZncmIrMkh5R3AKRVc0b3RkZjlYYzhOMWxrbGk1dFBqRGZuQ1U3OHB6QT\ +BxQmV1SWhZTnF1VjhGSm1NemhXeVFDbE1MUEFYbXFVdwpWYlY0MWduM0NkektuUlVhZXFONXlzOG5KQ\ +mRJNDBleWlYRUlvU0VKcFpyT1Z5ck1icnNCQzltaVFpZUFhSnlBClFvcjFaRGlwMkpZNUFza2phUGQ0\ +NGk0MGNkeFpob1RhNnpzako5UjZScllFYjhWTmZQemFLaElwSXJSd2NpbCsKWjFrbUUwSE1kY21ITXR\ +hbWZhK0l6WUR4dDV6OGVOZys1RGpVVG1MRkdyQUVWRW5hNDcxdllxYnk5UCs1T1cvNQpSdkxtUER2Tj\ +dlUURpTlZENlBYRFk5OTY4bTZaaHdJREFRQUJBb0lDQURjOEkrTCtlNE41OEFqcHV0MmEyeVNqCllxY\ +VFUSWowMW1GTWhOWXMwQUdTTUswQncyMkdleXZwNFl3R1EzdnNIOSsvSkEydXdoYkJzazNpUW9FQmlx\ +Q0EKenZmOWdPcDRFNlk0elV6RitwSmQvRnUwSG4wWHBab0Rhdnp2eFN4djNFeUN3b0puYWZuL1FHeGw\ +xZEhoQUtsKwpmZGZjekRCc3NPZ1Y2cGtBd1MyY2wwOHFOT2g3cVhaQWFkYk1sQ1lWM0owU1hhaVZiNz\ +lHZXNvTzNwUVBMUUZiClNjQjFjT2sxYnNxWkpOU244d0xmMis5QVBEdzMwWEtNNHg5eTdRTE42Q3oxQ\ +WpvcFJLQ0NIS3R1SEc4UmVETTIKcnRTbjJmTnltQ0VqeDZGVTB6MHFldDV3Y01UbU5weEZuYXdEMU5s\ +dFpnZXBsSllwTjVKZXNEUmo2cFlnWXBPKwo5UDU2cEdtZVNTVzVxcHRoWFFLQmFsdy8wWXp2YUlYdHp\ +hTnZyNUJzRFNrWkU3cldzODIvQmFzUE1RckFmOGpLClZFMU9pSzcrVllUVTRFVWVoZ0FZOXdzNjFqYk\ +lSSEpQbW9VQXpkWHcyL0d0Vk9JUTFwUFJnOXNYN0JaMmUyV1YKdmd5aThPUEJxRWtwblBiMkU5Z0d1U\ +25rY01OeWFVbUl0c3pFandadW14dnZrUW5HanlTb3pjY2R3dnNQNnBJagpoN0g5VUNQTHdOM0N5N1lp\ +UmliSlZBWlNjZkF6QzhubXNLODQrTzJUZHBzTXk0SEZDMmM4dlZiclpteTVkWC9qCk1ESnBzS25JWlZ\ +JMmpXSzRpRS82aUdIWVdoY3JvWnYvVEJ0YW1SQUxTWDVOYkhhWTI0bXVRSG5yMldtaytld3EKbHRGbC\ +90bXgyVkpWUitMZ0JCUGhBb0lCQVFENEI0MjQyVTgvbkJ4d2RzelhCdWxBOVFTa0I5Zktud0RlRkV3S\ +wp3Nks0eU14YVdRU04ycjRxRDhLcW93OVZVMzRYdkRWbFh0RUlDaVh3Q0hZdW5IL3g3cXNSdEVzbHJM\ +aWg4UHRPClpDSU8zUml4RmlIQXFlQUh2YXF0NVhXdndaREx6WnV2THRJOTdINkZ1QjYxck5qMnhxdlR\ +IN05pUmp2S0R0WXgKR1VtNURoQ094cm9tR0NkWHRnWHJGaS9WRU1TSmpQMkM3OTNrN1pTNmNZL0Nkc1\ +RqWEsrZ1UzeWM3OC9kN1pYbwpKMGg2WFlSdmhlQW9Bd2dkVTl4MWtYL2ZmY2tZK1hUcFRwV2xXWmtlU\ +ytsejBpQkRnUlJzMm45OFZDeTZDRmRZCldsZXZaZy9SWXZ6dzlKdWFVcXArOHpHbHNXR2xuOEhtZW5X\ +Q1luSHJnNFBxQnRkL0FvSUJBUUQrOXhDL1N5ZGIKVWZxMUJHYy95YktZc3RLb3A1azB0d3M0SlUwTzN\ +aT1U3MlZ5YTdLT2lTemdPSzVnL2QzckhMMXR2dHViTDBWNAo1dEF4a1AzSkVYbmxZZU5IVkpROTc2RH\ +NGS3Ztc0FGL2JJdVBsdFBRT1dyM3g1eW1RU3lCOTBUczV0dFdWMTVQCktYYVNnMTZidDhwNS9MeERkZ\ +ng2c1YzN1o5RDFRd21EQllreVFIcWQ4clljTm9ad1M5ZnI3UTZhN1ZNSDVtT3IKbEF5dzBCYVdZQk9k\ +bjFGd0pVV3NlRlpmTy9vNUVqZk9Hd0xMR1hiOEVmQ1hqdlRYcUNHLzNrT1JvN1NkOWY1eQowVjIxMmt\ +YVVNINHNDbFB0SmwzeHpaMWJxQ2RMVDNITWNLUTk5UGFFVFppQnNXQ1lOcXg1c0Q0RGhoMzdZQ2hKCm\ +hlN3VUM1E0MElINUFvSUJBREN1VXR1b0UweloyQjhld2grbUpKdnlPMEh5cENFSnlrTE1Xd3gxejNkV\ +E9nQzEKbmhZMWk4TjNxbTZSYUk0SHdDVHFkTlI3b3ExZ1NJZnZNVHIrem9IdXBUYnBXeUorM3hJeDJU\ +Rk9wL3lnMnByUApURHFqWE94SUJycnc0WU5vaTRIa3poeTVKTnl3a1RpdnBaOWsySVMvQTdTQmNWVGx\ +raENianVDK0pPRWthSTJOClpiWGFZY1p1WElVQ3FzcTM2c3RRbCtWZUxRQWt2VjlHc0wrclRnT09Dbz\ +UrTkdRZEVZQnVoRkMzZlJzL1JhSVoKOWFBRTBFL3BTTWp1a05tTnQ2Mm1NSk1tTUdydXhnWFRRblBRR\ +npNSW43aXB2Z0hxQjRsUDM4emdsbnMvbmZVcgo1NWRuZXk3ejhMRFFETHVIc0RHd3hINzNKQjgrTVR2\ +WGFVbkNwQU1DZ2dFQVNBSGxBL0dvdXR6TFRvWmcxcDRUClI1YnhjZHBycFh5d3VYbW5hclJmY3VldG9\ +nUVNtTGpiS0xRNVk0RXZSTENJTzA5MDNENGNnOG5FTU10L01XTXoKSnZwZll3emJGU2J4THR1anRQSX\ +VhaHR3eXV2UkJIVEM1aG5FL3h0WEE1bWZLTDBHWXpzbmtubm1WL2lzSnBSZwpwZFVnSW5sWEJodkRyR\ +FlreUsvWEp0N1FZWlhlUzI5NXlUd0krZndoamlzVVBlTWEyUmRUUE9rQ01JbUVaNUhZCjJHSmZjS25H\ +SkxDVHpDKzNPcGtQazdFRE4vTUlMS2F3YVUxaGp1cVlKWVVUVmpXQzFEM2VUL1ViWHptM0VQNHMKVEN\ +uYWpCYVMzN0N2YVd4ek5JektXZS9TSXdGbEFmYWNSTHlneUR4Z3Q3bHp1akVObEtvU2xya3h3ckpEND\ +Z2WAptUUtDQVFBcTVQWWxSQjgvNnFiWWt1OTA0NUZRdXk2QWtlYXBaMW0raS9SQzZtbFRvUXB6NDlPU\ +Gs4ZGx5YjVtCndvSVhpaEo2V05jN1RsWlRYMnpQTTRBS0M5VFNBUWJrWDg5bjEyU2VDSUlHbXVINnk0\ +TjZiY2lxZjVVcSsvc0IKcHJKeFRNYlRSUFpqS0VVd1N0SFg1MUQ1bi9sQnZERGY3Y2VEZytsYlE0RjR\ +KMTlPd09oZ1lGcjFheGQvNXd2VgpURjNoVlQwbFZGN2RyRC9iMHZOcmxnbUNjbEk4UDg1a2dkRUhZbG\ +ZtTFoxeXJIMkNXVy9SS0lsWk9ZdFVuNFNpCkp5a2VlNDROWElXU3ovalRBdFRta3VQTzRvUjF5d3dRc\ +jdhUTF5a3hRVm9rVm5vY2xqU0tyQlk4R294a0I0eDIKUDNrb3F1UnkvcUd3QzBnN1o4ZjBTQjNQZVZt\ +eQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==") + ("ringAccountCert" . "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZXakNDQTBLZ\ +0F3SUJBZ0lJRm1tNmZuaWRndEl3RFFZSktvWklodmNOQVFFTUJRQXdUREVRTUE0R0ExVUUKQXhNSFNt\ +RnRhU0JEUVRFNE1EWUdDZ21TSm9tVDhpeGtBUUVUS0RjNVpqSTJaVFZpWTJNeU9EWXlPREppT0dFMwp\ +PRFF6TUdOak1EWXpNakV4T1RFNFkyWm1PVGd3SGhjTk1qRXdOREUyTVRjek1qRXdXaGNOTXpFd05ERT\ +BNVGN6Ck1qRXdXakJKTVEwd0N3WURWUVFERXdSS1lXMXBNVGd3TmdZS0NaSW1pWlB5TEdRQkFSTW9aa\ +k16TkRWbU1qYzMKTldSa1ptVXdOMkUwWWpCa09UVmtZV1ZoTVRFeFpERTFabUpqTVRFNU9UQ0NBaUl3\ +RFFZSktvWklodmNOQVFFQgpCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFQY0czaUQwUk84NE5XL2ZGVllWNHB\ +LQ2MyZE1EQXFCZVN2NEpCcTQ3OHQ5ClhjeERPeEhqSnYvR0dLRnFoVyt4cWFDOUJKZG44TGthdjBBTn\ +MvV1d3YXRNSDVsYlQrZlc0T2pGOVNCZ1Ivc2UKUlNPdWE1QncrSVJlSk5VSnR3enBJS3k1S1RhMnEwd\ +0RyUXhObXBuci9UK2NEK2RQSTJveUlFd2xwRHNKT2lVMAp6eStDU2pBb0FTYkh5TWcraGQwcWJiRFBU\ +ck1uR2xKYkZubXdBQTBaRWU3aWg5Ymx0dlFPaU9TQWJVQm9IUHFpCmNtQW41RVFoNjVFa3dCb1p1U3h\ +qanlCVzZpWUJUbmc5S2c4U2pPVk9BYkJqaXZFZ3RyaFpYZ1JVdE11UWFmaDcKcjRRWDRuYjhRTUE5WX\ +lhME8xbFBJTUd5VEtiNHFIaE02VTd1RHV0NUFjcTN1NGFaZElPQ2prbUNFM3l4UU5UWAo5Vzl0b1NvV\ +1l2YVI1d1gxaFI5eVZCMFZ4V0N0djdZZklha1JiaWkxMS8xZHp3M1dXU1dMbTArTU4rY0pUdnluCk1E\ +U29GNjRpRmcycTVYd1VtWXpPRmJKQUtVd3M4QmVhcFRCVnRYaldDZmNKM01xZEZScDZvM25Lenlja0Y\ +wamoKUjdLSmNRaWhJUW1sbXM1WEtzeHV1d0VMMmFKQ0o0Qm9uSUJDaXZWa09LbllsamtDeVNObzkzam\ +lMalJ4M0ZtRwpoTnJyT3lNbjFIcEd0Z1J2eFUxOC9Ob3FFaWtpdEhCeUtYNW5XU1lUUWN4MXlZY3kxc\ +Vo5cjRqTmdQRzNuUHg0CjJEN2tPTlJPWXNVYXNBUlVTZHJqdlc5aXB2TDAvN2s1Yi9sRzh1WThPODN0\ +NUFPSTFVUG85Y05qMzNyeWJwbUgKQWdNQkFBR2pRekJCTUIwR0ExVWREZ1FXQkJUek5GOG5kZDMrQjZ\ +TdzJWMnVvUkhSWDd3Um1UQVBCZ05WSFJNQgpBZjhFQlRBREFRSC9NQThHQTFVZER3RUIvd1FGQXdNSE\ +JnQXdEUVlKS29aSWh2Y05BUUVNQlFBRGdnSUJBRDMrCjlscFluMjZyeG5pekY2UkNvZFFFVmgvOVF2R\ +Wp1V3dHUWZqa3gxb3VlVjdDMzUyWnpIT2hWU3VGcG43TUxkVFcKamI2dWhMRkpoMWtlTDlYZ0pHalMy\ +V0UwdDlJUGp2UWx5UHIwRWJoWGRJNDJMYUR0NDk0dWQ2MEE0bWg0bW1zbwovcjY2NERKOWMwUjZBOUd\ +QZUJjWi9zekhMQjJ4VmM5M3hYNjVjcmNoVTFLMDBVK2ZZUWtHS0xidFFXeUZzdnlKCmRHdFRxamVlYV\ +VNeGt5dFFWNWFxVHJ1SG4vV3U2RWRZejYrZ0ViQXJHUURRK1J3QmMxMDNGcWRIU0xReWdEWHoKd0pNV\ +GhDREdBVmR6V2NCemJYL1JIZms5bTZzK01HblNJUFBrNG9FOUdFbGdQc2JUZ2FrTzc3aElUdzRxZXJi\ +TAp2M0tiaTVOeVZZVFNVa3hDb0VRSkIrWlZJT3BVNFhRdVAvNkZkWldBRk1LU0Jkd1JLcnRmT1hZT1E\ +xcVBvYU1uCjZPR1VGMU0rYWZ0dTNCMkNhZ2ZMaE5hbVBoSjdxWTNSMzJhK2VRVllvYWlESXZKMElIUH\ +FnQ0NuWXlIaVBHTjQKS3VvaE9IZFpXTkxOUXdIQTg3SDV5NEwrSGZISmdFZFppdWYrbTNMa3JJcnN5M\ +WFoUjgyaEpZVkhreHVyZVRDcQpIR2NJaUIvTHpkSG91WFVrWGNrNjRvWXVRQnM3ZE9KVEx6bGlibU8x\ +elRzVWRoc0d4dE9zc2lYWkFjUURmZHBnCjNHdFJ3UkRwd0ZtL2k5TC9UWjMzMjBwY0VZd21aN1dBSzJ\ +Ra3Z6eWZlelRGeXdLWmh3c0RQRkwycllzLzhXdWsKRk1sek5BVmRMTytTS1RxeGlkM0l1elFaQ0FwU0\ +5ybTJMY2ZVN2grWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBV\ +EUtLS0tLQpNSUlGWFRDQ0EwV2dBd0lCQWdJSXV0T3MxUXBsSVRvd0RRWUpLb1pJaHZjTkFRRU1CUUF3\ +VERFUU1BNEdBMVVFCkF4TUhTbUZ0YVNCRFFURTRNRFlHQ2dtU0pvbVQ4aXhrQVFFVEtEYzVaakkyWlR\ +WaVkyTXlPRFl5T0RKaU9HRTMKT0RRek1HTmpNRFl6TWpFeE9URTRZMlptT1Rnd0hoY05NakV3TkRFMk\ +1UY3pNakExV2hjTk16RXdOREUwTVRjegpNakExV2pCTU1SQXdEZ1lEVlFRREV3ZEtZVzFwSUVOQk1UZ\ +3dOZ1lLQ1pJbWlaUHlMR1FCQVJNb056bG1NalpsCk5XSmpZekk0TmpJNE1tSTRZVGM0TkRNd1kyTXdO\ +ak15TVRFNU1UaGpabVk1T0RDQ0FpSXdEUVlKS29aSWh2Y04KQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0l\ +CQUxTcGduY2tYODd3OE5vVzdRWE5DbWtHSHphVnN1NE9UbjFSSUhqVQpGR0w5MjNvVlk5RHVoZjFtVn\ +llamgremVCOCszaTR4b1E5MU04WDdTVnk4SHZxejQ4c0I2djAxMk5RTGpwN08xCkd4dmc1a0REeDRqb\ +mVyUWd6d0JzVEFuaC8xNy9SOEFDZkhINzYzUjhMRjY1clJPSStOT21KNUV2cU9rRWJJOXYKb0UySko1\ +czBVSHZZM1hTQ2pid01ROXRkM2c0SG9LNmRYSU44a2d6ejg0Yi83YkF5TnZ4a09rNnVSei9CSjhhZQo\ +zWjZudElza2tmVHhIZFpBbGtpVW5DU21Bb3VwQ01TbGRLS3RMRzNja2FhN0FDMDRxS29Rekc0WTN2Tl\ +RCOUlmCmdvYThOazlKMThoaFN2REVuR0haaURLR1dkQVA5RW5GRHZERnRFRFZyVVZSWUN5WHdyejMya\ +29Na3dYODVUMTgKc1F2TUZSdWRsa1BoOGxmbnFEWTFpZEd1R2IvSGlnU1ZqalJKZlVTbS9lZ3hycStS\ +TnpJWGFBOWNuOXAxQkdFbwpZU0YxeUdtTEgzSkJscUhVRTg4VnFkenZRdXZ3Mkhvakdvd0pkdlhmU2l\ +oZk5WOTh6VkEzQ2o3L0d3V2w0VU9OCkRUVUk2SzUrR3Y0a01iYXdxcWduaFlHbHBlZVp2bHE2UlI3OV\ +pNblRWVjJ1RWo4aERYQzdFTGN2Yk5tekJSSkoKS0gzaUxIbmNlSkxOV2NIMUV0K0pkaEFRR2xEYmk2R\ +VR0dHRuaWVaN3ZkMyt6UE00eXpkb3JEMlJXUjRyWG1acQpGRlI5eTBab2hQVTBjVmdKZHFtdUpyV01Z\ +eTVsOGt5SWdwaExkdTR1WWRpc0RPMG1ianEySE55K3pEakpyYXFHClNWTkZBZ01CQUFHalF6QkJNQjB\ +HQTFVZERnUVdCQlI1OG01YnpDaGlncmluaERETUJqSVJrWXovbURBUEJnTlYKSFJNQkFmOEVCVEFEQV\ +FIL01BOEdBMVVkRHdFQi93UUZBd01IQmdBd0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQgpBRWFDblluY\ +m9yWmRhWWZRUmxSb0dtSE94T1g5VFdNMXY0dWEweCtFcG11RDVWRDVlWEY1QVZkMlZadEdaeHYvCkd2\ +VnFBU2l0UTk3ampKV2p2bURWTUZtb3hQSmRYWDFkYTd5cmJYeFRmYm1mM1pac1RpdmZVdWQxYThxdUN\ +3dTUKTnBrdHFjV0JyMHRnNzFhOXlidHJOdm1GczZGRE1WMXkrY2JxYlp1UWlDWnc0WmZhekFaeTRQRG\ +NocE9SNjRCSwpBWFZIT05HcWFoV2hwcDkwd2E0TFEwUTE1U3FDR25kYVI4SHg5MHJOeEdkRjM1T1BLU\ +jd1TDdrWDU4ZGxaWStDClJJK1pKMndYMzJUZzgrc1RtTmNaUTliWDdvS0t3R3E5Uk94SjZJSUhOSnN2\ +bXhaSnlPcmE2N21hNTd3OWxiQnUKSzJlQ3cwZjRDeHdLNU1LNStkbWx6R3dhZmJlMG00TTBvVjlhWUx\ +ZTzAwR3Iza05heW9PdjRRVGtEM2pCMzVSMQpDMGJnQmk2eU1sTVJ2akZ5eEZkOFJpL003VG1jcXNObT\ +B5aklqbkZaenVtMFZTR1NLMXlRU3Flak40S0Y2R0JMCllpZ2JpM3c4WG5HYm9pZGdBUE9ncVVJeTJ1d\ +EU1MllzVXFsVHVncXhtM2xDOUhzaDM2UFJLNURDUG93eHVUNlgKcXo1M1ZiN2h6TkxLelpiRlJzbUdF\ +OFY2cWM2bXZTbUFXa25nL3QwaStXVmdGVkZuZFQrQ0oyNTJsa0ZacGljdAp6ekdETW44VUNDRUp4TDR\ +KTklTM2lLOUhlRys2MlZuay9QOEM3YVpLSXpVdjFud25rcVdUUUFYWDBKckJGdDdICjI5ZDk1RElmRT\ +RuT0FyS0JFNHc2Z1R4SU1uZzVzWi9ZbDFjcG5wUHlsR3VICi0tLS0tRU5EIENFUlRJRklDQVRFLS0tL\ +S0K") + ("ethKey" . "fN8cOT1lYNziaW0+pjBIgZ8r6+zMMhHsukkWBNPDsFo=") + ("TURN.username" . "ring") + ("TURN.server" . "turn.jami.net") + ("TURN.realm" . "ring") + ("TURN.password" . "ring") + ("TURN.enable" . "true") + ("TLS.verifyServer" . "true") + ("TLS.verifyClient" . "true") + ("TLS.serverName" . "") + ("TLS.requireClientCertificate" . "true") + ("TLS.privateKeyFile" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQU\ +RBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRQzM5b1Z0cXNtUGdaSUgKcHpTV\ +GtlT3BlWC9CSEx2KzFTYnJPSFpVRHEwNFZCUU5BNmJmSFNSWTJpbHE1WEVheXNVSmwzQmsvM0txZEhS\ +cQpEV01wQ1dpcE1Vc2FwSGxJR0tSWHEwbXhQZ29WODZSUVBub1dCRTdhWVVEZTlJZXlxMmllZXpDK1l\ +YSnBtWTljCk5tblpaMFlHOHJGMEVpWFA0SHpVWGphZklTKzdKTTJ5ZTZyUlpINXBvdHBQNmV4NXhqVU\ +VuNEFFdWhuWGJ6U0EKNnZMaC9wYnhIUVBHMVlmNHFhcU9TY1lXV0ZWaE5ySVBCVFJNZ2RaTWRGRTh0W\ +VFyaUNkNTV4dUhrYncrQmY1VQpmVENqN25tVEcybDJNbGcrSXBHVkFXUFRWNkl0NFNiS3VadW5MZmRD\ +S2FrSU03SnA3V2dJWjZNRHdkaFFQWjJNClJPQzN0b0c1ajh4aFZOU0Q5QlZiOGZBcnRmeHdldlliQk1\ +yOEdRV2JQYlRKYk9tZHZnUGRGcXNTb1F4QnRUcWQKSG1TMG53RjJ4UGZrdm1Cd3BSWWhHNHpuZlVtMl\ +BQcDBIK1g5Sk96d0R1QWI5K0c0cWZtK3Z6bDd1N0o3anJ0TQpHQlJlSlREdGFNd2RHa0lmcUNRZGREZ\ +HFpM1hzVHVVOVNubVN4NkdxT2V6ZU04bk55dmtZWjR2Uk9vODFzU1JjCjQ4L3pZZjJ1OFBJUm4vVy9x\ +Zk9hbjVIbkcxeFNBUDZkcHAzQ1Y0YTgwUFduZyszcXQ4NW5Ha2k2Nk00NUlnRjgKNHZwRGUyM2YyZnp\ +rTk5OOTk1VTBvUStKVGg5eG1HaWJmenlCaXk5d3RUVHVYWDB3Y3gwTm9wNjdYaFFDVVBGSApybVd6Wj\ +V5bXhEdkRhcUN1U3NwcG0vTkRVRWQyc1FJREFRQUJBb0lDQUYyWXo4bzhXdERvMjZPSkx2Ym1BeTcyC\ +jRra2VsWWZTYXpyQ1AzSUZCWnpqS2xCMHl6STVZWVRUZXI4b2ZhTmtCMXdaOE5WeUlxVVhHeVBhSzls\ +MU1BcmwKU1pFRW5iQlEyVXpCbVh6VVU4MVhhUUpxeHpMc2ZqSWR5U09teG1QaFVobFFGRHpJMTYxaXM\ +4MzI0V1A3WjJXaApsU2U1RkFQdjg1TVpYREVhY1c2R0N5SUVTYVMvdkpHQ2loQ2VzL0pCSmpoejdtNT\ +VRU3liSjl0dnJxUE5KSDhJCmhDTm1BUWhEU3NPYVJXNlpBdGV6UEdUb0FQUHNHMXhLMGdwUlVDM1YyR\ +C90bGRRa0VlSjhxaW5TaUN6ZjZIc3cKTnpncjVUbTMzTm96R3Rjc2Z4ZFl0cVB1UzRPRG40bktLSFpE\ +MTBLTng2Qi9HakdQTHIra21jUUVSMUV4U2s2QwpSemtzSTRzRml6VnVLYTFNK2ZqaVNVc3RTdHV1cTJ\ +QQTJJNzFNTTZlMHJmU3ZKM3VESEJYOWY5T1RFaGxZUFBkCnB1VWM2ek1pdEJKRTg2SFo1M08wR0MzdG\ +p1M1BnSnhmWnJyMHBCU20rSzQ3ajVTUFNkaytiVGh3UDZDZDhzWGUKNmljS3YvMXI0SjVqd1pFTmRna\ +2hKeHVuMkE1WVA0c0NBU21JSFFXWmU1cGdFQ0ljUXBHZjNBVllVdVpGeXZ6cApLL3VBRTc0L3NMK0VU\ +UnhDUlhkN0ZJM2cwZFVySTA2WUFIV1FkY1JpdWpIUU12ZXB3V2RrdUdkaE9wV3VRTy9oCjc0MGgvRlZ\ +0dFdOMjc3ajhhc3ptSDA3T2lRWFIwTU1mN2FEaldMaElMYkd2YkV4TzN0TnRBYXZ6cGxmMUNSNk8KUm\ +1nNDdhVTZpR3lON1MwTE85RUJBb0lCQVFEWWMwelh2UmJHTWxkVVZnOFFTT1ZHKzV4NXVocTVyQ2xtQ\ +lp2ZApvYitWS1hkMXBONThraWkxTFBiYUJmZG9JcWVUamdOK0E0YnVpT3RGNjdCWUdISkp0WTk4ZWR5\ +RkpZREtCSzIyCmthRml2eWVuV01UWG5jaHMvUmNXMnVGS1M3cFAyNDRXYkF2clQxZGxmTTF3L1JzbTZ\ +QVjF1dndPSmNJcEdLSzgKWWgyN2hiaThUbEF6bnJCSS9TbGZwNlpxV3Y0MFRLanNNdmVGVFNWRU5yd1\ +F2MVl4TjcxbjA1UWRVUkIrT0lJSQpPenpNMWpNcm43cjNmS3RKTEx0RllEdUhJZzJDL2E0cUZORmpjM\ +296V1laQkhlcDkrWlEyOTgxdy96VTJIZ0oxCkxiajZjMy9qQU5EakI3MnRkcWMxVUkvMWhwVUh2WDJz\ +emY2czM0L3VSY3RlaFgxWEFvSUJBUURaazVaT01RdVMKNzlVQkhCeTRFbFR2cVkvUUxjMUd1aG9LVXE\ +0dzhONEtJZlpMSDk5TTcwek9JWjNoaEdaYWJDREZHN3RqSDl4Vwo3UnhXVWt5cFRDK1h5TTc1YjF0YW\ +9jRVVyZ1hnUnE4R1JFRXg3OUtwWUE3ei95TVc1OHJCTWhHTWlGZ1JTM00zCmNQSzg2dHBvaTFDN2crd\ +lUxcjJwcDEzN0habzZiUHpKTFRPNXA1OG1tTFRPQVpKd1VSZ3pzZWJnc1dsWXZlR0wKZWNBZ3lYbUtt\ +WmVSeGRNUFlCK0NmMno1TWZ5Ujk4MHRVSDJPaitGQjlJNExzRTExREphZ2wwS1lHMWxKRTBFagpodEV\ +1cTFOTG9DcVkzYXVKYjhtRUpqNlA2Ylc2SytCZTBlUi9CS1MraGxxb3VOYWEySnlhSDc4Qis2U1VZWE\ +RuCnd6MityWUhVZEI4M0FvSUJBRFlXc2ZnaloyS0Z4KzdxUm45aVIvRXlCUXNpSjNXSWdSdmVnUEdrY\ +nRTZWRSeXYKNDIwcnRRSjVSd0o2aFRXL216S3pSVW9qSlgvTU5VYld1ODEzNW05bThJRkJqb3F6TVhq\ +S0xJSzM1NlZlY1ZGUApUSGs1RTVHd3VTbGI3dnA2N0FieXJaSUswL3VzYXdHUWEySTF6YWd1aE5BenR\ +yTHVXcE9jZFdZditwQVd2WEJJCi9aKzRvd0xLU0tGL3FvVmZVYkRPQzFSaTlCbWFpcHArTndiVVdYeV\ +pHanFzMDVGejVYUTFPTUZIMUV5M3BqZmIKaFlRODRpeTZBZDQzU3dqY3lKV1lRUUtCQzBZWDRFeWVyW\ +Dd1TTkvaEUxbWRHUGlJdmNwVk8zWCt3Ly9LQndZNQorUGtTd1NKc3lTSDRqTkRsSGE2K2VuNUpSNy81\ +YWVVNENiY0lFcWNDZ2dFQkFLelMvNnhDWnZnalN5V2poK2hxCm4wN3plQW1icUJmTEVZNHJtTFBGVUF\ +ucWFqSElNbDV4SXFnRnFkd05pQ1BCQ2RLbnNaUU9KYjVpZjRUTndKa2wKckJRNzdMUFRVVlJQY2dnVU\ +p4Uzc4S0Rnckl5Vys5V1FPTEIxZEJEb3MzUDhhbFlmb3h5eHV1Wko4SFpCY3BWaQpQQkdHdTFnSDd3V\ +0lyUzBmbVhkWlJQNGp5cGRvM3hFUWNXWEZkK1dCZE9EektmcEcwZkFzZTdDSFdDWnpBdmttCkFYQklH\ +OXQxdGZHNWQvMEZTS05GbTVPb0FPT3h3L0xZNTgrL0RmZXd0U0VBcFdRZkxTL1BmSWxVdUdvQ3FwcEM\ +Kc2pOVXVNSGxxc011Z2JsY29mNHNoZityWjMzQldYOEJSNWdIb21mRE1ibDNDQWp5TXd1dHpybzVxcD\ +BBUTBWWApxOGNDZ2dFQkFLakFXVVRYY1F2TE8yYkxOZmJBTUlSVXk1T2lTZmJCbDNYRThSZnNzaUt2V\ +VBnTFcwSlV1V3FLCjdGdUFxTlJPRHhrS0pMSTdyQlo2YVNqNitFWHpUMnJwY2dFWktnSjFOUEFRdFNs\ +UjNJUkcyU3JJdjBFK3UzbkUKK1laa3pOa2Q0MUJqTkRjRm1HV21lZk5ROUJmaVIrZlZFSkZmcE5oSkl\ +mNUloSWU0RUtZUE5VUXNua0tSVTlxUApzWi9idXBXc2w4bWVFcko3bllJQ05ucHpnSHRpNXdSMlliVF\ +VXT01odmRFUldxMnhTV3BBYmtNMElhZDBUc05kCmUrYVRQVmJOMXFibFZLMm1qUTl2YS9JSkVuSE51V\ +E9TREtJeUpvcVArQkxiRTVjQU5acXQ2OFFadWdOc2RxNHkKV2FoeStydU5LS1F3Mk5MYzQzZUtsNmxv\ +bXdtRlFZOD0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=") + ("TLS.password" . "") + ("TLS.negotiationTimeoutSec" . "-1") + ("TLS.method" . "Automatic") + ("TLS.ciphers" . "") + ("TLS.certificateFile" . "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZHVENDQ\ +XdHZ0F3SUJBZ0lJU1pUdlZPQnh3akF3RFFZSktvWklodmNOQVFFTUJRQXdTVEVOTUFzR0ExVUUKQXhN\ +RVNtRnRhVEU0TURZR0NnbVNKb21UOGl4a0FRRVRLR1l6TXpRMVpqSTNOelZrWkdabE1EZGhOR0l3WkR\ +rMQpaR0ZsWVRFeE1XUXhOV1ppWXpFeE9Ua3dIaGNOTWpFd05ERTJNVGN6TWpFd1doY05NekV3TkRFME\ +1UY3pNakV3CldqQlFNUlF3RWdZRFZRUURFd3RLWVcxcElHUmxkbWxqWlRFNE1EWUdDZ21TSm9tVDhpe\ +GtBUUVUS0dFM09XTmwKTURVNE16VmhPRFV5WlRsbU5qWmxOelF3TURjeU5EUXdPVFZpTVdaa1kyVXdO\ +bVV3Z2dJaU1BMEdDU3FHU0liMwpEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUUMzOW9WdHFzbVBnWkl\ +IcHpTVGtlT3BlWC9CSEx2KzFTYnJPSFpVCkRxMDRWQlFOQTZiZkhTUlkyaWxxNVhFYXlzVUpsM0JrLz\ +NLcWRIUnFEV01wQ1dpcE1Vc2FwSGxJR0tSWHEwbXgKUGdvVjg2UlFQbm9XQkU3YVlVRGU5SWV5cTJpZ\ +WV6QytZWEpwbVk5Y05tblpaMFlHOHJGMEVpWFA0SHpVWGphZgpJUys3Sk0yeWU2clJaSDVwb3RwUDZl\ +eDV4alVFbjRBRXVoblhielNBNnZMaC9wYnhIUVBHMVlmNHFhcU9TY1lXCldGVmhOcklQQlRSTWdkWk1\ +kRkU4dFlRcmlDZDU1eHVIa2J3K0JmNVVmVENqN25tVEcybDJNbGcrSXBHVkFXUFQKVjZJdDRTYkt1Wn\ +VuTGZkQ0tha0lNN0pwN1dnSVo2TUR3ZGhRUFoyTVJPQzN0b0c1ajh4aFZOU0Q5QlZiOGZBcgp0Znh3Z\ +XZZYkJNcjhHUVdiUGJUSmJPbWR2Z1BkRnFzU29ReEJ0VHFkSG1TMG53RjJ4UGZrdm1Cd3BSWWhHNHpu\ +CmZVbTJQUHAwSCtYOUpPendEdUFiOStHNHFmbSt2emw3dTdKN2pydE1HQlJlSlREdGFNd2RHa0lmcUN\ +RZGREZHEKaTNYc1R1VTlTbm1TeDZHcU9lemVNOG5OeXZrWVo0dlJPbzgxc1NSYzQ4L3pZZjJ1OFBJUm\ +4vVy9xZk9hbjVIbgpHMXhTQVA2ZHBwM0NWNGE4MFBXbmcrM3F0ODVuR2tpNjZNNDVJZ0Y4NHZwRGUyM\ +2YyZnprTk5OOTk1VTBvUStKClRoOXhtR2liZnp5Qml5OXd0VFR1WFgwd2N4ME5vcDY3WGhRQ1VQRkhy\ +bVd6WjV5bXhEdkRhcUN1U3NwcG0vTkQKVUVkMnNRSURBUUFCTUEwR0NTcUdTSWIzRFFFQkRBVUFBNEl\ +DQVFCZmRCc0p4RVVWeFRBeG5vNll1bEFoR1ZvUAplWG8xMHIwOE5DcDZRZlJxeGJlTkZ5aXEvKzEwSE\ +NpL1RoZk41OVdLNlpudFF4NlFNZUxEUVZTb0NjNzlaaWQ4ClE2RUdsWkp1c2RTTmg0VjVteXRCQVZHZ\ +2J2aXJFWU1Wcm5jWWg3bHR2LzVuSGRsbyt2WXV3Vzh0aEhHTk1TUkIKQmhJN2xydmpqY3NkbVl6L1Bp\ +NFNZdkg3c3RaVWpRYmUzNzh3UE90b3lBMTNybEtQUTF4QjJFbUxISDYya21WTQowa25wL1hQQ2o2alR\ +zakpFWko1NzZNMmloYy9DTzkvREVlWWZ4RFlJb004NEF5dTc0UU9UUVN1cnVHRjF5T1RKCmlxRkltTH\ +hMcWRxNk1Zdmx1QjFmTzlKaU9QaS84UEJFTTVpeGYzajlGOFVMQTZUTU1NSklFR1ROeUNzOWpzQloKR\ +UNiWVgweTY4WWtGYnYzQmNWaGk2K1VVWVhBVUd0akhwQ3Z2VThYaHowL0RVZFVaTkpqejRJeWl1ZE5N\ +dnFjQgppSEJDdkxFS1B4VFd1ZlFZaGM5ZkVXTm1valc1WSsvalBVeDcrQWxPM1RXZm1OclBpWDJuSEd\ +5UG5tYjZIR2hWCmp3UU0wT1h4cGxnZ2dQMWpVZ0VYWWRucStjYzdRMy94RFIvdi9Fd244T1d4OVB3eV\ +Y0WFZwZXY5QnpmeWwyQTMKdFhWVkFKMzJtcTlPQmVadXczdWlWU2E2TWdCVG80eXcrYnBjU2VIU2xXO\ +XNRc1NYY3dUNjhvOUdhR2hMNjdXMApwQWx4R2VxSWRtbTZ0MkxIUCtQQnBtL3BweTMvTmh1NFIwMTNv\ +Znp5V2Y0bEcrVnpWVGE0eXVqU1J3UlluYmZyCjlSWER0L0I5VEg5TnNsamdBQT09Ci0tLS0tRU5EIEN\ +FUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZXakNDQTBLZ0F3SU\ +JBZ0lJRm1tNmZuaWRndEl3RFFZSktvWklodmNOQVFFTUJRQXdUREVRTUE0R0ExVUUKQXhNSFNtRnRhU\ +0JEUVRFNE1EWUdDZ21TSm9tVDhpeGtBUUVUS0RjNVpqSTJaVFZpWTJNeU9EWXlPREppT0dFMwpPRFF6\ +TUdOak1EWXpNakV4T1RFNFkyWm1PVGd3SGhjTk1qRXdOREUyTVRjek1qRXdXaGNOTXpFd05ERTBNVGN\ +6Ck1qRXdXakJKTVEwd0N3WURWUVFERXdSS1lXMXBNVGd3TmdZS0NaSW1pWlB5TEdRQkFSTW9aak16Tk\ +RWbU1qYzMKTldSa1ptVXdOMkUwWWpCa09UVmtZV1ZoTVRFeFpERTFabUpqTVRFNU9UQ0NBaUl3RFFZS\ +ktvWklodmNOQVFFQgpCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFQY0czaUQwUk84NE5XL2ZGVllWNHBLQ2My\ +ZE1EQXFCZVN2NEpCcTQ3OHQ5ClhjeERPeEhqSnYvR0dLRnFoVyt4cWFDOUJKZG44TGthdjBBTnMvV1d\ +3YXRNSDVsYlQrZlc0T2pGOVNCZ1Ivc2UKUlNPdWE1QncrSVJlSk5VSnR3enBJS3k1S1RhMnEwd0RyUX\ +hObXBuci9UK2NEK2RQSTJveUlFd2xwRHNKT2lVMAp6eStDU2pBb0FTYkh5TWcraGQwcWJiRFBUck1uR\ +2xKYkZubXdBQTBaRWU3aWg5Ymx0dlFPaU9TQWJVQm9IUHFpCmNtQW41RVFoNjVFa3dCb1p1U3hqanlC\ +VzZpWUJUbmc5S2c4U2pPVk9BYkJqaXZFZ3RyaFpYZ1JVdE11UWFmaDcKcjRRWDRuYjhRTUE5WXlhME8\ +xbFBJTUd5VEtiNHFIaE02VTd1RHV0NUFjcTN1NGFaZElPQ2prbUNFM3l4UU5UWAo5Vzl0b1NvV1l2YV\ +I1d1gxaFI5eVZCMFZ4V0N0djdZZklha1JiaWkxMS8xZHp3M1dXU1dMbTArTU4rY0pUdnluCk1EU29GN\ +jRpRmcycTVYd1VtWXpPRmJKQUtVd3M4QmVhcFRCVnRYaldDZmNKM01xZEZScDZvM25Lenlja0YwamoK\ +UjdLSmNRaWhJUW1sbXM1WEtzeHV1d0VMMmFKQ0o0Qm9uSUJDaXZWa09LbllsamtDeVNObzkzamlMalJ\ +4M0ZtRwpoTnJyT3lNbjFIcEd0Z1J2eFUxOC9Ob3FFaWtpdEhCeUtYNW5XU1lUUWN4MXlZY3kxcVo5cj\ +RqTmdQRzNuUHg0CjJEN2tPTlJPWXNVYXNBUlVTZHJqdlc5aXB2TDAvN2s1Yi9sRzh1WThPODN0NUFPS\ +TFVUG85Y05qMzNyeWJwbUgKQWdNQkFBR2pRekJCTUIwR0ExVWREZ1FXQkJUek5GOG5kZDMrQjZTdzJW\ +MnVvUkhSWDd3Um1UQVBCZ05WSFJNQgpBZjhFQlRBREFRSC9NQThHQTFVZER3RUIvd1FGQXdNSEJnQXd\ +EUVlKS29aSWh2Y05BUUVNQlFBRGdnSUJBRDMrCjlscFluMjZyeG5pekY2UkNvZFFFVmgvOVF2RWp1V3\ +dHUWZqa3gxb3VlVjdDMzUyWnpIT2hWU3VGcG43TUxkVFcKamI2dWhMRkpoMWtlTDlYZ0pHalMyV0Uwd\ +DlJUGp2UWx5UHIwRWJoWGRJNDJMYUR0NDk0dWQ2MEE0bWg0bW1zbwovcjY2NERKOWMwUjZBOUdQZUJj\ +Wi9zekhMQjJ4VmM5M3hYNjVjcmNoVTFLMDBVK2ZZUWtHS0xidFFXeUZzdnlKCmRHdFRxamVlYVVNeGt\ +5dFFWNWFxVHJ1SG4vV3U2RWRZejYrZ0ViQXJHUURRK1J3QmMxMDNGcWRIU0xReWdEWHoKd0pNVGhDRE\ +dBVmR6V2NCemJYL1JIZms5bTZzK01HblNJUFBrNG9FOUdFbGdQc2JUZ2FrTzc3aElUdzRxZXJiTAp2M\ +0tiaTVOeVZZVFNVa3hDb0VRSkIrWlZJT3BVNFhRdVAvNkZkWldBRk1LU0Jkd1JLcnRmT1hZT1ExcVBv\ +YU1uCjZPR1VGMU0rYWZ0dTNCMkNhZ2ZMaE5hbVBoSjdxWTNSMzJhK2VRVllvYWlESXZKMElIUHFnQ0N\ +uWXlIaVBHTjQKS3VvaE9IZFpXTkxOUXdIQTg3SDV5NEwrSGZISmdFZFppdWYrbTNMa3JJcnN5MWFoUj\ +gyaEpZVkhreHVyZVRDcQpIR2NJaUIvTHpkSG91WFVrWGNrNjRvWXVRQnM3ZE9KVEx6bGlibU8xelRzV\ +WRoc0d4dE9zc2lYWkFjUURmZHBnCjNHdFJ3UkRwd0ZtL2k5TC9UWjMzMjBwY0VZd21aN1dBSzJRa3Z6\ +eWZlelRGeXdLWmh3c0RQRkwycllzLzhXdWsKRk1sek5BVmRMTytTS1RxeGlkM0l1elFaQ0FwU05ybTJ\ +MY2ZVN2grWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS\ +0tLQpNSUlGWFRDQ0EwV2dBd0lCQWdJSXV0T3MxUXBsSVRvd0RRWUpLb1pJaHZjTkFRRU1CUUF3VERFU\ +U1BNEdBMVVFCkF4TUhTbUZ0YVNCRFFURTRNRFlHQ2dtU0pvbVQ4aXhrQVFFVEtEYzVaakkyWlRWaVky\ +TXlPRFl5T0RKaU9HRTMKT0RRek1HTmpNRFl6TWpFeE9URTRZMlptT1Rnd0hoY05NakV3TkRFMk1UY3p\ +NakExV2hjTk16RXdOREUwTVRjegpNakExV2pCTU1SQXdEZ1lEVlFRREV3ZEtZVzFwSUVOQk1UZ3dOZ1\ +lLQ1pJbWlaUHlMR1FCQVJNb056bG1NalpsCk5XSmpZekk0TmpJNE1tSTRZVGM0TkRNd1kyTXdOak15T\ +VRFNU1UaGpabVk1T0RDQ0FpSXdEUVlKS29aSWh2Y04KQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUxT\ +cGduY2tYODd3OE5vVzdRWE5DbWtHSHphVnN1NE9UbjFSSUhqVQpGR0w5MjNvVlk5RHVoZjFtVnllamg\ +remVCOCszaTR4b1E5MU04WDdTVnk4SHZxejQ4c0I2djAxMk5RTGpwN08xCkd4dmc1a0REeDRqbmVyUW\ +d6d0JzVEFuaC8xNy9SOEFDZkhINzYzUjhMRjY1clJPSStOT21KNUV2cU9rRWJJOXYKb0UySko1czBVS\ +HZZM1hTQ2pid01ROXRkM2c0SG9LNmRYSU44a2d6ejg0Yi83YkF5TnZ4a09rNnVSei9CSjhhZQozWjZu\ +dElza2tmVHhIZFpBbGtpVW5DU21Bb3VwQ01TbGRLS3RMRzNja2FhN0FDMDRxS29Rekc0WTN2TlRCOUl\ +mCmdvYThOazlKMThoaFN2REVuR0haaURLR1dkQVA5RW5GRHZERnRFRFZyVVZSWUN5WHdyejMya29Na3\ +dYODVUMTgKc1F2TUZSdWRsa1BoOGxmbnFEWTFpZEd1R2IvSGlnU1ZqalJKZlVTbS9lZ3hycStSTnpJW\ +GFBOWNuOXAxQkdFbwpZU0YxeUdtTEgzSkJscUhVRTg4VnFkenZRdXZ3Mkhvakdvd0pkdlhmU2loZk5W\ +OTh6VkEzQ2o3L0d3V2w0VU9OCkRUVUk2SzUrR3Y0a01iYXdxcWduaFlHbHBlZVp2bHE2UlI3OVpNblR\ +WVjJ1RWo4aERYQzdFTGN2Yk5tekJSSkoKS0gzaUxIbmNlSkxOV2NIMUV0K0pkaEFRR2xEYmk2RVR0dH\ +RuaWVaN3ZkMyt6UE00eXpkb3JEMlJXUjRyWG1acQpGRlI5eTBab2hQVTBjVmdKZHFtdUpyV01ZeTVsO\ +Gt5SWdwaExkdTR1WWRpc0RPMG1ianEySE55K3pEakpyYXFHClNWTkZBZ01CQUFHalF6QkJNQjBHQTFV\ +ZERnUVdCQlI1OG01YnpDaGlncmluaERETUJqSVJrWXovbURBUEJnTlYKSFJNQkFmOEVCVEFEQVFIL01\ +BOEdBMVVkRHdFQi93UUZBd01IQmdBd0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQgpBRWFDblluYm9yWm\ +RhWWZRUmxSb0dtSE94T1g5VFdNMXY0dWEweCtFcG11RDVWRDVlWEY1QVZkMlZadEdaeHYvCkd2VnFBU\ +2l0UTk3ampKV2p2bURWTUZtb3hQSmRYWDFkYTd5cmJYeFRmYm1mM1pac1RpdmZVdWQxYThxdUN3dTUK\ +TnBrdHFjV0JyMHRnNzFhOXlidHJOdm1GczZGRE1WMXkrY2JxYlp1UWlDWnc0WmZhekFaeTRQRGNocE9\ +SNjRCSwpBWFZIT05HcWFoV2hwcDkwd2E0TFEwUTE1U3FDR25kYVI4SHg5MHJOeEdkRjM1T1BLUjd1TD\ +drWDU4ZGxaWStDClJJK1pKMndYMzJUZzgrc1RtTmNaUTliWDdvS0t3R3E5Uk94SjZJSUhOSnN2bXhaS\ +nlPcmE2N21hNTd3OWxiQnUKSzJlQ3cwZjRDeHdLNU1LNStkbWx6R3dhZmJlMG00TTBvVjlhWUxZTzAw\ +R3Iza05heW9PdjRRVGtEM2pCMzVSMQpDMGJnQmk2eU1sTVJ2akZ5eEZkOFJpL003VG1jcXNObTB5akl\ +qbkZaenVtMFZTR1NLMXlRU3Flak40S0Y2R0JMCllpZ2JpM3c4WG5HYm9pZGdBUE9ncVVJeTJ1dEU1Ml\ +lzVXFsVHVncXhtM2xDOUhzaDM2UFJLNURDUG93eHVUNlgKcXo1M1ZiN2h6TkxLelpiRlJzbUdFOFY2c\ +WM2bXZTbUFXa25nL3QwaStXVmdGVkZuZFQrQ0oyNTJsa0ZacGljdAp6ekdETW44VUNDRUp4TDRKTklT\ +M2lLOUhlRys2MlZuay9QOEM3YVpLSXpVdjFud25rcVdUUUFYWDBKckJGdDdICjI5ZDk1RElmRTRuT0F\ +yS0JFNHc2Z1R4SU1uZzVzWi9ZbDFjcG5wUHlsR3VICi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K") + ("STUN.server" . "") + ("STUN.enable" . "false") + ("SRTP.rtpFallback" . "false") + ("SRTP.keyExchange" . "sdes") + ("SRTP.enable" . "true") + ("RingNS.uri" . "") + ("RingNS.account" . "0790738ce15fa05933b49dd77034312787da86c3") + ("DHT.PublicInCalls" . "true") + ("Account.videoPortMin" . "49152") + ("Account.videoPortMax" . "65534") + ("Account.videoEnabled" . "true") + ("Account.username" . "f3345f2775ddfe07a4b0d95daea111d15fbc1199") + ("Account.useragent" . "") + ("Account.upnpEnabled" . "true") + ("Account.type" . "RING") + ("Account.ringtoneEnabled" . "true") + ("Account.rendezVous" . "true") + ("Account.publishedSameAsLocal" . "true") + ("Account.publishedPort" . "5060") + ("Account.publishedAddress" . "") + ("Account.presenceSubscribeSupported" . "true") + ("Account.peerDiscovery" . "false") + ("Account.managerUsername" . "") + ("Account.managerUri" . "") + ("Account.mailbox" . "") + ("Account.localModeratorsEnabled" . "true") + ("Account.localInterface" . "default") + ("Account.hostname" . "bootstrap.jami.net") + ("Account.hasCustomUserAgent" . "false") + ("Account.enable" . "true") + ("Account.dtmfType" . "overrtp") + ("Account.displayName" . "dummy") + ("Account.defaultModerators" . "") + ("Account.audioPortMin" . "16384") + ("Account.audioPortMax" . "32766") + ("Account.archiveHasPassword" . "false") + ("Account.allowCertFromTrusted" . "true") + ("Account.allowCertFromHistory" . "true") + ("Account.allowCertFromContact" . "true") + ("Account.allModeratorEnabled" . "true") + ("Account.alias" . "dummy") + ("Account.activeCallLimit" . "-1") + ("Account.accountPublish" . "false") + ("Account.accountDiscovery" . "false"))) diff --git a/gnu/tests/telephony.scm b/gnu/tests/telephony.scm new file mode 100644 index 0000000000..cdcd00d057 --- /dev/null +++ b/gnu/tests/telephony.scm @@ -0,0 +1,202 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Maxim Cournoyer . +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu tests telephony) + #:use-module (gnu) + #:use-module (gnu packages guile) + #:use-module (gnu tests) + #:use-module (gnu system vm) + #:use-module (gnu services) + #:use-module (gnu services dbus) + #:use-module (gnu services ssh) + #:use-module (gnu services telephony) + #:use-module (guix gexp) + #:use-module (guix modules) + #:export (%test-jami-daemon + %test-jami-daemon-provisioning)) + +;;; +;;; Jami daemon. +;;; + +(define define-with-retries (@@ (gnu services telephony) define-with-retries)) + +(include "data/jami-dummy-account.dat") ;defines %jami-account-content-sexp + +(define %dummy-jami-account + ;; A Jami account archive is a gzipped JSON file. + (computed-file + "dummy-jami-account.gz" + (with-extensions (list guile-json-4 guile-zlib) + #~(begin + (use-modules (json) (zlib)) + (let ((port (open-output-file #$output))) + (call-with-gzip-output-port port + (lambda (port) + (scm->json '#$%jami-account-content-sexp port)))))))) + +(define* (make-jami-daemon-os #:key provisioning?) + (simple-operating-system + (service jami-daemon-service-type + (if provisioning? + (jami-daemon-configuration + (account-archives (list %dummy-jami-account))) + (jami-daemon-configuration))) + (service dbus-root-service-type) + (service openssh-service-type ;for debugging + (openssh-configuration + (permit-root-login 'without-password))))) + +(define %jami-daemon-os + (make-jami-daemon-os)) + +(define %jami-daemon-os-provisioning + (make-jami-daemon-os #:provisioning? #t)) + +(define* (run-jami-daemon-test #:key provisioning?) + "Run tests in %JAMI-DAEMON-OS. When PROVISIONING? is true, test the +accounts provisioning feature of the service." + (define os (marionette-operating-system + (if provisioning? + %jami-daemon-os-provisioning + %jami-daemon-os) + #:imported-modules '((gnu services herd) + (guix combinators)))) + (define vm (virtual-machine + (operating-system os) + (memory-size 512))) + + (define test + (with-imported-modules '((gnu build marionette)) + #~(begin + (use-modules (rnrs base) + (srfi srfi-11) + (srfi srfi-64) + (gnu build marionette)) + + (define marionette + (make-marionette (list #$vm))) + + (mkdir #$output) + (chdir #$output) + + (test-begin "jami-daemon") + + (test-assert "service running" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) (number? pid)))))) + marionette)) + + (test-assert "service can be stopped" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + #$define-with-retries + (setenv "PATH" "/run/current-system/profile/bin") + (let ((pid (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid)))))) + + (assert (number? pid)) + + (match (stop-service 'jami-daemon) + (services ;a list of service symbols + (member 'jami-daemon services))) + ;; Sometimes, the process still appear in pgrep, even + ;; though we are using waitpid after sending it SIGTERM + ;; in the service; use retries. + (with-retries + 19 1 + (not (zero? (status:exit-val + (system* "pgrep" "dring"))))))) + marionette)) + + (test-assert "service can be restarted" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + ;; Start and retrieve the current PID. + (define pid (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid))))) + (assert (number? pid)) + + ;; Restart the service. + (restart-service 'jami-daemon) + + (define new-pid (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid))))) + (assert (number? new-pid)) + + (not (eq? pid new-pid))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami accounts provisioning" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + + #$define-with-retries + + (setenv "PATH" "/run/current-system/profile/bin") + ;; The imported account takes some time to appear in the + ;; account files; retry for up to about 10 s. + (with-retries + 20 1 + (zero? (status:exit-val + (system* "grep" "-r" + #$(assoc-ref %jami-account-content-sexp + "Account.username") + "/var/lib/jami/.local/share/jami/"))))) + marionette)) + + (test-end) + (exit (= (test-runner-fail-count (test-runner-current)) 0))))) + + (gexp->derivation (if provisioning? + "jami-daemon-provisioning-test" + "jami-daemon-test") + test)) + +(define %test-jami-daemon + (system-test + (name "jami-daemon") + (description "Basic tests for the jami-daemon service.") + (value (run-jami-daemon-test)))) + +(define %test-jami-daemon-provisioning + (system-test + (name "jami-daemon-provisioning") + (description "Provisioning test for the jami-daemon service.") + (value (run-jami-daemon-test #:provisioning? #t)))) -- 2.31.1 From debbugs-submit-bounces@debbugs.gnu.org Sun Apr 18 08:13:35 2021 Received: (at 47849) by debbugs.gnu.org; 18 Apr 2021 12:13:36 +0000 Received: from localhost ([127.0.0.1]:45621 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lY6Ix-0006qU-JU for submit@debbugs.gnu.org; Sun, 18 Apr 2021 08:13:35 -0400 Received: from albert.telenet-ops.be ([195.130.137.90]:44590) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lY6Iv-0006qA-Pd for 47849@debbugs.gnu.org; Sun, 18 Apr 2021 08:13:34 -0400 Received: from butterfly.local ([5.23.206.113]) by albert.telenet-ops.be with bizsmtp id uCDY2400C2TKVvH06CDYBp; Sun, 18 Apr 2021 14:13:33 +0200 Message-ID: <1e9354c0744afc2d5d11d3eeecaba31f62e59e65.camel@telenet.be> Subject: Re: [bug#47849] [PATCH 1/1] services: Add a service for the Jami daemon. From: Maxime Devos To: Maxim Cournoyer , 47849@debbugs.gnu.org In-Reply-To: <20210417200617.18182-1-maxim.cournoyer@gmail.com> References: <20210417200414.18050-1-maxim.cournoyer@gmail.com> <20210417200617.18182-1-maxim.cournoyer@gmail.com> Content-Type: multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature"; boundary="=-jfo/kC9siTqVS/AR+Y8P" Date: Sun, 18 Apr 2021 13:41:06 +0200 MIME-Version: 1.0 User-Agent: Evolution 3.34.2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telenet.be; s=r21; t=1618748013; bh=EOKzu+va/f3mlV4if7xaIYLNZfAACpMSyxz7fFR7ku0=; h=Subject:From:To:In-Reply-To:References:Date; b=IK2hFvz+pGV5T0Wzyn45jYF/aIhQenepYpsHFf1QgMmGYEszJdUsJmvFT7sA3ibsl GUnRTLbEgm2rqmiDmzuYr9K0NaQJ1YAVUHwFfbDFS2lDVDBiuSxHWUUykEHL5BNFvw FP6jwe9Myi0/imAazqVgSfoDeDfrg64CcseUTafZXk7g1+hsmj/FpJ6glwnOJI2GaO YF+T2/XfcqFYDZ5v30nA/54QIioIpogIcPnWcB2EPzqTOyFhOGSGUM6ziSdzEruOyv 4aCiST2GEpPt0IPD+HfqdFLc+vu2dXqIlmVSS2R2PgfHhdmX5uOmBPqcxgAzj/exJU jXdAvu3E5hKvQ== X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 47849 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --=-jfo/kC9siTqVS/AR+Y8P Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Maxim Cournoyer schreef op za 17-04-2021 om 16:06 [-0400]: + (delete-file-recursively "/var/lib/jami/.cache/jami"= ) + (delete-file-recursively "/var/lib/jami/.config/jami= ") + (delete-file-recursively "/var/lib/jami/.local/share= /jami") + (delete-file-recursively "/var/lib/jami/accounts")) You might want to verify whether /var/lib/jami/{.cache,.config,.local/share= ,.local} aren't symbolic links. That way, if the Jami daemon is compromised (due to= buffer overflow --> arbitrary code execution or something), the attacker can't tri= ck the shepherd service into deleting arbitrary directories. This attack is _not_ blocked by fs.protected_symlinks. From the sysctl doc= umentation: When set to "1" symlinks are permitted to be followed only when outside a sticky world-writable directory, or [...] /var/lib/jami is not world-writable (I'd hope). Example scenario: * the jami daemon has a security bug that allows arbitrary code execution within the daemon * the attacker exploits this * now the attacker can modify everything under /var/lib/jami * the attacker deletes /var/lib/jami/.config and replaces it with a symli= nk to /home/ANY-USER/.config * eventually, the system reboots * (delete-file-recursively "/var/lib/jami/.config/jami") is run. As "/var/lib/jami/.config" points to "/home/ANY-USER/.config", this means "/home/ANY-USER/.config/jami" is deleted. * thus, ANY-USER loses their jami configuration Does that makes sense to you? Greetings, Maxime. --=-jfo/kC9siTqVS/AR+Y8P Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYHwayxccbWF4aW1lZGV2 b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7qSCAQDJFxwHTTtk3NefZrfxoYn7wiXU bKKWE4wsy018Jz0yPAD/c/j0Ag79AkvEljYjkUgJSS4QjNo7MRPHVgK0cUSR7wE= =pUai -----END PGP SIGNATURE----- --=-jfo/kC9siTqVS/AR+Y8P-- From debbugs-submit-bounces@debbugs.gnu.org Sun Apr 18 08:13:42 2021 Received: (at 47849) by debbugs.gnu.org; 18 Apr 2021 12:13:42 +0000 Received: from localhost ([127.0.0.1]:45623 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lY6J0-0006qj-V1 for submit@debbugs.gnu.org; Sun, 18 Apr 2021 08:13:42 -0400 Received: from albert.telenet-ops.be ([195.130.137.90]:44512) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lY6Iw-0006q6-IG for 47849@debbugs.gnu.org; Sun, 18 Apr 2021 08:13:35 -0400 Received: from butterfly.local ([5.23.206.113]) by albert.telenet-ops.be with bizsmtp id uCDZ2400J2TKVvH06CDaBu; Sun, 18 Apr 2021 14:13:34 +0200 Message-ID: <8f42495246e684121605e7cef2462a068130d5cc.camel@telenet.be> Subject: Re: [bug#47849] [PATCH 1/1] services: Add a service for the Jami daemon. From: Maxime Devos To: Maxim Cournoyer , 47849@debbugs.gnu.org In-Reply-To: <20210417200617.18182-1-maxim.cournoyer@gmail.com> References: <20210417200414.18050-1-maxim.cournoyer@gmail.com> <20210417200617.18182-1-maxim.cournoyer@gmail.com> Content-Type: multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature"; boundary="=-ryJv23nOc+agdtDMxpIP" Date: Sun, 18 Apr 2021 13:47:03 +0200 MIME-Version: 1.0 User-Agent: Evolution 3.34.2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telenet.be; s=r21; t=1618748014; bh=hX0W8pxJNJJXd1odd9HkE2awZNg0APv5UUBMlDHJwQo=; h=Subject:From:To:In-Reply-To:References:Date; b=crcDMqftCo3JDTaVJdOHQstNnKjHb6k8xnUhXk/skqnSNsahXiLZfl4dihGTiGAQF XkpseRRfWND74sjNHcKPUReELVWisvF5rCw3WMob2RLyvFGQF6tWg9ZNUvXJ/n9wiR mBi/csk/dAOS1z4qF+pLob5zCyesZn9LIOg1JzO099TJ9SJg79a1CUztvndTLBomvA okHx9ih0nyp3IV+ZoRXThZMRTX8m/+9ekvBez0nDZ6NiYBFtH7HxyrsUYggfRUg/dt /O08z40IZ4bSCtZ/ou1Cf5/BHn4zJBSIBCIKHU9Dhu/jv9b1k9IHTv+Uh19gNSoUY5 vq2RiUJ/oasmA== X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 47849 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --=-ryJv23nOc+agdtDMxpIP Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Maxim Cournoyer schreef op za 17-04-2021 om 16:06 [-0400]: > + ;; Start the daemon. > + (define daemon-pid > + (fork+exec-command > + '#$(jami-daemon-configuration->command-line-arguments= config) > + #:user "jami" > + #:group "jami" > + #:environment-variables > + (list (string-append "DBUS_SESSION_BUS_ADDRESS=3D" > + "unix:path=3D/var/run/jami/bus")= ))) It would be nice if this could be run in a container that only has access to the relevant parts of the file system (and not, say, /run/setuid-programs). See, e.g., gnu/build/linux-container= .scm. Greetings, Maxime. --=-ryJv23nOc+agdtDMxpIP Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYHwcNBccbWF4aW1lZGV2 b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7hx2AQDtvj1EkLuPKUa7vjy9nYW3l80/ mtgi+KNSxLp9hPMxtgD+JkkjJ8LUfJEgkI24ezKYQyhVyVvonAVA8hPNH2byCgs= =7Vh7 -----END PGP SIGNATURE----- --=-ryJv23nOc+agdtDMxpIP-- From debbugs-submit-bounces@debbugs.gnu.org Mon Apr 19 08:07:35 2021 Received: (at 47849) by debbugs.gnu.org; 19 Apr 2021 12:07:35 +0000 Received: from localhost ([127.0.0.1]:48600 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYSgh-00035y-22 for submit@debbugs.gnu.org; Mon, 19 Apr 2021 08:07:35 -0400 Received: from mail-qt1-f175.google.com ([209.85.160.175]:34334) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYSge-00035k-Fv for 47849@debbugs.gnu.org; Mon, 19 Apr 2021 08:07:34 -0400 Received: by mail-qt1-f175.google.com with SMTP id c6so25824449qtc.1 for <47849@debbugs.gnu.org>; Mon, 19 Apr 2021 05:07:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=4CUJgmRGCvtHnZhdjmuNgryw8vJyB5wL7AMEcxTO9y4=; b=MXDn5CZ3F1bB8KgzvTaW3DhaPusW1v/H5/EYZJlORm7GZdS7S3QrlyHb1LKP8dSjSn gEsCC0uhv8UW/kcbzFUkzosG3G1TTOcZZPmr+P7kAqa/auODOPa073DnWeUMz9xJst/t ABJItGbhixuqtokdc04g6pvTn7LiGdup9xeyuTkjgKNBnzbHfcI7dJqXE6vtcUttMovQ AppbrAXZkNj+H+0Q8cPfzYQ3VTEMGdydGyo55HYdYZFcFPsIWIVgZtT7XT45yMAuxUx3 oLkL0jz3NXTu/lWJke5m2ArLtuF2/Ah2WeSsFeSjVeAAo3iXqib5+rpHApJi3zAnEJyf DcSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=4CUJgmRGCvtHnZhdjmuNgryw8vJyB5wL7AMEcxTO9y4=; b=L2lUuFVMiJHurDd3JxIqC4fQu6n2YeyLutYQneobVksjjktJuu6O3lv/Qfw2CJXLJ0 kRIUOEt1VvGOXZuDnQeAprFNHpdimB5MpEwt+O8e322Kc8JUhGqbrRxbkrjBrYmy29GR yUByUF/ImrwRwcxL4anirmHi2fyk5iYlKDTTiKosRDeFGdlqtIvmQlOPBV7aD7HXsS0H 6j05wFuFItGXjOOaQe6EDw9uXdz89BQC6wxsTd4HNmd83DBftZNXCoLXIxrPQ2NUQv8R k0MfU7OFem15cOZDY7GHjWE0E+XJKXNXB2JAOCpGTnh3QLokfwKq1Bx4HVzeiwXN9A3i HGDg== X-Gm-Message-State: AOAM532VudtMSPnRK9H/9pduVlQSnGV6xEB9D7z2CJIkckxuLMNO+7jH gby5M2ConBZNyCOdw84mpo5G9DszdlhwNg== X-Google-Smtp-Source: ABdhPJwNGmvJ85YrSPQXmlRFTUB+ZiSPx61gOz802VdHfVhr6d4ky/cP24gX6+VMkuqUyPa+JA5m1A== X-Received: by 2002:ac8:5cce:: with SMTP id s14mr11110024qta.305.1618834046795; Mon, 19 Apr 2021 05:07:26 -0700 (PDT) Received: from hurd (dsl-205-151-56-5.b2b2c.ca. [205.151.56.5]) by smtp.gmail.com with ESMTPSA id a4sm8772999qta.19.2021.04.19.05.07.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Apr 2021 05:07:26 -0700 (PDT) From: Maxim Cournoyer To: Maxime Devos Subject: Re: [bug#47849] [PATCH 1/1] services: Add a service for the Jami daemon. References: <20210417200414.18050-1-maxim.cournoyer@gmail.com> <20210417200617.18182-1-maxim.cournoyer@gmail.com> <1e9354c0744afc2d5d11d3eeecaba31f62e59e65.camel@telenet.be> Date: Mon, 19 Apr 2021 08:07:25 -0400 In-Reply-To: <1e9354c0744afc2d5d11d3eeecaba31f62e59e65.camel@telenet.be> (Maxime Devos's message of "Sun, 18 Apr 2021 13:41:06 +0200") Message-ID: <87czuqiiki.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849 Cc: 47849@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi Maxime! Maxime Devos writes: > Maxim Cournoyer schreef op za 17-04-2021 om 16:06 [-0400]: > + (delete-file-recursively "/var/lib/jami/.cache/jami") > + (delete-file-recursively "/var/lib/jami/.config/jami") > + (delete-file-recursively "/var/lib/jami/.local/share/jami") > + (delete-file-recursively "/var/lib/jami/accounts")) > > You might want to verify whether /var/lib/jami/{.cache,.config,.local/share,.local} > aren't symbolic links. That way, if the Jami daemon is compromised (due to buffer > overflow --> arbitrary code execution or something), the attacker can't trick the > shepherd service into deleting arbitrary directories. It would only be able to delete directories that are world writable though, right? Seems the opportunity to cause damage is limited, but it's a simple check to add, so I'll do it. What about if the daemon was run in a container (your suggestion in a following email, to which I agree would be a good thing)? It would prevent this kind of attack, right? > This attack is _not_ blocked by fs.protected_symlinks. From the sysctl documentation: > When set to "1" symlinks are permitted to be followed only when outside > a sticky world-writable directory, or [...] > > /var/lib/jami is not world-writable (I'd hope). No, it's only readable/writable by the 'jami' user of the service: $ sudo ls -ald /var/lib/jami drwx------ 1 jami jami 80 Apr 19 00:38 /var/lib/jami > Example scenario: > * the jami daemon has a security bug that allows arbitrary code execution > within the daemon > * the attacker exploits this > * now the attacker can modify everything under /var/lib/jami > * the attacker deletes /var/lib/jami/.config and replaces it with a symlink > to /home/ANY-USER/.config > * eventually, the system reboots > * (delete-file-recursively "/var/lib/jami/.config/jami") is run. > As "/var/lib/jami/.config" points to "/home/ANY-USER/.config", > this means "/home/ANY-USER/.config/jami" is deleted. > * thus, ANY-USER loses their jami configuration The cleanup code is run as the 'jami' user, so I don't think it'd be able to touch anything under /home/ANY-OTHER-USER/, unless they manually loosened permissions on their home directory (shooting themselves in the foot). > Does that makes sense to you? It does! Thanks for explaining. Maxim From debbugs-submit-bounces@debbugs.gnu.org Mon Apr 19 08:08:44 2021 Received: (at 47849) by debbugs.gnu.org; 19 Apr 2021 12:08:44 +0000 Received: from localhost ([127.0.0.1]:48606 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYSho-00037y-H0 for submit@debbugs.gnu.org; Mon, 19 Apr 2021 08:08:44 -0400 Received: from mail-qk1-f180.google.com ([209.85.222.180]:45898) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYShl-00037d-3m for 47849@debbugs.gnu.org; Mon, 19 Apr 2021 08:08:42 -0400 Received: by mail-qk1-f180.google.com with SMTP id d23so23368389qko.12 for <47849@debbugs.gnu.org>; Mon, 19 Apr 2021 05:08:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=bAf12svVq9chtm3j77Gpe1eNaqrFXCdVqgkPdXGSetc=; b=Ejn/yN2V1sG2Py/mZeXeje77ayY3BVR62uRVosr+tEmbqKJwq9MuNwDaHFoyGW8YrG IhBaGVSmf2G/A8NvA95ir/ilAv4oi2aedxCqKsfbSdW9RHGP9vcVlvKVObk3UP1gEgOS WZ/zrZbGePWw+TqFo+p0Hrtmg/bpKHWaVKz2Its1E1ZZKf4pZzDNLPnJQA5KK848i6Qi BetGttB0fjeKRhDfJYZSkM5SdKB6LHtdJdZsdMzPrpjM1IuaDZAenDqguf+eiXEu5Yie dvMH8SG3bcRtNutlHPVfH3zuqGPOhk5459WJgiTWy5N9ljaMC3QvIlQA7cUE89/YG9YC 39qA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=bAf12svVq9chtm3j77Gpe1eNaqrFXCdVqgkPdXGSetc=; b=IYy+77zutiEpSsRyvEfzf9seka23Vz8KeVwIfhS43gSBmGAQvZZD4RLdD5WU1sUUzi U0eAFBhSLmnfC+1IuzNHykwAC4N8kcnN5SkYetCPFoxb70piFd6AMVmO8oxT//NqDYLi ET/ORWiPtLmgJyUd1N22p/ZdDgfcrpqTtGEA4bYhxxOnvZlryDlI8dtgMi0Seb6xg4HY NA2keGASHx0DO8LGkGpgFTbD6QjUaeVgB4bFaSYDgNAWW+Ai+t+tgv+xkx7ckSql2FsY sp48i5igGOtw7f0yV9rUGLQoxz5GqBai76vc7/dYcoodsJDW/+sa9xstw8YDGJbp4i+s FoWg== X-Gm-Message-State: AOAM532zf0YA2IRCvjAZyUiTcEl1zMT8l/o+o+sw7Gvvwc5Y4AN5LdKz l4CbvOti5xx3HJxzxHatLEbmL2dCqtUcrg== X-Google-Smtp-Source: ABdhPJy+DYC6EbGpGX+twoIIYGXaRNDBr5zDLfwkjaiA4Ij3XMvZimGqnntrIJXQXZjp1+fO0SCWrQ== X-Received: by 2002:a05:620a:2058:: with SMTP id d24mr2906015qka.469.1618834115637; Mon, 19 Apr 2021 05:08:35 -0700 (PDT) Received: from hurd (dsl-205-151-56-5.b2b2c.ca. [205.151.56.5]) by smtp.gmail.com with ESMTPSA id q205sm9641886qka.99.2021.04.19.05.08.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Apr 2021 05:08:35 -0700 (PDT) From: Maxim Cournoyer To: Maxime Devos Subject: Re: [bug#47849] [PATCH 1/1] services: Add a service for the Jami daemon. References: <20210417200414.18050-1-maxim.cournoyer@gmail.com> <20210417200617.18182-1-maxim.cournoyer@gmail.com> <8f42495246e684121605e7cef2462a068130d5cc.camel@telenet.be> Date: Mon, 19 Apr 2021 08:08:34 -0400 In-Reply-To: <8f42495246e684121605e7cef2462a068130d5cc.camel@telenet.be> (Maxime Devos's message of "Sun, 18 Apr 2021 13:47:03 +0200") Message-ID: <878s5eiiil.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849 Cc: 47849@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi again, Maxime Devos writes: > Maxim Cournoyer schreef op za 17-04-2021 om 16:06 [-0400]: >> + ;; Start the daemon. >> + (define daemon-pid >> + (fork+exec-command >> + '#$(jami-daemon-configuration->command-line-arguments config) >> + #:user "jami" >> + #:group "jami" >> + #:environment-variables >> + (list (string-append "DBUS_SESSION_BUS_ADDRESS=" >> + "unix:path=/var/run/jami/bus")))) > > It would be nice if this could be run in a container > that only has access to the relevant parts of the file system > (and not, say, /run/setuid-programs). See, e.g., gnu/build/linux-container.scm. I agree! The opendht service is already doing so, so it should not be too difficult I believe. I'll try looking into it, after the 1.3.0 release is done. Thank you! Maxim From debbugs-submit-bounces@debbugs.gnu.org Mon Apr 19 10:41:35 2021 Received: (at 47849) by debbugs.gnu.org; 19 Apr 2021 14:41:35 +0000 Received: from localhost ([127.0.0.1]:51554 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYV5i-0008Is-Vc for submit@debbugs.gnu.org; Mon, 19 Apr 2021 10:41:35 -0400 Received: from laurent.telenet-ops.be ([195.130.137.89]:46684) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYV5g-0008Ih-3e for 47849@debbugs.gnu.org; Mon, 19 Apr 2021 10:41:33 -0400 Received: from ptr-bvsjgyjmffd7q9timvx.18120a2.ip6.access.telenet.be ([IPv6:2a02:1811:8c09:9d00:aaf1:9810:a0b8:a55d]) by laurent.telenet-ops.be with bizsmtp id uehW2400K0mfAB401ehWdE; Mon, 19 Apr 2021 16:41:30 +0200 Message-ID: <9fc5f3f454a77ccf2a8e09fa602755166c03abf3.camel@telenet.be> Subject: Re: [bug#47849] [PATCH 1/1] services: Add a service for the Jami daemon. From: Maxime Devos To: Maxim Cournoyer Date: Mon, 19 Apr 2021 16:41:20 +0200 In-Reply-To: <87czuqiiki.fsf@gmail.com> References: <20210417200414.18050-1-maxim.cournoyer@gmail.com> <20210417200617.18182-1-maxim.cournoyer@gmail.com> <1e9354c0744afc2d5d11d3eeecaba31f62e59e65.camel@telenet.be> <87czuqiiki.fsf@gmail.com> Content-Type: multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature"; boundary="=-Gs+1+lPGRZJ1CxpmLWgP" User-Agent: Evolution 3.34.2 MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telenet.be; s=r21; t=1618843290; bh=j3eBlX83M+iPkmNBIj3IP4J4FwuxHMRybjfp15N+mG8=; h=Subject:From:To:Cc:Date:In-Reply-To:References; b=Yci767cQWVN/rdFFN8vlDWXYUjeAIa4/w/aVZaTOcfusH3KZ5RlMPF1MFFqgaaRny uO6dfui+MNU8Nj5mQII2enGtvlJ8g4ITIX23d63e77WNzLaAKSCEHXDbjqq/DvxKWo IhpBrvTPdAJLUwbX5E4a6NDquTu88K9zGwUOi7hW5fidvsXatWSbDS3eeUajmO/DM+ E/NNTmUHhq5qjTj+PmKK7yhSYeNMAnxsDZygEOvMCcfITwh1SwRo3qzIRnXtndCnCf celRSLatsij5X2tAnbE2z1bhbxEMN3saBzmmeLv3S7n46ReHvF5GoFXbqAKt/xTKbp cVuog2ACVY/xg== X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 47849 Cc: 47849@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --=-Gs+1+lPGRZJ1CxpmLWgP Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Maxim Cournoyer schreef op ma 19-04-2021 om 08:07 [-0400]: > Hi Maxime! >=20 > Maxime Devos writes: >=20 > > Maxim Cournoyer schreef op za 17-04-2021 om 16:06 [-0400]: > > + [...] > > + (delete-file-recursively "/var/lib/jami/account= s")) > >=20 > > You might want to verify whether /var/lib/jami/{.cache,.config,.local/s= hare,.local} > > aren't symbolic links. That way, if the Jami daemon is compromised (du= e to buffer > > overflow --> arbitrary code execution or something), the attacker can't= trick the > > shepherd service into deleting arbitrary directories. >=20 > It would only be able to delete directories that are world writable > though, right? Seems the opportunity to cause damage is limited, but > it's a simple check to add, so I'll do it. Let's step through the relevant code of the shepherd service. (shepherd-service (documentation "Run the Jami daemon.") [blabla] (start #~(lambda args [other stuff] (when [blabla, and a 'catch' form] (delete-file-recursively "/var/lib/jami/.cache/jami") [etcetera]) (let* (([blabla]) (user (passwd:uid [blabla jami user])) (group [likewise])) [blabla] (chown accounts-dir user group))) ;; Start the daemon (define daemon-pid (fork+exec-command [blabla Jami cmdline arguments] #:user "jami" #:group "jami" [blabla])) [blabla])) (stop [blabla])) =20 Remember that the shepherd daemon is run as root (and therefore has read-write-execute access to everything). The 'start' procedure (and 'stop' procedure) are run _within_ the shepherd daemon. Thus, the 'start' gexp is run as root. As the start procedure didn't change the uid/gid from root to something else, (delete-file-recursively "/var/lib/jami/.cache/jami") is run as root. IIUC, root user can read/write anything, ignoring things like "user" and "group". World-writability is not required. > What about if the daemon was > run in a container (your suggestion in a following email, to which I > agree would be a good thing)? It would prevent this kind of attack, > right? I don't see how that would help. It is the _shepherd daemon_ (that runs as root) that runs (delete-file-recursively ...), not the attacker (from within the compromised jami-daemon process). Perhaps this is cleared up by my previous response? If not, please walk me through the attack scenari= o you had in mind that would be thwarted by running the jami-daemon in a cont= ainer. > > Example scenario: > > * the jami daemon has a security bug that allows arbitrary code execu= tion > > within the daemon > > * the attacker exploits this > > * now the attacker can modify everything under /var/lib/jami > > * the attacker deletes /var/lib/jami/.config and replaces it with a s= ymlink > > to /home/ANY-USER/.config > > * eventually, the system reboots > > * (delete-file-recursively "/var/lib/jami/.config/jami") is run. > > As "/var/lib/jami/.config" points to "/home/ANY-USER/.config", > > this means "/home/ANY-USER/.config/jami" is deleted. > > * thus, ANY-USER loses their jami configuration >=20 > The cleanup code is run as the 'jami' user, Err, the cleanup code is run from within the shepherd service, outside the fork+exec-command. The shepherd service is run _within_ the shepherd daemo= n, which runs as *root*. Only in the fork+exec-command, code is run as the 'j= ami' user; the cleanup code is run as 'root'. > so I don't think it'd be able to touch anything under /home/ANY-OTHER-USE= R/, > unless they manually loosened permissions on their home directory (shooti= ng > themselves in the foot). See my comment above. Greetings, Maxime. --=-Gs+1+lPGRZJ1CxpmLWgP Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYH2WkBccbWF4aW1lZGV2 b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7mCIAP9jTTa/0eekxqBmhORKYGL12rVg E1ZdgcCXyh36NjjXPQEA/m3pbrue/O1BDrlXO1zgfJoxFMF/6JGQcKS77cbjXwY= =1rqa -----END PGP SIGNATURE----- --=-Gs+1+lPGRZJ1CxpmLWgP-- From debbugs-submit-bounces@debbugs.gnu.org Mon Apr 19 11:42:22 2021 Received: (at 47849) by debbugs.gnu.org; 19 Apr 2021 15:42:22 +0000 Received: from localhost ([127.0.0.1]:51777 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYW2Y-0001YI-5E for submit@debbugs.gnu.org; Mon, 19 Apr 2021 11:42:22 -0400 Received: from mail-qv1-f52.google.com ([209.85.219.52]:46609) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lYW2W-0001Y4-Ch for 47849@debbugs.gnu.org; Mon, 19 Apr 2021 11:42:21 -0400 Received: by mail-qv1-f52.google.com with SMTP id h3so16309051qve.13 for <47849@debbugs.gnu.org>; Mon, 19 Apr 2021 08:42:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=RSxKVTB4DhCWQVBqWYnlT2IXfOQlDi1uszuu4Jsd0V4=; b=BNxcQaMTZLoqqm5zJFBYRwLycxvM68gbHcUgVtN0XG9UkESYRSYw1HmeHR8k6LoAef c/aWux7Dlr1YCqYhQt+C/vsmNdpaNjtH0oA9oIjJaBB8fw9RixQ54S+9XQj9k4zuurDJ R1Snlnb9buNRSCGcnJfMaXrHTIQp6WyG69G4sASgD0253Oaf63JVl2zMSVMkb+hjIkLu d2bit7SdGBwSOZ3QDrGUaM5D0vlVAxepd9/4LI7cq4ItWvdh73FhcCpYj6BXonPYqnzW Wd/blAVBQoHiceuwhpWkfeGtPgPEj9n6Bay9FrpHlD04rR/3YEeOwtVRKUDvKN1SjjhX dknA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=RSxKVTB4DhCWQVBqWYnlT2IXfOQlDi1uszuu4Jsd0V4=; b=S4MiXJ7mp1qnXW3ZCQ0jLQih7mvtdjFhsJJl1Q6x5UqA9byc/X4v1NpQCA43c6gbrX Da2uXaCB4JQD9KfOzBbng+r1kisjRJ9IZ2ZhrtQj+zvn3Z4UTLaeWzpiVsWWXPR14vdI oDNjzASsVrw5pP1B/0Tc275hbZNVOjKoiaVO0XzFuJzTv+nXpaBVRc2r8H7UojM2CzAD d5hLe2FGFzN8VHeC7yuIB1FngkOnBrmp+JVbg2cqlt4mXS/cLY3ZZfRhqtcT/fzR17UR 3/vDfsSsh1f37jzsov8kDjuTCcJxVGL2EY/JYtDV66uJuu2jk0fXDUZZHdYWpSPPb6Ny m7pg== X-Gm-Message-State: AOAM533F0BmRhiCWUDzIzjI+pmaY+LPHN3Yz0yZJU2s4VLWx+pyK9nkw hYw4uyHnl1QnHsHMaDXu5tbgGgWUd33JFQ== X-Google-Smtp-Source: ABdhPJwpjioj8FYj4oQIDp7oQkiFYhEk5P3PEoeYG6zFk1GLT0YdQpbFWEvIq3l2xy7FiF8RuFwAIA== X-Received: by 2002:a0c:a163:: with SMTP id d90mr16310841qva.24.1618846934535; Mon, 19 Apr 2021 08:42:14 -0700 (PDT) Received: from hurd (dsl-205-151-56-5.b2b2c.ca. [205.151.56.5]) by smtp.gmail.com with ESMTPSA id g3sm1199999qtj.44.2021.04.19.08.42.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Apr 2021 08:42:14 -0700 (PDT) From: Maxim Cournoyer To: Maxime Devos Subject: Re: [bug#47849] [PATCH 1/1] services: Add a service for the Jami daemon. References: <20210417200414.18050-1-maxim.cournoyer@gmail.com> <20210417200617.18182-1-maxim.cournoyer@gmail.com> <1e9354c0744afc2d5d11d3eeecaba31f62e59e65.camel@telenet.be> <87czuqiiki.fsf@gmail.com> <9fc5f3f454a77ccf2a8e09fa602755166c03abf3.camel@telenet.be> Date: Mon, 19 Apr 2021 11:42:13 -0400 In-Reply-To: <9fc5f3f454a77ccf2a8e09fa602755166c03abf3.camel@telenet.be> (Maxime Devos's message of "Mon, 19 Apr 2021 16:41:20 +0200") Message-ID: <87r1j6gu22.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849 Cc: 47849@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi Maxime, Maxime Devos writes: > Maxim Cournoyer schreef op ma 19-04-2021 om 08:07 [-0400]: >> Hi Maxime! >> >> Maxime Devos writes: >> >> > Maxim Cournoyer schreef op za 17-04-2021 om 16:06 [-0400]: >> > + [...] >> > + (delete-file-recursively "/var/lib/jami/accounts")) >> > >> > You might want to verify whether /var/lib/jami/{.cache,.config,.local/share,.local} >> > aren't symbolic links. That way, if the Jami daemon is compromised (due to buffer >> > overflow --> arbitrary code execution or something), the attacker can't trick the >> > shepherd service into deleting arbitrary directories. >> >> It would only be able to delete directories that are world writable >> though, right? Seems the opportunity to cause damage is limited, but >> it's a simple check to add, so I'll do it. > > Let's step through the relevant code of the shepherd service. > > (shepherd-service > (documentation "Run the Jami daemon.") > [blabla] > (start > #~(lambda args > [other stuff] > (when [blabla, and a 'catch' form] > (delete-file-recursively "/var/lib/jami/.cache/jami") > [etcetera]) > (let* (([blabla]) > (user (passwd:uid [blabla jami user])) > (group [likewise])) > [blabla] (chown accounts-dir user group))) > ;; Start the daemon > (define daemon-pid > (fork+exec-command [blabla Jami cmdline arguments] > #:user "jami" #:group "jami" [blabla])) > [blabla])) > (stop [blabla])) > > Remember that the shepherd daemon is run as root (and therefore > has read-write-execute access to everything). The 'start' procedure > (and 'stop' procedure) are run _within_ the shepherd daemon. Thus, the > 'start' gexp is run as root. Ah yes, looking the service definition it's obvious. Sorry for missing that earlier :-). > As the start procedure didn't change the uid/gid from root to something > else, (delete-file-recursively "/var/lib/jami/.cache/jami") is run as > root. IIUC, root user can read/write anything, ignoring things like "user" > and "group". World-writability is not required. > >> What about if the daemon was >> run in a container (your suggestion in a following email, to which I >> agree would be a good thing)? It would prevent this kind of attack, >> right? > > I don't see how that would help. It is the _shepherd daemon_ (that runs > as root) that runs (delete-file-recursively ...), not the attacker (from > within the compromised jami-daemon process). Perhaps this is cleared up > by my previous response? Indeed! Thanks for taking the time to make it clear for me! I'll address this in a v2 patch series, hopefully resolving the issues with the daemon starting in double the first time the system is reconfigured (something to do with d-bus autospawning I think -- perhaps the D-Bus ping method is enough to spawn the process if it was not yet up and running). It'll take me some time to get to it; probably after the v1.3.0 is released. Thank you! Maxim From debbugs-submit-bounces@debbugs.gnu.org Thu May 20 08:32:20 2021 Received: (at 47849) by debbugs.gnu.org; 20 May 2021 12:32:20 +0000 Received: from localhost ([127.0.0.1]:33310 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ljhqa-00068h-1o for submit@debbugs.gnu.org; Thu, 20 May 2021 08:32:20 -0400 Received: from mail-qv1-f53.google.com ([209.85.219.53]:39634) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ljhqW-00061b-Jj for 47849@debbugs.gnu.org; Thu, 20 May 2021 08:32:14 -0400 Received: by mail-qv1-f53.google.com with SMTP id eb9so8478898qvb.6 for <47849@debbugs.gnu.org>; Thu, 20 May 2021 05:32:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1LEm/vNH66JNyt2nDcJbp+VJyDodQJilxokR4pSOP+Q=; b=QbKOJAGWFNOzZAxnwmDkWfBgG2QvnUbGK+7cso5iXDJ+Tu/rGswajiKMmGi8oGt/Dn qsBEq5oZlY3sAZzyNYa8l9IBM5A9l9p/eYlxzMFJBsYWjituhobjt/fy0K6olL5IBg7f w/nU10w2GMMr0dDjAIrFDs7cHlQ9vx11YuAAfO3CTXwc4/nMqBO/MViHiBACAbN+icfJ MJ8nsJabtHM2VdxmgLJuZFZ4TpQStWQpFzAfsimbhJB2pBgFjBeXEdH6yAB6VdHH1z3J 16mr8Q/HKAQLazxPXf56C8KeEhBygeABpy4xGpYvTHWShzlnC7N4aBY9Z2OnyHGNLkZL Bqkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1LEm/vNH66JNyt2nDcJbp+VJyDodQJilxokR4pSOP+Q=; b=RVQFKQJrFDluwyKLmyH1PhR7F3jfLCdTXXuimaFF8iUxWG8enYXFF+MpkVDxXHoj8G Hx7qtxMSkquV3BlopQPDKzr1pom7wame8cUizFrSCYm+flqiDzA/FXd1Q3QKdmlRaomr NY/xDgxxaq1/Nf6Qkgq8gAq3LdHvcxyQpjLwCpVa5WcqBG4aI76jUJILvUeoJrYwJbS2 nhAOJRjw8vINDmeqnAmDu+SRxP4uhldAfVjqgZmopUpuSZqco2mF770pXqoGTCpvsMMW tDS7GW4LKLRfUbNev4osfDb/8RCoFwvL6wLrrnuhx7pZSkLnSU+n7W/KjgrfV8r9YtFM UyKg== X-Gm-Message-State: AOAM533LEyyhWF+2S/1cRfYyQzsenmmGy4ejYrw/ZrLZ/05SrwwvGOxU 141ITLRPO1pE6Hi0xYLZCz1KGsDZyV8= X-Google-Smtp-Source: ABdhPJyb5nH28PAA04Xks+25dKLciD1hOb5Nq1SUGnVENaWCqKFKLC9Hb9nEjszSgzimiLWielFuJQ== X-Received: by 2002:ad4:5f87:: with SMTP id jp7mr5252204qvb.46.1621513921781; Thu, 20 May 2021 05:32:01 -0700 (PDT) Received: from localhost.localdomain (dsl-150-81.b2b2c.ca. [66.158.150.81]) by smtp.gmail.com with ESMTPSA id f15sm1757041qtg.25.2021.05.20.05.32.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 May 2021 05:32:01 -0700 (PDT) From: Maxim Cournoyer To: 47849@debbugs.gnu.org Subject: [PATCH v2] services: Add a service for the Jami daemon. Date: Thu, 20 May 2021 08:31:10 -0400 Message-Id: <20210520123110.6331-1-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <8f42495246e684121605e7cef2462a068130d5cc.camel@telenet.be> References: <8f42495246e684121605e7cef2462a068130d5cc.camel@telenet.be> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849 Cc: Maxime Devos , Maxim Cournoyer X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) * gnu/services/telephony.scm (string-list?): New procedure. (maybe-string-list?): Likewise. (jami-daemon-configuration): New configuration. (%jami-daemon-accounts): New variable. (jami-daemon-configuration->command-line-arguments): New procedure. (jami-dbus-session-activation): Likewise. (define-with-retries, define-send-dbus) (jami-daemon-service-type): New variables. (jami-daemon-shepherd-services): New procedure. * gnu/tests/data/jami-dummy-account.dat: New file. * gnu/tests/telephony.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Register the new test file. (dist_patch_DATA): Register the new data file. * doc/guix.texi (Telephony Services): Document it. --- doc/guix.texi | 77 +++++ gnu/local.mk | 4 +- gnu/services/telephony.scm | 355 ++++++++++++++++++++++- gnu/tests/data/jami-dummy-account.dat | 391 ++++++++++++++++++++++++++ gnu/tests/telephony.scm | 204 ++++++++++++++ 5 files changed, 1028 insertions(+), 3 deletions(-) create mode 100644 gnu/tests/data/jami-dummy-account.dat create mode 100644 gnu/tests/telephony.scm diff --git a/doc/guix.texi b/doc/guix.texi index e8b0485f78..a58fe0a44e 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -22435,6 +22435,83 @@ and Error. @node Telephony Services @subsection Telephony Services +@cindex telephony, services +The @code{(gnu services telephony)} module contains Guix service +definitions for telephony services. Currently it provides the following +services: + +@subsubheading Jami (daemon) + +@cindex jami-daemon, service + +This section describes how to configure a Jami server that can be used +to host video (or audio) conferences. Here's an example that +demonstrates how to specify account archives (Jami backups) to be +provisioned automatically: + +@lisp +(service jami-daemon-service-type + (jami-daemon-configuration + (account-archives + '("/etc/jami/unencrypted-account-1.gz" + "/etc/jami/unencrypted-account-2.gz")))) +@end lisp + +Jami accounts and their corresponding backup archives can be generated +using either the @code{jami-qt} or @code{jami-gnome} Jami clients. The +accounts should not be password-protected, but it is wise to ensure +their files are only readable by @samp{root}. The complete set of +available configuration options are detailed below. + +Available @code{jami-daemon-configuration} fields are: + +@deftypevr {@code{jami-daemon-configuration} parameter} package jami-daemon +The Jami daemon package to use. + +@end deftypevr + +@deftypevr {@code{jami-daemon-configuration} parameter} package dbus +The D-Bus package to use to start the required D-Bus session. + +@end deftypevr + +@deftypevr {@code{jami-daemon-configuration} parameter} boolean enable-logging? +Whether to enable logging to syslog. + +Defaults to @samp{#t}. + +@end deftypevr + +@deftypevr {@code{jami-daemon-configuration} parameter} boolean debug? +Whether to enable debug level messages. + +Defaults to @samp{#f}. + +@end deftypevr + +@deftypevr {@code{jami-daemon-configuration} parameter} boolean auto-answer? +Whether to force automatic answer to incoming calls. + +Defaults to @samp{#f}. + +@end deftypevr + +@deftypevr {@code{jami-daemon-configuration} parameter} maybe-string-list account-archives +A list of Jami account archive (backup) file names to be +(re-)provisioned every time the Jami daemon service starts. These Jami +account backups should @emph{not} be encrypted and should be made +readable only to the @samp{root} user (i.e., not in the store), to guard +against leaking the secret key material of the Jami accounts they +contain. When providing this field, the account directories under +@file{/var/lib/jami/} are recreated every time the service starts, +ensuring a consistent state. + +Defaults to @samp{disabled}. + +@end deftypevr + +@subsubheading Murmur (VoIP server) + @cindex Murmur (VoIP server) @cindex VoIP server This section describes how to set up and run a Murmur server. Murmur is diff --git a/gnu/local.mk b/gnu/local.mk index dd68bb5957..18700f78a1 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -712,6 +712,7 @@ GNU_SYSTEM_MODULES = \ %D%/tests/security-token.scm \ %D%/tests/singularity.scm \ %D%/tests/ssh.scm \ + %D%/tests/telephony.scm \ %D%/tests/version-control.scm \ %D%/tests/virtualization.scm \ %D%/tests/web.scm @@ -1842,7 +1843,8 @@ dist_patch_DATA = \ %D%/packages/patches/ytnef-CVE-2021-3403.patch \ %D%/packages/patches/ytnef-CVE-2021-3404.patch \ %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch \ - %D%/packages/patches/zziplib-CVE-2018-16548.patch + %D%/packages/patches/zziplib-CVE-2018-16548.patch \ + %D%/tests/data/jami-dummy-account.dat MISC_DISTRO_FILES = \ %D%/packages/ld-wrapper.in diff --git a/gnu/services/telephony.scm b/gnu/services/telephony.scm index e1259cc2df..d0dc79a68a 100644 --- a/gnu/services/telephony.scm +++ b/gnu/services/telephony.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 nee +;;; Copyright © 2021 Maxim Cournoyer ;;; ;;; This file is part of GNU Guix. ;;; @@ -17,16 +18,31 @@ ;;; along with GNU Guix. If not, see . (define-module (gnu services telephony) - #:use-module (gnu services) + #:use-module ((gnu services) #:hide (delete)) + #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (gnu packages admin) + #:use-module (gnu packages glib) + #:use-module (gnu packages jami) #:use-module (gnu packages telephony) #:use-module (guix records) + #:use-module (guix modules) + #:use-module (guix packages) #:use-module (guix gexp) #:use-module (srfi srfi-1) #:use-module (ice-9 match) - #:export (murmur-configuration + #:export (jami-daemon-configuration + jami-daemon-configuration-jami-daemon + jami-daemon-configuration-dbus + jami-daemon-configuration-enable-logging? + jami-daemon-configuration-debug? + jami-daemon-configuration-auto-answer? + jami-daemon-configuration-account-archives + + jami-daemon-service-type + + murmur-configuration make-murmur-configuration murmur-configuration? murmur-configuration-package @@ -74,6 +90,337 @@ murmur-service-type)) + + +;;; +;;; Jami daemon. +;;; + +;;; Copied from (gnu services messaging). +(define (string-list? val) + (and (list? val) + (and-map (lambda (x) + (or (computed-file? x) ;XXX: for tests + (and (string? x) (not (string-index x #\,))))) + val))) + +(define-maybe/no-serialization string-list) + +(define-configuration/no-serialization jami-daemon-configuration + (jami-daemon + (package libring) + "The Jami daemon package to use.") + (dbus + (package dbus) + "The D-Bus package to use to start the required D-Bus session.") + (enable-logging? + (boolean #t) + "Whether to enable logging to syslog.") + (debug? + (boolean #f) + "Whether to enable debug level messages.") + (auto-answer? + (boolean #f) + "Whether to force automatic answer to incoming calls.") + (account-archives + (maybe-string-list 'disabled) + "A list of Jami account archive (backup) file names to be (re-)provisioned +every time the Jami daemon service starts. These Jami account backups should +@emph{not} be encrypted and should be made readable only to the @samp{jami} +user (i.e., not in the store), to guard against leaking the secret key +material of the Jami accounts they contain. When providing this field, the +account directories under @file{/var/lib/jami/} are recreated every time the +service starts, ensuring a consistent state.")) + +(define %jami-daemon-accounts + (list (user-group (name "jami") (system? #t)) + (user-account + (name "jami") + (group "jami") + (system? #t) + (comment "Jami daemon user") + (home-directory "/var/lib/jami")))) + +(define (jami-daemon-configuration->command-line-arguments config) + "Derive the command line arguments to used to launch the Jami daemon from +CONFIG, a object." + (match-record config + (jami-daemon dbus enable-logging? debug? auto-answer?) + `(,(file-append jami-daemon "/lib/ring/dring") + "--persistent" ;stay alive after client quits + ,@(if enable-logging? + '() ;logs go to syslog by default + (list "--console")) ;else stdout/stderr + ,@(if debug? + (list "--debug") + '()) + ,@(if auto-answer? + (list "--auto-answer") + '())))) + +(define (jami-dbus-session-activation config) + "Create a directory to hold the Jami D-Bus session socket." + (with-imported-modules (source-module-closure '((gnu build activation))) + #~(begin + (use-modules (gnu build activation)) + (let ((user (getpwnam "jami"))) + (mkdir-p/perms "/var/run/jami" user #o700))))) + +;; Local definitions to expand in source form in G-exps. +(define define-with-retries + '(define-syntax-rule (with-retries n delay body ...) + "Retry the code in BODY up to N times until it returns #t, +else #f. A delay of DELAY seconds is inserted before each retry." + (let loop ((attempts 0)) + (if (< attempts n) + (or (catch #t + (lambda () + body ...) + (lambda args + #f)) + (begin + (sleep delay) ;else wait and retry + (loop (+ 1 attempts)))) + (error "maximum number of retry attempts reached"))))) + +(define define-send-dbus + '(define (send-dbus dbus-send service path interface method . arguments) + "Return the response of dbus-send, else #f." + (let* ((command `(,dbus-send + "--bus=unix:path=/var/run/jami/bus" + "--print-reply" + ,(string-append "--dest=" service) ;e.g., cx.ring.Ring + ,path ;e.g., /cx/ring/Ring/ConfigurationManager + ,(string-append interface "." method) + ,@arguments)) + (temporary-log-file "/var/run/jami/.temporary-dbus-output.log") + (clear-temp-file (lambda () (false-if-exception + (delete-file temporary-log-file))))) + (catch #t + (lambda () + (dynamic-wind + clear-temp-file + (lambda () + (let ((pid (fork+exec-command command + #:user "jami" #:group "jami" + #:log-file temporary-log-file))) + (match (waitpid pid) + ((_ . status) + (let ((exit-status (status:exit-val status))) + (unless (= 0 exit-status) + (error "the send-dbus command exited with" + exit-status)) + #t)))) + (call-with-input-file temporary-log-file get-string-all)) + clear-temp-file)) + (lambda args + (format (current-error-port) "command ~s failed with ~a~%" + command args) + #f))))) + +(define (jami-daemon-shepherd-services config) + "Return a running the Jami daemon." + (let* ((jami-daemon (jami-daemon-configuration-jami-daemon config)) + (dbus (jami-daemon-configuration-dbus config)) + (dbus-daemon (file-append dbus "/bin/dbus-daemon")) + (dbus-send (file-append dbus "/bin/dbus-send")) + (accounts (jami-daemon-configuration-account-archives config)) + (declarative-mode? (not (eq? 'disabled accounts)))) + + (with-imported-modules (source-module-closure + '((gnu build shepherd) + (gnu system file-systems))) + (list (shepherd-service + (documentation "Run a D-Bus session for the Jami daemon.") + (provision '(jami-daemon-dbus-session)) + (modules `((gnu build shepherd) + (gnu system file-systems) + ,@%default-modules)) + ;; The requirement on dbus-system is to ensure other required + ;; activation for D-Bus, such as a /etc/machine-id file. + (requirement '(dbus-system syslogd)) + (start + #~(lambda args + #$define-with-retries + + (define pid + ((make-forkexec-constructor/container + (list #$dbus-daemon "--session" + "--address=unix:path=/var/run/jami/bus" + "--nofork" "--syslog-only" "--nopidfile") + #:mappings (list (file-system-mapping + (source "/dev/log") ;for syslog + (target source)) + (file-system-mapping + (source "/var/run/jami") + (target source) + (writable? #t))) + #:user "jami" + #:group "jami" + #:environment-variables + ;; This is so that the cx.ring.Ring service D-Bus + ;; definition is found by dbus-send. + (list (string-append "XDG_DATA_DIRS=" + #$jami-daemon "/share"))))) + + ;; XXX: This manual synchronization probably wouldn't be + ;; needed if we were using a PID file, but providing it via a + ;; customized config file with would not override + ;; the one inherited from the base config of D-Bus. + (let ((sock (socket PF_UNIX SOCK_STREAM 0))) + (with-retries 20 1 (catch 'system-error + (lambda () + (connect sock AF_UNIX + "/var/run/jami/bus") + (close-port sock) + #t) + (lambda args + #f)))) + + pid)) + (stop #~(make-kill-destructor))) + + (shepherd-service + (documentation "Run the Jami daemon.") + (provision '(jami-daemon dring)) + (requirement '(jami-daemon-dbus-session)) + (modules `((ice-9 ftw) + (ice-9 match) + (rnrs io ports) + (srfi srfi-1) + (srfi srfi-26) + (gnu build shepherd) + (gnu system file-systems) + ,@%default-modules)) + (start + #~(lambda args + #$define-with-retries + #$define-send-dbus + + (define (delete-file-recursively/safe file) + ;; Ensure we're not deleting things outside of + ;; /var/lib/jami. This prevents a possible attack in case + ;; the daemon is compromised and an attacker gains write + ;; access to /var/lib/jami. + (let ((parent-directory (dirname file))) + (if (eq? 'symlink (stat:type (stat parent-directory))) + (error "abnormality detected; unexpected symlink found at" + parent-directory) + (delete-file-recursively file)))) + + (when #$declarative-mode? + ;; Clear the Jami configuration and accounts, to enforce the + ;; declared state. + (catch #t + (lambda () + (for-each (cut delete-file-recursively/safe <>) + '("/var/lib/jami/.cache/jami" + "/var/lib/jami/.config/jami" + "/var/lib/jami/.local/share/jami" + "/var/lib/jami/accounts"))) + (lambda args + #t)) + ;; Copy the Jami accounts from somewhere readable by root to + ;; a place only the jami user can read. + (let* ((accounts-dir "/var/lib/jami/accounts/") + (pwd (getpwnam "jami")) + (user (passwd:uid pwd)) + (group (passwd:gid pwd))) + (mkdir-p accounts-dir) + (chown accounts-dir user group) + (for-each (lambda (f) + (let ((dest (string-append accounts-dir + (basename f)))) + (copy-file f dest) + (chown dest user group))) + '#$accounts))) + + ;; Start the daemon. + (define daemon-pid + ((make-forkexec-constructor/container + '#$(jami-daemon-configuration->command-line-arguments config) + #:mappings (list (file-system-mapping + (source "/dev/log") ;for syslog + (target source)) + (file-system-mapping + (source "/var/lib/jami") + (target source) + (writable? #t)) + (file-system-mapping + (source "/var/run/jami") + (target source) + (writable? #t))) + #:user "jami" + #:group "jami" + #:environment-variables + (list (string-append "DBUS_SESSION_BUS_ADDRESS=" + "unix:path=/var/run/jami/bus"))))) + + ;; Wait until the service name has been acquired by D-Bus + ;; (this does *not* trigger automatic D-Bus service + ;; activation, which is what we want). + (with-retries 20 1 + (let ((output (send-dbus #$dbus-send "org.freedesktop.DBus" + "/org/freedesktop/DBus" + "org.freedesktop.DBus" + "ListNames"))) + (string-contains output "cx.ring.Ring"))) + + ;; Provision the accounts, by means of D-Bus commands sent to + ;; the daemon. + (when #$declarative-mode? + (or (every + identity + (map (lambda (archive) + (send-dbus + #$dbus-send + "cx.ring.Ring" + "/cx/ring/Ring/ConfigurationManager" + "cx.ring.Ring.ConfigurationManager" + "addAccount" + (string-append + "dict:string:string:Account.archivePath," + archive + ",Account.type,RING"))) + (map (cut string-append + "/var/lib/jami/accounts/" <>) + (scandir "/var/lib/jami/accounts/" + (lambda (f) + (not (member f '("." "..")))))))) + (error "failed provisioning the jami accounts"))) + + ;; Finally, return the PID of the dring process. + daemon-pid)) + (stop + #~(lambda (pid . args) + (kill pid SIGTERM) + ;; Wait for the process to exit; this prevents overlapping + ;; processes when issuing 'herd restart'. + (waitpid pid) + #f))))))) + +(define jami-daemon-service-type + (service-type + (name 'jami-daemon) + (default-value (jami-daemon-configuration)) + (extensions + (list (service-extension shepherd-root-service-type + jami-daemon-shepherd-services) + (service-extension account-service-type + (const %jami-daemon-accounts)) + (service-extension activation-service-type + jami-dbus-session-activation))) + (description "Run the Jami daemon (@command{dring}). This service is +geared toward the use case of hosting Jami rendezvous points over a headless +server. If you use Jami on your local machine, you may prefer to setup a user +Shepherd service for it instead; this way, the daemon will be shared via your +normal user D-Bus session bus."))) + + +;;; +;;; Murmur. +;;; + ;; https://github.com/mumble-voip/mumble/blob/master/scripts/murmur.ini (define-record-type* murmur-configuration @@ -305,3 +652,7 @@ suite.") (service-extension account-service-type murmur-accounts))) (default-value (murmur-configuration)))) + +;; Local Variables: +;; eval: (put 'with-retries 'scheme-indent-function 2) +;; End: diff --git a/gnu/tests/data/jami-dummy-account.dat b/gnu/tests/data/jami-dummy-account.dat new file mode 100644 index 0000000000..026890052d --- /dev/null +++ b/gnu/tests/data/jami-dummy-account.dat @@ -0,0 +1,391 @@ +;;; JSON extracted from an actual Jami account and processed with +;;; Emacs/guile-json. +(define %jami-account-content-sexp + '(("RINGCAKEY" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQURBTkJna3F\ +oa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRQzBxWUozSkYvTzhQRGEKRnUwRnpRcHBCaD\ +gybGJMdURrNTlVU0I0MUJSaS9kdDZGV1BRN29YOVpsY25vNGZzM2dmUHQ0dU1hRVBkVFBGKwowbGN2Q\ +jc2cytQTEFlcjlOZGpVQzQ2ZXp0UnNiNE9aQXc4ZUk1M3EwSU04QWJFd0o0ZjllLzBmQUFueHgrK3Qw\ +CmZDeGV1YTBUaVBqVHBpZVJMNmpwQkd5UGI2Qk5pU2ViTkZCNzJOMTBnbzI4REVQYlhkNE9CNkN1blZ\ +5RGZKSU0KOC9PRy8rMndNamI4WkRwT3JrYy93U2ZHbnQyZXA3U0xKSkgwOFIzV1FKWklsSndrcGdLTH\ +FRakVwWFNpclN4dAozSkdtdXdBdE9LaXFFTXh1R043elV3ZlNINEtHdkRaUFNkZklZVXJ3eEp4aDJZZ\ +3lobG5RRC9SSnhRN3d4YlJBCjFhMUZVV0FzbDhLODk5cEtESk1GL09VOWZMRUx6QlViblpaRDRmSlg1\ +NmcyTlluUnJobS94NG9FbFk0MFNYMUUKcHYzb01hNnZrVGN5RjJnUFhKL2FkUVJoS0dFaGRjaHBpeDl\ +5UVphaDFCUFBGYW5jNzBMcjhOaDZJeHFNQ1hiMQozMG9vWHpWZmZNMVFOd28rL3hzRnBlRkRqUTAxQ0\ +9pdWZocitKREcyc0txb0o0V0JwYVhubWI1YXVrVWUvV1RKCjAxVmRyaEkvSVExd3V4QzNMMnpac3dVU\ +1NTaDk0aXg1M0hpU3pWbkI5UkxmaVhZUUVCcFEyNHVoRTdiYlo0bm0KZTczZC9zenpPTXMzYUt3OWtW\ +a2VLMTVtYWhSVWZjdEdhSVQxTkhGWUNYYXByaWExakdNdVpmSk1pSUtZUzNidQpMbUhZckF6dEptNDZ\ +0aHpjdnN3NHlhMnFoa2xUUlFJREFRQUJBb0lDQVFDaHZaUm85KzZ5aFhFTHZ6U3FXZHcxCkZGOERibG\ +hIMmhVWkNuV0kxMDM5SmdyRkxMczFSU1krSzg1aFZYMk9hV1VTNk44TmNCYzUyL1hrdFltS09HUFQKM\ +WZqMnE2M3pPcDNSSFdGNWVPMXhNeExRN3JZSDhqMGZZTFFTUytKemdwb3ZRVnJLSXkrb21JSSt3aUN6\ +R1laRApGQUM0ODJzL0J5MHdtRjVjdC9JTEdIeVY3ZXNVUlo1Vi9iL0ltQzUwQ1lDUWpQR2xBb3JkeUx\ +1MHp2NjZZUXc2CkQycTg0VHAyVUg3SExEVmhFNytUbDg4Q04xWll0VGtpSkthbkNpMFVmbStPKzJFM0\ +5HM01hajk1aDl2NktqYkoKUlkxeTNDRTVmQmkyUFNLbVVzRjN3SzdhbzJDRks5MTgybmlxL2FaNm5WO\ +Xc3NmVrRjhEOWUvS1pqUE5ZT0xkaApFczBSL2laV3RpbUx2RHdXQWNWNFNnSFFjNXJvNU9yOEFUS1ZK\ +VmlzZGFuWXkvdUhmVXZWN3U5cDVLK2E4SHU2CllabW13ZTh4bnF5M3V2M0VabE9LY20zTnZvWllVMnJ\ +HUUFQQW1sWWQ4WlRsZGxPa1JCSGxxYzllMmJuSnNTQW8KNUhhS0N3aDJsWmZpalVGNXFrMXNQcm1kN3\ +BlMld2VVV3QmVuSjJnS1ZoTE5VVGtHWmtTWGhzNlV3WWRRMjVtRQppQzl6WjhXNkQ2OXBvb0lsTTVXT\ +01ySEs0Rng1ck9vT05kUHQ4NEk1bTI3cnpnbXM4QnJXVUlGLytZZjJ0bGdmClBIR0V4c3ZCK3JRQk52\ +WHU3dXoxcVdFTlJTL2YwR2E3dVF4ZW5sZ2dubHc5M1pNOW1GWXpXb1RpdWFmdnphTnAKWEsrTEVrV2F\ +RYUs1Q0VaNEhmUlhBUUtDQVFFQTUyK240OUxQODlyQkR2bFdsTkxNanJqTDdSb0xyQ3FVZGpQWQpyT1\ +hZS3ZkTkxyS2NTc1hNdkY4YW5HQng1UG5oVDZGY05ic2dzQ3BUUXowMThZYmcrbUUxQno5ZTdFNTJGZ\ +i9NCk9BbWZqSllXUnZueUtiNnB3SGlvOHlXUXlVVk1zZU1CcmpvWk1kNkpPZEZ0K2JITHBWOS9iSkdR\ +a3NTRE04WTkKbWxGQUlUL0gyNTh1K1ZKTWsrT0prU28zZmJQSk5Ja1Q2WVBKVmNaSnZTRGI5QU83WDF\ +lendCOXVRL0FEblZ6YwpSQkJOUVZaTStZS2ZNWFJBdmFuWnlmWFFwaUxCQW8rRVRPSHJCR1dDRUhtSF\ +RCaEZIMTkyamtxNlcrTStvS0R1Cm1xMitMc2hZWTVFc2NpL2hPOVZjK2FCM0hhaGliME03M092MHFNc\ +WZoTncyU1BncHdRS0NBUUVBeDlaR1gxQnQKL3MwdGtNcGV1QWhlWjFqTklnZmFEY0RRTWlmU0k4QjRx\ +WUhiL1hOREQ5NjFQME9zMDdCN2wzNE1iZ3U2QlNwcwpXdSt0Y1hjSFlqQVJUc0Qzd0pSaVRIb0RSQzR\ +YYkxEa2pHRUVCVzRKbFVqZTA1QWZrU0QrdkZSMkJwZStxQlBLCm5yb3Mwd1BWL3RXa3MzY2VFOUlBTV\ +pWWDhQeFA3RVNXbitVZDJEWkZhcVFLb0JybHZXRXhxelpYUEJSVjhoS3QKcFBqWnFkZXFQLzhUZTBtS\ +zh5MEVreXVXOWhFdGZ2Sm5HWXhMNStrSG9xd2hQVk1tODZ5YlZNVHRQYWJTdCtPUwp0WHhJTE9RMWRN\ +QkFabzRxSnNkUUZJcTJnSHA5WFYwa2ZNUms1ajdJT1Q4c2Z6TlpKVkRNK1k5VHVlSGJXSnduCnZsWld\ +VZ2NVZTlBaWhRS0NBUUVBbFJaK2h1ckUvNGdLR2dWUld5bTRrTEJHM2dTTFJHdGhuQXVtSnlzaFoveE\ +wKZ2l1Wk55bll5L2hRQWpDMjdoUnlxb04rRFRid3hjdGVPOUJ3c1poNzBZOVJROHYwOERGVExMVE43O\ +E56UG5OcApBbXY5TGhzZTYxaFBMZU1qTkNVcVZPV3hyWFRMeWk1YkpCM2Z4SnhlWGJmNU5BMUpudUpz\ +eXF1SC82TWJ0cytKCmhkY3p3WFRjMCtBZVBKOS9nOENQZXdKYkMzRFVBQ2R1VlNHWHo4ZWZxcm1xbDd\ +jbnB5ZzBpK2pJRkNpVU8rVEcKVFcxeDg3KzUvUFF2MGtSQ0Z1UUloZ2ZCNkcwWW9vcHBrUWRZdXhKZl\ +pPaHdUUldpbTVMMlF5K294WWZySGVQOQozSlltbGFCMmJiN3kxL1FoQjcvek9VMk1nTEtYdHl4Z09ve\ +EpoQlFwZ1FLQ0FRQkIwSUE4dy9CMkNuMEhRcDhQClhUSTZOelRZRUYzd1NhQkg1SFdBOE5MTWdNaERJ\ +TUxsWnlPcVFrK1pLSGFMM2llWjFxTGRNS3VmQjNESC9idWcKeXRQb2JBVXNsN0lJSGVjVmZWaVpvMml\ +pRXhHUCtEMlB2UUFtRFVGWU90V3FrT2FPSlV2VmJ5ODhOM1NyeW9lZgo5aHpZUGxMWmxFQWNGR055S3\ +FibjJXOENHaU5LSWhXYW1Zd21UclY3T1pkeUcrTi9GZk40Vms1NkZyc1pCTDQ5CmRYU2xGZ045TTBaZ\ +WNleTEvZEpPRE9lSHNuME5VK0gvNFZEUk1hR1NmelpwSkxJOXE4T2FiSWpVM0ttb24wQTcKdzFWeWNU\ +L1FwYlBxRUFVckt5dytvMzV3MlAyaUZ1czZiMlBvUUxFTGFTRVl6K3R6UEw5UTM1ejNRdGdMQytuagp\ +IUmxCQW9JQkFES0Q4NGhrYkphczlIQ00zanNNSU9kb213ZEMvcktxVUxKNHFWZU5QR0xDY2VpNEdocn\ +dlQnNICnNoN0hibFlZSDN2U2Y3RW1iZEVCb2xlWVJsaUx5ZzJDQU1ZOGpNK0lpUEwydk1yM2Y3SzZPT\ +mU0UkVPUFJSZkcKWlJDcTh4a0ZPQlg1SUJUbkVCV3QzdVdyb1NGY2x4RTdUa2I4VkUyVzExTG9ZNlkw\ +TUNPaHdxN21xYXRUVnNrawpTRDNySmkrTFR6a2Y4OEx1bjZZNjdiaFNOTWpKZkFaUXNQc0FTRkJBUTJ\ +rQnE5alRLZGVuaU4yYTJIbm0xNCtrCnJDeU9ZVE14Q2hQbWNpS25pVy9MWnFUL0U1dlNRUGdBVzc0dT\ +VLazJoSjRBajNjRW9NVEwxSytZbStWYWh2U0cKTi8xOFdYQ1JRQkg1d0p2eXJYczBtT29GQlRnTWg4d\ +z0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=") + ("ringAccountKey" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTk\ +Jna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRRDNCdDRnOUVUdk9EVnYKM3hWV0ZlS\ +1Nnbk5uVEF3S2dYa3IrQ1FhdU8vTGZWM01RenNSNHliL3hoaWhhb1Z2c2FtZ3ZRU1haL0M1R3I5QQpE\ +YlAxbHNHclRCK1pXMC9uMXVEb3hmVWdZRWY3SGtVanJtdVFjUGlFWGlUVkNiY002U0NzdVNrMnRxdE1\ +BNjBNClRacVo2LzAvbkEvblR5TnFNaUJNSmFRN0NUb2xOTTh2Z2tvd0tBRW14OGpJUG9YZEttMnd6MD\ +Z6SnhwU1d4WjUKc0FBTkdSSHU0b2ZXNWJiMERvamtnRzFBYUJ6Nm9uSmdKK1JFSWV1UkpNQWFHYmtzW\ +TQ4Z1Z1b21BVTU0UFNvUApFb3psVGdHd1k0cnhJTGE0V1Y0RVZMVExrR240ZTYrRUYrSjIvRURBUFdN\ +bXREdFpUeURCc2t5bStLaDRUT2xPCjdnN3JlUUhLdDd1R21YU0RnbzVKZ2hOOHNVRFUxL1Z2YmFFcUZ\ +tTDJrZWNGOVlVZmNsUWRGY1ZncmIrMkh5R3AKRVc0b3RkZjlYYzhOMWxrbGk1dFBqRGZuQ1U3OHB6QT\ +BxQmV1SWhZTnF1VjhGSm1NemhXeVFDbE1MUEFYbXFVdwpWYlY0MWduM0NkektuUlVhZXFONXlzOG5KQ\ +mRJNDBleWlYRUlvU0VKcFpyT1Z5ck1icnNCQzltaVFpZUFhSnlBClFvcjFaRGlwMkpZNUFza2phUGQ0\ +NGk0MGNkeFpob1RhNnpzako5UjZScllFYjhWTmZQemFLaElwSXJSd2NpbCsKWjFrbUUwSE1kY21ITXR\ +hbWZhK0l6WUR4dDV6OGVOZys1RGpVVG1MRkdyQUVWRW5hNDcxdllxYnk5UCs1T1cvNQpSdkxtUER2Tj\ +dlUURpTlZENlBYRFk5OTY4bTZaaHdJREFRQUJBb0lDQURjOEkrTCtlNE41OEFqcHV0MmEyeVNqCllxY\ +VFUSWowMW1GTWhOWXMwQUdTTUswQncyMkdleXZwNFl3R1EzdnNIOSsvSkEydXdoYkJzazNpUW9FQmlx\ +Q0EKenZmOWdPcDRFNlk0elV6RitwSmQvRnUwSG4wWHBab0Rhdnp2eFN4djNFeUN3b0puYWZuL1FHeGw\ +xZEhoQUtsKwpmZGZjekRCc3NPZ1Y2cGtBd1MyY2wwOHFOT2g3cVhaQWFkYk1sQ1lWM0owU1hhaVZiNz\ +lHZXNvTzNwUVBMUUZiClNjQjFjT2sxYnNxWkpOU244d0xmMis5QVBEdzMwWEtNNHg5eTdRTE42Q3oxQ\ +WpvcFJLQ0NIS3R1SEc4UmVETTIKcnRTbjJmTnltQ0VqeDZGVTB6MHFldDV3Y01UbU5weEZuYXdEMU5s\ +dFpnZXBsSllwTjVKZXNEUmo2cFlnWXBPKwo5UDU2cEdtZVNTVzVxcHRoWFFLQmFsdy8wWXp2YUlYdHp\ +hTnZyNUJzRFNrWkU3cldzODIvQmFzUE1RckFmOGpLClZFMU9pSzcrVllUVTRFVWVoZ0FZOXdzNjFqYk\ +lSSEpQbW9VQXpkWHcyL0d0Vk9JUTFwUFJnOXNYN0JaMmUyV1YKdmd5aThPUEJxRWtwblBiMkU5Z0d1U\ +25rY01OeWFVbUl0c3pFandadW14dnZrUW5HanlTb3pjY2R3dnNQNnBJagpoN0g5VUNQTHdOM0N5N1lp\ +UmliSlZBWlNjZkF6QzhubXNLODQrTzJUZHBzTXk0SEZDMmM4dlZiclpteTVkWC9qCk1ESnBzS25JWlZ\ +JMmpXSzRpRS82aUdIWVdoY3JvWnYvVEJ0YW1SQUxTWDVOYkhhWTI0bXVRSG5yMldtaytld3EKbHRGbC\ +90bXgyVkpWUitMZ0JCUGhBb0lCQVFENEI0MjQyVTgvbkJ4d2RzelhCdWxBOVFTa0I5Zktud0RlRkV3S\ +wp3Nks0eU14YVdRU04ycjRxRDhLcW93OVZVMzRYdkRWbFh0RUlDaVh3Q0hZdW5IL3g3cXNSdEVzbHJM\ +aWg4UHRPClpDSU8zUml4RmlIQXFlQUh2YXF0NVhXdndaREx6WnV2THRJOTdINkZ1QjYxck5qMnhxdlR\ +IN05pUmp2S0R0WXgKR1VtNURoQ094cm9tR0NkWHRnWHJGaS9WRU1TSmpQMkM3OTNrN1pTNmNZL0Nkc1\ +RqWEsrZ1UzeWM3OC9kN1pYbwpKMGg2WFlSdmhlQW9Bd2dkVTl4MWtYL2ZmY2tZK1hUcFRwV2xXWmtlU\ +ytsejBpQkRnUlJzMm45OFZDeTZDRmRZCldsZXZaZy9SWXZ6dzlKdWFVcXArOHpHbHNXR2xuOEhtZW5X\ +Q1luSHJnNFBxQnRkL0FvSUJBUUQrOXhDL1N5ZGIKVWZxMUJHYy95YktZc3RLb3A1azB0d3M0SlUwTzN\ +aT1U3MlZ5YTdLT2lTemdPSzVnL2QzckhMMXR2dHViTDBWNAo1dEF4a1AzSkVYbmxZZU5IVkpROTc2RH\ +NGS3Ztc0FGL2JJdVBsdFBRT1dyM3g1eW1RU3lCOTBUczV0dFdWMTVQCktYYVNnMTZidDhwNS9MeERkZ\ +ng2c1YzN1o5RDFRd21EQllreVFIcWQ4clljTm9ad1M5ZnI3UTZhN1ZNSDVtT3IKbEF5dzBCYVdZQk9k\ +bjFGd0pVV3NlRlpmTy9vNUVqZk9Hd0xMR1hiOEVmQ1hqdlRYcUNHLzNrT1JvN1NkOWY1eQowVjIxMmt\ +YVVNINHNDbFB0SmwzeHpaMWJxQ2RMVDNITWNLUTk5UGFFVFppQnNXQ1lOcXg1c0Q0RGhoMzdZQ2hKCm\ +hlN3VUM1E0MElINUFvSUJBREN1VXR1b0UweloyQjhld2grbUpKdnlPMEh5cENFSnlrTE1Xd3gxejNkV\ +E9nQzEKbmhZMWk4TjNxbTZSYUk0SHdDVHFkTlI3b3ExZ1NJZnZNVHIrem9IdXBUYnBXeUorM3hJeDJU\ +Rk9wL3lnMnByUApURHFqWE94SUJycnc0WU5vaTRIa3poeTVKTnl3a1RpdnBaOWsySVMvQTdTQmNWVGx\ +raENianVDK0pPRWthSTJOClpiWGFZY1p1WElVQ3FzcTM2c3RRbCtWZUxRQWt2VjlHc0wrclRnT09Dbz\ +UrTkdRZEVZQnVoRkMzZlJzL1JhSVoKOWFBRTBFL3BTTWp1a05tTnQ2Mm1NSk1tTUdydXhnWFRRblBRR\ +npNSW43aXB2Z0hxQjRsUDM4emdsbnMvbmZVcgo1NWRuZXk3ejhMRFFETHVIc0RHd3hINzNKQjgrTVR2\ +WGFVbkNwQU1DZ2dFQVNBSGxBL0dvdXR6TFRvWmcxcDRUClI1YnhjZHBycFh5d3VYbW5hclJmY3VldG9\ +nUVNtTGpiS0xRNVk0RXZSTENJTzA5MDNENGNnOG5FTU10L01XTXoKSnZwZll3emJGU2J4THR1anRQSX\ +VhaHR3eXV2UkJIVEM1aG5FL3h0WEE1bWZLTDBHWXpzbmtubm1WL2lzSnBSZwpwZFVnSW5sWEJodkRyR\ +FlreUsvWEp0N1FZWlhlUzI5NXlUd0krZndoamlzVVBlTWEyUmRUUE9rQ01JbUVaNUhZCjJHSmZjS25H\ +SkxDVHpDKzNPcGtQazdFRE4vTUlMS2F3YVUxaGp1cVlKWVVUVmpXQzFEM2VUL1ViWHptM0VQNHMKVEN\ +uYWpCYVMzN0N2YVd4ek5JektXZS9TSXdGbEFmYWNSTHlneUR4Z3Q3bHp1akVObEtvU2xya3h3ckpEND\ +Z2WAptUUtDQVFBcTVQWWxSQjgvNnFiWWt1OTA0NUZRdXk2QWtlYXBaMW0raS9SQzZtbFRvUXB6NDlPU\ +Gs4ZGx5YjVtCndvSVhpaEo2V05jN1RsWlRYMnpQTTRBS0M5VFNBUWJrWDg5bjEyU2VDSUlHbXVINnk0\ +TjZiY2lxZjVVcSsvc0IKcHJKeFRNYlRSUFpqS0VVd1N0SFg1MUQ1bi9sQnZERGY3Y2VEZytsYlE0RjR\ +KMTlPd09oZ1lGcjFheGQvNXd2VgpURjNoVlQwbFZGN2RyRC9iMHZOcmxnbUNjbEk4UDg1a2dkRUhZbG\ +ZtTFoxeXJIMkNXVy9SS0lsWk9ZdFVuNFNpCkp5a2VlNDROWElXU3ovalRBdFRta3VQTzRvUjF5d3dRc\ +jdhUTF5a3hRVm9rVm5vY2xqU0tyQlk4R294a0I0eDIKUDNrb3F1UnkvcUd3QzBnN1o4ZjBTQjNQZVZt\ +eQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==") + ("ringAccountCert" . "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZXakNDQTBLZ\ +0F3SUJBZ0lJRm1tNmZuaWRndEl3RFFZSktvWklodmNOQVFFTUJRQXdUREVRTUE0R0ExVUUKQXhNSFNt\ +RnRhU0JEUVRFNE1EWUdDZ21TSm9tVDhpeGtBUUVUS0RjNVpqSTJaVFZpWTJNeU9EWXlPREppT0dFMwp\ +PRFF6TUdOak1EWXpNakV4T1RFNFkyWm1PVGd3SGhjTk1qRXdOREUyTVRjek1qRXdXaGNOTXpFd05ERT\ +BNVGN6Ck1qRXdXakJKTVEwd0N3WURWUVFERXdSS1lXMXBNVGd3TmdZS0NaSW1pWlB5TEdRQkFSTW9aa\ +k16TkRWbU1qYzMKTldSa1ptVXdOMkUwWWpCa09UVmtZV1ZoTVRFeFpERTFabUpqTVRFNU9UQ0NBaUl3\ +RFFZSktvWklodmNOQVFFQgpCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFQY0czaUQwUk84NE5XL2ZGVllWNHB\ +LQ2MyZE1EQXFCZVN2NEpCcTQ3OHQ5ClhjeERPeEhqSnYvR0dLRnFoVyt4cWFDOUJKZG44TGthdjBBTn\ +MvV1d3YXRNSDVsYlQrZlc0T2pGOVNCZ1Ivc2UKUlNPdWE1QncrSVJlSk5VSnR3enBJS3k1S1RhMnEwd\ +0RyUXhObXBuci9UK2NEK2RQSTJveUlFd2xwRHNKT2lVMAp6eStDU2pBb0FTYkh5TWcraGQwcWJiRFBU\ +ck1uR2xKYkZubXdBQTBaRWU3aWg5Ymx0dlFPaU9TQWJVQm9IUHFpCmNtQW41RVFoNjVFa3dCb1p1U3h\ +qanlCVzZpWUJUbmc5S2c4U2pPVk9BYkJqaXZFZ3RyaFpYZ1JVdE11UWFmaDcKcjRRWDRuYjhRTUE5WX\ +lhME8xbFBJTUd5VEtiNHFIaE02VTd1RHV0NUFjcTN1NGFaZElPQ2prbUNFM3l4UU5UWAo5Vzl0b1NvV\ +1l2YVI1d1gxaFI5eVZCMFZ4V0N0djdZZklha1JiaWkxMS8xZHp3M1dXU1dMbTArTU4rY0pUdnluCk1E\ +U29GNjRpRmcycTVYd1VtWXpPRmJKQUtVd3M4QmVhcFRCVnRYaldDZmNKM01xZEZScDZvM25Lenlja0Y\ +wamoKUjdLSmNRaWhJUW1sbXM1WEtzeHV1d0VMMmFKQ0o0Qm9uSUJDaXZWa09LbllsamtDeVNObzkzam\ +lMalJ4M0ZtRwpoTnJyT3lNbjFIcEd0Z1J2eFUxOC9Ob3FFaWtpdEhCeUtYNW5XU1lUUWN4MXlZY3kxc\ +Vo5cjRqTmdQRzNuUHg0CjJEN2tPTlJPWXNVYXNBUlVTZHJqdlc5aXB2TDAvN2s1Yi9sRzh1WThPODN0\ +NUFPSTFVUG85Y05qMzNyeWJwbUgKQWdNQkFBR2pRekJCTUIwR0ExVWREZ1FXQkJUek5GOG5kZDMrQjZ\ +TdzJWMnVvUkhSWDd3Um1UQVBCZ05WSFJNQgpBZjhFQlRBREFRSC9NQThHQTFVZER3RUIvd1FGQXdNSE\ +JnQXdEUVlKS29aSWh2Y05BUUVNQlFBRGdnSUJBRDMrCjlscFluMjZyeG5pekY2UkNvZFFFVmgvOVF2R\ +Wp1V3dHUWZqa3gxb3VlVjdDMzUyWnpIT2hWU3VGcG43TUxkVFcKamI2dWhMRkpoMWtlTDlYZ0pHalMy\ +V0UwdDlJUGp2UWx5UHIwRWJoWGRJNDJMYUR0NDk0dWQ2MEE0bWg0bW1zbwovcjY2NERKOWMwUjZBOUd\ +QZUJjWi9zekhMQjJ4VmM5M3hYNjVjcmNoVTFLMDBVK2ZZUWtHS0xidFFXeUZzdnlKCmRHdFRxamVlYV\ +VNeGt5dFFWNWFxVHJ1SG4vV3U2RWRZejYrZ0ViQXJHUURRK1J3QmMxMDNGcWRIU0xReWdEWHoKd0pNV\ +GhDREdBVmR6V2NCemJYL1JIZms5bTZzK01HblNJUFBrNG9FOUdFbGdQc2JUZ2FrTzc3aElUdzRxZXJi\ +TAp2M0tiaTVOeVZZVFNVa3hDb0VRSkIrWlZJT3BVNFhRdVAvNkZkWldBRk1LU0Jkd1JLcnRmT1hZT1E\ +xcVBvYU1uCjZPR1VGMU0rYWZ0dTNCMkNhZ2ZMaE5hbVBoSjdxWTNSMzJhK2VRVllvYWlESXZKMElIUH\ +FnQ0NuWXlIaVBHTjQKS3VvaE9IZFpXTkxOUXdIQTg3SDV5NEwrSGZISmdFZFppdWYrbTNMa3JJcnN5M\ +WFoUjgyaEpZVkhreHVyZVRDcQpIR2NJaUIvTHpkSG91WFVrWGNrNjRvWXVRQnM3ZE9KVEx6bGlibU8x\ +elRzVWRoc0d4dE9zc2lYWkFjUURmZHBnCjNHdFJ3UkRwd0ZtL2k5TC9UWjMzMjBwY0VZd21aN1dBSzJ\ +Ra3Z6eWZlelRGeXdLWmh3c0RQRkwycllzLzhXdWsKRk1sek5BVmRMTytTS1RxeGlkM0l1elFaQ0FwU0\ +5ybTJMY2ZVN2grWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBV\ +EUtLS0tLQpNSUlGWFRDQ0EwV2dBd0lCQWdJSXV0T3MxUXBsSVRvd0RRWUpLb1pJaHZjTkFRRU1CUUF3\ +VERFUU1BNEdBMVVFCkF4TUhTbUZ0YVNCRFFURTRNRFlHQ2dtU0pvbVQ4aXhrQVFFVEtEYzVaakkyWlR\ +WaVkyTXlPRFl5T0RKaU9HRTMKT0RRek1HTmpNRFl6TWpFeE9URTRZMlptT1Rnd0hoY05NakV3TkRFMk\ +1UY3pNakExV2hjTk16RXdOREUwTVRjegpNakExV2pCTU1SQXdEZ1lEVlFRREV3ZEtZVzFwSUVOQk1UZ\ +3dOZ1lLQ1pJbWlaUHlMR1FCQVJNb056bG1NalpsCk5XSmpZekk0TmpJNE1tSTRZVGM0TkRNd1kyTXdO\ +ak15TVRFNU1UaGpabVk1T0RDQ0FpSXdEUVlKS29aSWh2Y04KQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0l\ +CQUxTcGduY2tYODd3OE5vVzdRWE5DbWtHSHphVnN1NE9UbjFSSUhqVQpGR0w5MjNvVlk5RHVoZjFtVn\ +llamgremVCOCszaTR4b1E5MU04WDdTVnk4SHZxejQ4c0I2djAxMk5RTGpwN08xCkd4dmc1a0REeDRqb\ +mVyUWd6d0JzVEFuaC8xNy9SOEFDZkhINzYzUjhMRjY1clJPSStOT21KNUV2cU9rRWJJOXYKb0UySko1\ +czBVSHZZM1hTQ2pid01ROXRkM2c0SG9LNmRYSU44a2d6ejg0Yi83YkF5TnZ4a09rNnVSei9CSjhhZQo\ +zWjZudElza2tmVHhIZFpBbGtpVW5DU21Bb3VwQ01TbGRLS3RMRzNja2FhN0FDMDRxS29Rekc0WTN2Tl\ +RCOUlmCmdvYThOazlKMThoaFN2REVuR0haaURLR1dkQVA5RW5GRHZERnRFRFZyVVZSWUN5WHdyejMya\ +29Na3dYODVUMTgKc1F2TUZSdWRsa1BoOGxmbnFEWTFpZEd1R2IvSGlnU1ZqalJKZlVTbS9lZ3hycStS\ +TnpJWGFBOWNuOXAxQkdFbwpZU0YxeUdtTEgzSkJscUhVRTg4VnFkenZRdXZ3Mkhvakdvd0pkdlhmU2l\ +oZk5WOTh6VkEzQ2o3L0d3V2w0VU9OCkRUVUk2SzUrR3Y0a01iYXdxcWduaFlHbHBlZVp2bHE2UlI3OV\ +pNblRWVjJ1RWo4aERYQzdFTGN2Yk5tekJSSkoKS0gzaUxIbmNlSkxOV2NIMUV0K0pkaEFRR2xEYmk2R\ +VR0dHRuaWVaN3ZkMyt6UE00eXpkb3JEMlJXUjRyWG1acQpGRlI5eTBab2hQVTBjVmdKZHFtdUpyV01Z\ +eTVsOGt5SWdwaExkdTR1WWRpc0RPMG1ianEySE55K3pEakpyYXFHClNWTkZBZ01CQUFHalF6QkJNQjB\ +HQTFVZERnUVdCQlI1OG01YnpDaGlncmluaERETUJqSVJrWXovbURBUEJnTlYKSFJNQkFmOEVCVEFEQV\ +FIL01BOEdBMVVkRHdFQi93UUZBd01IQmdBd0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQgpBRWFDblluY\ +m9yWmRhWWZRUmxSb0dtSE94T1g5VFdNMXY0dWEweCtFcG11RDVWRDVlWEY1QVZkMlZadEdaeHYvCkd2\ +VnFBU2l0UTk3ampKV2p2bURWTUZtb3hQSmRYWDFkYTd5cmJYeFRmYm1mM1pac1RpdmZVdWQxYThxdUN\ +3dTUKTnBrdHFjV0JyMHRnNzFhOXlidHJOdm1GczZGRE1WMXkrY2JxYlp1UWlDWnc0WmZhekFaeTRQRG\ +NocE9SNjRCSwpBWFZIT05HcWFoV2hwcDkwd2E0TFEwUTE1U3FDR25kYVI4SHg5MHJOeEdkRjM1T1BLU\ +jd1TDdrWDU4ZGxaWStDClJJK1pKMndYMzJUZzgrc1RtTmNaUTliWDdvS0t3R3E5Uk94SjZJSUhOSnN2\ +bXhaSnlPcmE2N21hNTd3OWxiQnUKSzJlQ3cwZjRDeHdLNU1LNStkbWx6R3dhZmJlMG00TTBvVjlhWUx\ +ZTzAwR3Iza05heW9PdjRRVGtEM2pCMzVSMQpDMGJnQmk2eU1sTVJ2akZ5eEZkOFJpL003VG1jcXNObT\ +B5aklqbkZaenVtMFZTR1NLMXlRU3Flak40S0Y2R0JMCllpZ2JpM3c4WG5HYm9pZGdBUE9ncVVJeTJ1d\ +EU1MllzVXFsVHVncXhtM2xDOUhzaDM2UFJLNURDUG93eHVUNlgKcXo1M1ZiN2h6TkxLelpiRlJzbUdF\ +OFY2cWM2bXZTbUFXa25nL3QwaStXVmdGVkZuZFQrQ0oyNTJsa0ZacGljdAp6ekdETW44VUNDRUp4TDR\ +KTklTM2lLOUhlRys2MlZuay9QOEM3YVpLSXpVdjFud25rcVdUUUFYWDBKckJGdDdICjI5ZDk1RElmRT\ +RuT0FyS0JFNHc2Z1R4SU1uZzVzWi9ZbDFjcG5wUHlsR3VICi0tLS0tRU5EIENFUlRJRklDQVRFLS0tL\ +S0K") + ("ethKey" . "fN8cOT1lYNziaW0+pjBIgZ8r6+zMMhHsukkWBNPDsFo=") + ("TURN.username" . "ring") + ("TURN.server" . "turn.jami.net") + ("TURN.realm" . "ring") + ("TURN.password" . "ring") + ("TURN.enable" . "true") + ("TLS.verifyServer" . "true") + ("TLS.verifyClient" . "true") + ("TLS.serverName" . "") + ("TLS.requireClientCertificate" . "true") + ("TLS.privateKeyFile" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQU\ +RBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRQzM5b1Z0cXNtUGdaSUgKcHpTV\ +GtlT3BlWC9CSEx2KzFTYnJPSFpVRHEwNFZCUU5BNmJmSFNSWTJpbHE1WEVheXNVSmwzQmsvM0txZEhS\ +cQpEV01wQ1dpcE1Vc2FwSGxJR0tSWHEwbXhQZ29WODZSUVBub1dCRTdhWVVEZTlJZXlxMmllZXpDK1l\ +YSnBtWTljCk5tblpaMFlHOHJGMEVpWFA0SHpVWGphZklTKzdKTTJ5ZTZyUlpINXBvdHBQNmV4NXhqVU\ +VuNEFFdWhuWGJ6U0EKNnZMaC9wYnhIUVBHMVlmNHFhcU9TY1lXV0ZWaE5ySVBCVFJNZ2RaTWRGRTh0W\ +VFyaUNkNTV4dUhrYncrQmY1VQpmVENqN25tVEcybDJNbGcrSXBHVkFXUFRWNkl0NFNiS3VadW5MZmRD\ +S2FrSU03SnA3V2dJWjZNRHdkaFFQWjJNClJPQzN0b0c1ajh4aFZOU0Q5QlZiOGZBcnRmeHdldlliQk1\ +yOEdRV2JQYlRKYk9tZHZnUGRGcXNTb1F4QnRUcWQKSG1TMG53RjJ4UGZrdm1Cd3BSWWhHNHpuZlVtMl\ +BQcDBIK1g5Sk96d0R1QWI5K0c0cWZtK3Z6bDd1N0o3anJ0TQpHQlJlSlREdGFNd2RHa0lmcUNRZGREZ\ +HFpM1hzVHVVOVNubVN4NkdxT2V6ZU04bk55dmtZWjR2Uk9vODFzU1JjCjQ4L3pZZjJ1OFBJUm4vVy9x\ +Zk9hbjVIbkcxeFNBUDZkcHAzQ1Y0YTgwUFduZyszcXQ4NW5Ha2k2Nk00NUlnRjgKNHZwRGUyM2YyZnp\ +rTk5OOTk1VTBvUStKVGg5eG1HaWJmenlCaXk5d3RUVHVYWDB3Y3gwTm9wNjdYaFFDVVBGSApybVd6Wj\ +V5bXhEdkRhcUN1U3NwcG0vTkRVRWQyc1FJREFRQUJBb0lDQUYyWXo4bzhXdERvMjZPSkx2Ym1BeTcyC\ +jRra2VsWWZTYXpyQ1AzSUZCWnpqS2xCMHl6STVZWVRUZXI4b2ZhTmtCMXdaOE5WeUlxVVhHeVBhSzls\ +MU1BcmwKU1pFRW5iQlEyVXpCbVh6VVU4MVhhUUpxeHpMc2ZqSWR5U09teG1QaFVobFFGRHpJMTYxaXM\ +4MzI0V1A3WjJXaApsU2U1RkFQdjg1TVpYREVhY1c2R0N5SUVTYVMvdkpHQ2loQ2VzL0pCSmpoejdtNT\ +VRU3liSjl0dnJxUE5KSDhJCmhDTm1BUWhEU3NPYVJXNlpBdGV6UEdUb0FQUHNHMXhLMGdwUlVDM1YyR\ +C90bGRRa0VlSjhxaW5TaUN6ZjZIc3cKTnpncjVUbTMzTm96R3Rjc2Z4ZFl0cVB1UzRPRG40bktLSFpE\ +MTBLTng2Qi9HakdQTHIra21jUUVSMUV4U2s2QwpSemtzSTRzRml6VnVLYTFNK2ZqaVNVc3RTdHV1cTJ\ +QQTJJNzFNTTZlMHJmU3ZKM3VESEJYOWY5T1RFaGxZUFBkCnB1VWM2ek1pdEJKRTg2SFo1M08wR0MzdG\ +p1M1BnSnhmWnJyMHBCU20rSzQ3ajVTUFNkaytiVGh3UDZDZDhzWGUKNmljS3YvMXI0SjVqd1pFTmRna\ +2hKeHVuMkE1WVA0c0NBU21JSFFXWmU1cGdFQ0ljUXBHZjNBVllVdVpGeXZ6cApLL3VBRTc0L3NMK0VU\ +UnhDUlhkN0ZJM2cwZFVySTA2WUFIV1FkY1JpdWpIUU12ZXB3V2RrdUdkaE9wV3VRTy9oCjc0MGgvRlZ\ +0dFdOMjc3ajhhc3ptSDA3T2lRWFIwTU1mN2FEaldMaElMYkd2YkV4TzN0TnRBYXZ6cGxmMUNSNk8KUm\ +1nNDdhVTZpR3lON1MwTE85RUJBb0lCQVFEWWMwelh2UmJHTWxkVVZnOFFTT1ZHKzV4NXVocTVyQ2xtQ\ +lp2ZApvYitWS1hkMXBONThraWkxTFBiYUJmZG9JcWVUamdOK0E0YnVpT3RGNjdCWUdISkp0WTk4ZWR5\ +RkpZREtCSzIyCmthRml2eWVuV01UWG5jaHMvUmNXMnVGS1M3cFAyNDRXYkF2clQxZGxmTTF3L1JzbTZ\ +QVjF1dndPSmNJcEdLSzgKWWgyN2hiaThUbEF6bnJCSS9TbGZwNlpxV3Y0MFRLanNNdmVGVFNWRU5yd1\ +F2MVl4TjcxbjA1UWRVUkIrT0lJSQpPenpNMWpNcm43cjNmS3RKTEx0RllEdUhJZzJDL2E0cUZORmpjM\ +296V1laQkhlcDkrWlEyOTgxdy96VTJIZ0oxCkxiajZjMy9qQU5EakI3MnRkcWMxVUkvMWhwVUh2WDJz\ +emY2czM0L3VSY3RlaFgxWEFvSUJBUURaazVaT01RdVMKNzlVQkhCeTRFbFR2cVkvUUxjMUd1aG9LVXE\ +0dzhONEtJZlpMSDk5TTcwek9JWjNoaEdaYWJDREZHN3RqSDl4Vwo3UnhXVWt5cFRDK1h5TTc1YjF0YW\ +9jRVVyZ1hnUnE4R1JFRXg3OUtwWUE3ei95TVc1OHJCTWhHTWlGZ1JTM00zCmNQSzg2dHBvaTFDN2crd\ +lUxcjJwcDEzN0habzZiUHpKTFRPNXA1OG1tTFRPQVpKd1VSZ3pzZWJnc1dsWXZlR0wKZWNBZ3lYbUtt\ +WmVSeGRNUFlCK0NmMno1TWZ5Ujk4MHRVSDJPaitGQjlJNExzRTExREphZ2wwS1lHMWxKRTBFagpodEV\ +1cTFOTG9DcVkzYXVKYjhtRUpqNlA2Ylc2SytCZTBlUi9CS1MraGxxb3VOYWEySnlhSDc4Qis2U1VZWE\ +RuCnd6MityWUhVZEI4M0FvSUJBRFlXc2ZnaloyS0Z4KzdxUm45aVIvRXlCUXNpSjNXSWdSdmVnUEdrY\ +nRTZWRSeXYKNDIwcnRRSjVSd0o2aFRXL216S3pSVW9qSlgvTU5VYld1ODEzNW05bThJRkJqb3F6TVhq\ +S0xJSzM1NlZlY1ZGUApUSGs1RTVHd3VTbGI3dnA2N0FieXJaSUswL3VzYXdHUWEySTF6YWd1aE5BenR\ +yTHVXcE9jZFdZditwQVd2WEJJCi9aKzRvd0xLU0tGL3FvVmZVYkRPQzFSaTlCbWFpcHArTndiVVdYeV\ +pHanFzMDVGejVYUTFPTUZIMUV5M3BqZmIKaFlRODRpeTZBZDQzU3dqY3lKV1lRUUtCQzBZWDRFeWVyW\ +Dd1TTkvaEUxbWRHUGlJdmNwVk8zWCt3Ly9LQndZNQorUGtTd1NKc3lTSDRqTkRsSGE2K2VuNUpSNy81\ +YWVVNENiY0lFcWNDZ2dFQkFLelMvNnhDWnZnalN5V2poK2hxCm4wN3plQW1icUJmTEVZNHJtTFBGVUF\ +ucWFqSElNbDV4SXFnRnFkd05pQ1BCQ2RLbnNaUU9KYjVpZjRUTndKa2wKckJRNzdMUFRVVlJQY2dnVU\ +p4Uzc4S0Rnckl5Vys5V1FPTEIxZEJEb3MzUDhhbFlmb3h5eHV1Wko4SFpCY3BWaQpQQkdHdTFnSDd3V\ +0lyUzBmbVhkWlJQNGp5cGRvM3hFUWNXWEZkK1dCZE9EektmcEcwZkFzZTdDSFdDWnpBdmttCkFYQklH\ +OXQxdGZHNWQvMEZTS05GbTVPb0FPT3h3L0xZNTgrL0RmZXd0U0VBcFdRZkxTL1BmSWxVdUdvQ3FwcEM\ +Kc2pOVXVNSGxxc011Z2JsY29mNHNoZityWjMzQldYOEJSNWdIb21mRE1ibDNDQWp5TXd1dHpybzVxcD\ +BBUTBWWApxOGNDZ2dFQkFLakFXVVRYY1F2TE8yYkxOZmJBTUlSVXk1T2lTZmJCbDNYRThSZnNzaUt2V\ +VBnTFcwSlV1V3FLCjdGdUFxTlJPRHhrS0pMSTdyQlo2YVNqNitFWHpUMnJwY2dFWktnSjFOUEFRdFNs\ +UjNJUkcyU3JJdjBFK3UzbkUKK1laa3pOa2Q0MUJqTkRjRm1HV21lZk5ROUJmaVIrZlZFSkZmcE5oSkl\ +mNUloSWU0RUtZUE5VUXNua0tSVTlxUApzWi9idXBXc2w4bWVFcko3bllJQ05ucHpnSHRpNXdSMlliVF\ +VXT01odmRFUldxMnhTV3BBYmtNMElhZDBUc05kCmUrYVRQVmJOMXFibFZLMm1qUTl2YS9JSkVuSE51V\ +E9TREtJeUpvcVArQkxiRTVjQU5acXQ2OFFadWdOc2RxNHkKV2FoeStydU5LS1F3Mk5MYzQzZUtsNmxv\ +bXdtRlFZOD0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=") + ("TLS.password" . "") + ("TLS.negotiationTimeoutSec" . "-1") + ("TLS.method" . "Automatic") + ("TLS.ciphers" . "") + ("TLS.certificateFile" . "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZHVENDQ\ +XdHZ0F3SUJBZ0lJU1pUdlZPQnh3akF3RFFZSktvWklodmNOQVFFTUJRQXdTVEVOTUFzR0ExVUUKQXhN\ +RVNtRnRhVEU0TURZR0NnbVNKb21UOGl4a0FRRVRLR1l6TXpRMVpqSTNOelZrWkdabE1EZGhOR0l3WkR\ +rMQpaR0ZsWVRFeE1XUXhOV1ppWXpFeE9Ua3dIaGNOTWpFd05ERTJNVGN6TWpFd1doY05NekV3TkRFME\ +1UY3pNakV3CldqQlFNUlF3RWdZRFZRUURFd3RLWVcxcElHUmxkbWxqWlRFNE1EWUdDZ21TSm9tVDhpe\ +GtBUUVUS0dFM09XTmwKTURVNE16VmhPRFV5WlRsbU5qWmxOelF3TURjeU5EUXdPVFZpTVdaa1kyVXdO\ +bVV3Z2dJaU1BMEdDU3FHU0liMwpEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUUMzOW9WdHFzbVBnWkl\ +IcHpTVGtlT3BlWC9CSEx2KzFTYnJPSFpVCkRxMDRWQlFOQTZiZkhTUlkyaWxxNVhFYXlzVUpsM0JrLz\ +NLcWRIUnFEV01wQ1dpcE1Vc2FwSGxJR0tSWHEwbXgKUGdvVjg2UlFQbm9XQkU3YVlVRGU5SWV5cTJpZ\ +WV6QytZWEpwbVk5Y05tblpaMFlHOHJGMEVpWFA0SHpVWGphZgpJUys3Sk0yeWU2clJaSDVwb3RwUDZl\ +eDV4alVFbjRBRXVoblhielNBNnZMaC9wYnhIUVBHMVlmNHFhcU9TY1lXCldGVmhOcklQQlRSTWdkWk1\ +kRkU4dFlRcmlDZDU1eHVIa2J3K0JmNVVmVENqN25tVEcybDJNbGcrSXBHVkFXUFQKVjZJdDRTYkt1Wn\ +VuTGZkQ0tha0lNN0pwN1dnSVo2TUR3ZGhRUFoyTVJPQzN0b0c1ajh4aFZOU0Q5QlZiOGZBcgp0Znh3Z\ +XZZYkJNcjhHUVdiUGJUSmJPbWR2Z1BkRnFzU29ReEJ0VHFkSG1TMG53RjJ4UGZrdm1Cd3BSWWhHNHpu\ +CmZVbTJQUHAwSCtYOUpPendEdUFiOStHNHFmbSt2emw3dTdKN2pydE1HQlJlSlREdGFNd2RHa0lmcUN\ +RZGREZHEKaTNYc1R1VTlTbm1TeDZHcU9lemVNOG5OeXZrWVo0dlJPbzgxc1NSYzQ4L3pZZjJ1OFBJUm\ +4vVy9xZk9hbjVIbgpHMXhTQVA2ZHBwM0NWNGE4MFBXbmcrM3F0ODVuR2tpNjZNNDVJZ0Y4NHZwRGUyM\ +2YyZnprTk5OOTk1VTBvUStKClRoOXhtR2liZnp5Qml5OXd0VFR1WFgwd2N4ME5vcDY3WGhRQ1VQRkhy\ +bVd6WjV5bXhEdkRhcUN1U3NwcG0vTkQKVUVkMnNRSURBUUFCTUEwR0NTcUdTSWIzRFFFQkRBVUFBNEl\ +DQVFCZmRCc0p4RVVWeFRBeG5vNll1bEFoR1ZvUAplWG8xMHIwOE5DcDZRZlJxeGJlTkZ5aXEvKzEwSE\ +NpL1RoZk41OVdLNlpudFF4NlFNZUxEUVZTb0NjNzlaaWQ4ClE2RUdsWkp1c2RTTmg0VjVteXRCQVZHZ\ +2J2aXJFWU1Wcm5jWWg3bHR2LzVuSGRsbyt2WXV3Vzh0aEhHTk1TUkIKQmhJN2xydmpqY3NkbVl6L1Bp\ +NFNZdkg3c3RaVWpRYmUzNzh3UE90b3lBMTNybEtQUTF4QjJFbUxISDYya21WTQowa25wL1hQQ2o2alR\ +zakpFWko1NzZNMmloYy9DTzkvREVlWWZ4RFlJb004NEF5dTc0UU9UUVN1cnVHRjF5T1RKCmlxRkltTH\ +hMcWRxNk1Zdmx1QjFmTzlKaU9QaS84UEJFTTVpeGYzajlGOFVMQTZUTU1NSklFR1ROeUNzOWpzQloKR\ +UNiWVgweTY4WWtGYnYzQmNWaGk2K1VVWVhBVUd0akhwQ3Z2VThYaHowL0RVZFVaTkpqejRJeWl1ZE5N\ +dnFjQgppSEJDdkxFS1B4VFd1ZlFZaGM5ZkVXTm1valc1WSsvalBVeDcrQWxPM1RXZm1OclBpWDJuSEd\ +5UG5tYjZIR2hWCmp3UU0wT1h4cGxnZ2dQMWpVZ0VYWWRucStjYzdRMy94RFIvdi9Fd244T1d4OVB3eV\ +Y0WFZwZXY5QnpmeWwyQTMKdFhWVkFKMzJtcTlPQmVadXczdWlWU2E2TWdCVG80eXcrYnBjU2VIU2xXO\ +XNRc1NYY3dUNjhvOUdhR2hMNjdXMApwQWx4R2VxSWRtbTZ0MkxIUCtQQnBtL3BweTMvTmh1NFIwMTNv\ +Znp5V2Y0bEcrVnpWVGE0eXVqU1J3UlluYmZyCjlSWER0L0I5VEg5TnNsamdBQT09Ci0tLS0tRU5EIEN\ +FUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZXakNDQTBLZ0F3SU\ +JBZ0lJRm1tNmZuaWRndEl3RFFZSktvWklodmNOQVFFTUJRQXdUREVRTUE0R0ExVUUKQXhNSFNtRnRhU\ +0JEUVRFNE1EWUdDZ21TSm9tVDhpeGtBUUVUS0RjNVpqSTJaVFZpWTJNeU9EWXlPREppT0dFMwpPRFF6\ +TUdOak1EWXpNakV4T1RFNFkyWm1PVGd3SGhjTk1qRXdOREUyTVRjek1qRXdXaGNOTXpFd05ERTBNVGN\ +6Ck1qRXdXakJKTVEwd0N3WURWUVFERXdSS1lXMXBNVGd3TmdZS0NaSW1pWlB5TEdRQkFSTW9aak16Tk\ +RWbU1qYzMKTldSa1ptVXdOMkUwWWpCa09UVmtZV1ZoTVRFeFpERTFabUpqTVRFNU9UQ0NBaUl3RFFZS\ +ktvWklodmNOQVFFQgpCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFQY0czaUQwUk84NE5XL2ZGVllWNHBLQ2My\ +ZE1EQXFCZVN2NEpCcTQ3OHQ5ClhjeERPeEhqSnYvR0dLRnFoVyt4cWFDOUJKZG44TGthdjBBTnMvV1d\ +3YXRNSDVsYlQrZlc0T2pGOVNCZ1Ivc2UKUlNPdWE1QncrSVJlSk5VSnR3enBJS3k1S1RhMnEwd0RyUX\ +hObXBuci9UK2NEK2RQSTJveUlFd2xwRHNKT2lVMAp6eStDU2pBb0FTYkh5TWcraGQwcWJiRFBUck1uR\ +2xKYkZubXdBQTBaRWU3aWg5Ymx0dlFPaU9TQWJVQm9IUHFpCmNtQW41RVFoNjVFa3dCb1p1U3hqanlC\ +VzZpWUJUbmc5S2c4U2pPVk9BYkJqaXZFZ3RyaFpYZ1JVdE11UWFmaDcKcjRRWDRuYjhRTUE5WXlhME8\ +xbFBJTUd5VEtiNHFIaE02VTd1RHV0NUFjcTN1NGFaZElPQ2prbUNFM3l4UU5UWAo5Vzl0b1NvV1l2YV\ +I1d1gxaFI5eVZCMFZ4V0N0djdZZklha1JiaWkxMS8xZHp3M1dXU1dMbTArTU4rY0pUdnluCk1EU29GN\ +jRpRmcycTVYd1VtWXpPRmJKQUtVd3M4QmVhcFRCVnRYaldDZmNKM01xZEZScDZvM25Lenlja0YwamoK\ +UjdLSmNRaWhJUW1sbXM1WEtzeHV1d0VMMmFKQ0o0Qm9uSUJDaXZWa09LbllsamtDeVNObzkzamlMalJ\ +4M0ZtRwpoTnJyT3lNbjFIcEd0Z1J2eFUxOC9Ob3FFaWtpdEhCeUtYNW5XU1lUUWN4MXlZY3kxcVo5cj\ +RqTmdQRzNuUHg0CjJEN2tPTlJPWXNVYXNBUlVTZHJqdlc5aXB2TDAvN2s1Yi9sRzh1WThPODN0NUFPS\ +TFVUG85Y05qMzNyeWJwbUgKQWdNQkFBR2pRekJCTUIwR0ExVWREZ1FXQkJUek5GOG5kZDMrQjZTdzJW\ +MnVvUkhSWDd3Um1UQVBCZ05WSFJNQgpBZjhFQlRBREFRSC9NQThHQTFVZER3RUIvd1FGQXdNSEJnQXd\ +EUVlKS29aSWh2Y05BUUVNQlFBRGdnSUJBRDMrCjlscFluMjZyeG5pekY2UkNvZFFFVmgvOVF2RWp1V3\ +dHUWZqa3gxb3VlVjdDMzUyWnpIT2hWU3VGcG43TUxkVFcKamI2dWhMRkpoMWtlTDlYZ0pHalMyV0Uwd\ +DlJUGp2UWx5UHIwRWJoWGRJNDJMYUR0NDk0dWQ2MEE0bWg0bW1zbwovcjY2NERKOWMwUjZBOUdQZUJj\ +Wi9zekhMQjJ4VmM5M3hYNjVjcmNoVTFLMDBVK2ZZUWtHS0xidFFXeUZzdnlKCmRHdFRxamVlYVVNeGt\ +5dFFWNWFxVHJ1SG4vV3U2RWRZejYrZ0ViQXJHUURRK1J3QmMxMDNGcWRIU0xReWdEWHoKd0pNVGhDRE\ +dBVmR6V2NCemJYL1JIZms5bTZzK01HblNJUFBrNG9FOUdFbGdQc2JUZ2FrTzc3aElUdzRxZXJiTAp2M\ +0tiaTVOeVZZVFNVa3hDb0VRSkIrWlZJT3BVNFhRdVAvNkZkWldBRk1LU0Jkd1JLcnRmT1hZT1ExcVBv\ +YU1uCjZPR1VGMU0rYWZ0dTNCMkNhZ2ZMaE5hbVBoSjdxWTNSMzJhK2VRVllvYWlESXZKMElIUHFnQ0N\ +uWXlIaVBHTjQKS3VvaE9IZFpXTkxOUXdIQTg3SDV5NEwrSGZISmdFZFppdWYrbTNMa3JJcnN5MWFoUj\ +gyaEpZVkhreHVyZVRDcQpIR2NJaUIvTHpkSG91WFVrWGNrNjRvWXVRQnM3ZE9KVEx6bGlibU8xelRzV\ +WRoc0d4dE9zc2lYWkFjUURmZHBnCjNHdFJ3UkRwd0ZtL2k5TC9UWjMzMjBwY0VZd21aN1dBSzJRa3Z6\ +eWZlelRGeXdLWmh3c0RQRkwycllzLzhXdWsKRk1sek5BVmRMTytTS1RxeGlkM0l1elFaQ0FwU05ybTJ\ +MY2ZVN2grWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS\ +0tLQpNSUlGWFRDQ0EwV2dBd0lCQWdJSXV0T3MxUXBsSVRvd0RRWUpLb1pJaHZjTkFRRU1CUUF3VERFU\ +U1BNEdBMVVFCkF4TUhTbUZ0YVNCRFFURTRNRFlHQ2dtU0pvbVQ4aXhrQVFFVEtEYzVaakkyWlRWaVky\ +TXlPRFl5T0RKaU9HRTMKT0RRek1HTmpNRFl6TWpFeE9URTRZMlptT1Rnd0hoY05NakV3TkRFMk1UY3p\ +NakExV2hjTk16RXdOREUwTVRjegpNakExV2pCTU1SQXdEZ1lEVlFRREV3ZEtZVzFwSUVOQk1UZ3dOZ1\ +lLQ1pJbWlaUHlMR1FCQVJNb056bG1NalpsCk5XSmpZekk0TmpJNE1tSTRZVGM0TkRNd1kyTXdOak15T\ +VRFNU1UaGpabVk1T0RDQ0FpSXdEUVlKS29aSWh2Y04KQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUxT\ +cGduY2tYODd3OE5vVzdRWE5DbWtHSHphVnN1NE9UbjFSSUhqVQpGR0w5MjNvVlk5RHVoZjFtVnllamg\ +remVCOCszaTR4b1E5MU04WDdTVnk4SHZxejQ4c0I2djAxMk5RTGpwN08xCkd4dmc1a0REeDRqbmVyUW\ +d6d0JzVEFuaC8xNy9SOEFDZkhINzYzUjhMRjY1clJPSStOT21KNUV2cU9rRWJJOXYKb0UySko1czBVS\ +HZZM1hTQ2pid01ROXRkM2c0SG9LNmRYSU44a2d6ejg0Yi83YkF5TnZ4a09rNnVSei9CSjhhZQozWjZu\ +dElza2tmVHhIZFpBbGtpVW5DU21Bb3VwQ01TbGRLS3RMRzNja2FhN0FDMDRxS29Rekc0WTN2TlRCOUl\ +mCmdvYThOazlKMThoaFN2REVuR0haaURLR1dkQVA5RW5GRHZERnRFRFZyVVZSWUN5WHdyejMya29Na3\ +dYODVUMTgKc1F2TUZSdWRsa1BoOGxmbnFEWTFpZEd1R2IvSGlnU1ZqalJKZlVTbS9lZ3hycStSTnpJW\ +GFBOWNuOXAxQkdFbwpZU0YxeUdtTEgzSkJscUhVRTg4VnFkenZRdXZ3Mkhvakdvd0pkdlhmU2loZk5W\ +OTh6VkEzQ2o3L0d3V2w0VU9OCkRUVUk2SzUrR3Y0a01iYXdxcWduaFlHbHBlZVp2bHE2UlI3OVpNblR\ +WVjJ1RWo4aERYQzdFTGN2Yk5tekJSSkoKS0gzaUxIbmNlSkxOV2NIMUV0K0pkaEFRR2xEYmk2RVR0dH\ +RuaWVaN3ZkMyt6UE00eXpkb3JEMlJXUjRyWG1acQpGRlI5eTBab2hQVTBjVmdKZHFtdUpyV01ZeTVsO\ +Gt5SWdwaExkdTR1WWRpc0RPMG1ianEySE55K3pEakpyYXFHClNWTkZBZ01CQUFHalF6QkJNQjBHQTFV\ +ZERnUVdCQlI1OG01YnpDaGlncmluaERETUJqSVJrWXovbURBUEJnTlYKSFJNQkFmOEVCVEFEQVFIL01\ +BOEdBMVVkRHdFQi93UUZBd01IQmdBd0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQgpBRWFDblluYm9yWm\ +RhWWZRUmxSb0dtSE94T1g5VFdNMXY0dWEweCtFcG11RDVWRDVlWEY1QVZkMlZadEdaeHYvCkd2VnFBU\ +2l0UTk3ampKV2p2bURWTUZtb3hQSmRYWDFkYTd5cmJYeFRmYm1mM1pac1RpdmZVdWQxYThxdUN3dTUK\ +TnBrdHFjV0JyMHRnNzFhOXlidHJOdm1GczZGRE1WMXkrY2JxYlp1UWlDWnc0WmZhekFaeTRQRGNocE9\ +SNjRCSwpBWFZIT05HcWFoV2hwcDkwd2E0TFEwUTE1U3FDR25kYVI4SHg5MHJOeEdkRjM1T1BLUjd1TD\ +drWDU4ZGxaWStDClJJK1pKMndYMzJUZzgrc1RtTmNaUTliWDdvS0t3R3E5Uk94SjZJSUhOSnN2bXhaS\ +nlPcmE2N21hNTd3OWxiQnUKSzJlQ3cwZjRDeHdLNU1LNStkbWx6R3dhZmJlMG00TTBvVjlhWUxZTzAw\ +R3Iza05heW9PdjRRVGtEM2pCMzVSMQpDMGJnQmk2eU1sTVJ2akZ5eEZkOFJpL003VG1jcXNObTB5akl\ +qbkZaenVtMFZTR1NLMXlRU3Flak40S0Y2R0JMCllpZ2JpM3c4WG5HYm9pZGdBUE9ncVVJeTJ1dEU1Ml\ +lzVXFsVHVncXhtM2xDOUhzaDM2UFJLNURDUG93eHVUNlgKcXo1M1ZiN2h6TkxLelpiRlJzbUdFOFY2c\ +WM2bXZTbUFXa25nL3QwaStXVmdGVkZuZFQrQ0oyNTJsa0ZacGljdAp6ekdETW44VUNDRUp4TDRKTklT\ +M2lLOUhlRys2MlZuay9QOEM3YVpLSXpVdjFud25rcVdUUUFYWDBKckJGdDdICjI5ZDk1RElmRTRuT0F\ +yS0JFNHc2Z1R4SU1uZzVzWi9ZbDFjcG5wUHlsR3VICi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K") + ("STUN.server" . "") + ("STUN.enable" . "false") + ("SRTP.rtpFallback" . "false") + ("SRTP.keyExchange" . "sdes") + ("SRTP.enable" . "true") + ("RingNS.uri" . "") + ("RingNS.account" . "0790738ce15fa05933b49dd77034312787da86c3") + ("DHT.PublicInCalls" . "true") + ("Account.videoPortMin" . "49152") + ("Account.videoPortMax" . "65534") + ("Account.videoEnabled" . "true") + ("Account.username" . "f3345f2775ddfe07a4b0d95daea111d15fbc1199") + ("Account.useragent" . "") + ("Account.upnpEnabled" . "true") + ("Account.type" . "RING") + ("Account.ringtoneEnabled" . "true") + ("Account.rendezVous" . "true") + ("Account.publishedSameAsLocal" . "true") + ("Account.publishedPort" . "5060") + ("Account.publishedAddress" . "") + ("Account.presenceSubscribeSupported" . "true") + ("Account.peerDiscovery" . "false") + ("Account.managerUsername" . "") + ("Account.managerUri" . "") + ("Account.mailbox" . "") + ("Account.localModeratorsEnabled" . "true") + ("Account.localInterface" . "default") + ("Account.hostname" . "bootstrap.jami.net") + ("Account.hasCustomUserAgent" . "false") + ("Account.enable" . "true") + ("Account.dtmfType" . "overrtp") + ("Account.displayName" . "dummy") + ("Account.defaultModerators" . "") + ("Account.audioPortMin" . "16384") + ("Account.audioPortMax" . "32766") + ("Account.archiveHasPassword" . "false") + ("Account.allowCertFromTrusted" . "true") + ("Account.allowCertFromHistory" . "true") + ("Account.allowCertFromContact" . "true") + ("Account.allModeratorEnabled" . "true") + ("Account.alias" . "dummy") + ("Account.activeCallLimit" . "-1") + ("Account.accountPublish" . "false") + ("Account.accountDiscovery" . "false"))) diff --git a/gnu/tests/telephony.scm b/gnu/tests/telephony.scm new file mode 100644 index 0000000000..1d98294411 --- /dev/null +++ b/gnu/tests/telephony.scm @@ -0,0 +1,204 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Maxim Cournoyer . +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu tests telephony) + #:use-module (gnu) + #:use-module (gnu packages guile) + #:use-module (gnu tests) + #:use-module (gnu system vm) + #:use-module (gnu services) + #:use-module (gnu services dbus) + #:use-module (gnu services ssh) + #:use-module (gnu services telephony) + #:use-module (guix gexp) + #:use-module (guix modules) + #:export (%test-jami-daemon + %test-jami-daemon-provisioning)) + +;;; +;;; Jami daemon. +;;; + +(define define-with-retries (@@ (gnu services telephony) define-with-retries)) + +(include "data/jami-dummy-account.dat") ;defines %jami-account-content-sexp + +(define %dummy-jami-account + ;; A Jami account archive is a gzipped JSON file. + (computed-file + "dummy-jami-account.gz" + (with-extensions (list guile-json-4 guile-zlib) + #~(begin + (use-modules (json) (zlib)) + (let ((port (open-output-file #$output))) + (call-with-gzip-output-port port + (lambda (port) + (scm->json '#$%jami-account-content-sexp port)))))))) + +(define* (make-jami-daemon-os #:key provisioning?) + (simple-operating-system + (service jami-daemon-service-type + (if provisioning? + (jami-daemon-configuration + (account-archives (list %dummy-jami-account))) + (jami-daemon-configuration))) + (service dbus-root-service-type) + (service openssh-service-type ;for debugging + (openssh-configuration + (permit-root-login 'without-password))))) + +(define %jami-daemon-os + (make-jami-daemon-os)) + +(define %jami-daemon-os-provisioning + (make-jami-daemon-os #:provisioning? #t)) + +(define* (run-jami-daemon-test #:key provisioning?) + "Run tests in %JAMI-DAEMON-OS. When PROVISIONING? is true, test the +accounts provisioning feature of the service." + (define os (marionette-operating-system + (if provisioning? + %jami-daemon-os-provisioning + %jami-daemon-os) + #:imported-modules '((gnu services herd) + (guix combinators)))) + (define vm (virtual-machine + (operating-system os) + (memory-size 512))) + + (define test + (with-imported-modules '((gnu build marionette)) + #~(begin + (use-modules (rnrs base) + (srfi srfi-11) + (srfi srfi-64) + (gnu build marionette)) + + (define marionette + (make-marionette (list #$vm))) + + (mkdir #$output) + (chdir #$output) + + (test-begin "jami-daemon") + + (test-assert "service running" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) (number? pid)))))) + marionette)) + + (test-assert "service can be stopped" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + #$define-with-retries + (setenv "PATH" "/run/current-system/profile/bin") + (let ((pid (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid)))))) + + (assert (number? pid)) + + (match (stop-service 'jami-daemon) + (services ;a list of service symbols + (member 'jami-daemon services))) + ;; Sometimes, the process still appear in pgrep, even + ;; though we are using waitpid after sending it SIGTERM + ;; in the service; use retries. + (with-retries 20 1 + (not (zero? (status:exit-val + (system* "pgrep" "dring"))))))) + marionette)) + + (test-assert "service can be restarted" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + ;; Start and retrieve the current PID. + (define pid (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid))))) + (assert (number? pid)) + + ;; Restart the service. + (restart-service 'jami-daemon) + + (define new-pid (match (start-service 'jami-daemon) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid))))) + (assert (number? new-pid)) + + (not (eq? pid new-pid))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami accounts provisioning" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + + #$define-with-retries + + (setenv "PATH" "/run/current-system/profile/bin") + ;; The imported account takes some time to appear in the + ;; account files. + (with-retries 20 1 + (zero? (status:exit-val + (system* "grep" "-r" + #$(assoc-ref %jami-account-content-sexp + "Account.username") + "/var/lib/jami/.local/share/jami/"))))) + marionette)) + + (test-end) + (exit (= (test-runner-fail-count (test-runner-current)) 0))))) + + (gexp->derivation (if provisioning? + "jami-daemon-provisioning-test" + "jami-daemon-test") + test)) + +(define %test-jami-daemon + (system-test + (name "jami-daemon") + (description "Basic tests for the jami-daemon service.") + (value (run-jami-daemon-test)))) + +(define %test-jami-daemon-provisioning + (system-test + (name "jami-daemon-provisioning") + (description "Provisioning test for the jami-daemon service.") + (value (run-jami-daemon-test #:provisioning? #t)))) + +;; Local Variables: +;; eval: (put 'with-retries 'scheme-indent-function 2) +;; End: -- 2.31.1 From debbugs-submit-bounces@debbugs.gnu.org Thu May 20 08:37:28 2021 Received: (at 47849) by debbugs.gnu.org; 20 May 2021 12:37:28 +0000 Received: from localhost ([127.0.0.1]:33314 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ljhvc-0006YZ-8Y for submit@debbugs.gnu.org; Thu, 20 May 2021 08:37:28 -0400 Received: from mail-qk1-f181.google.com ([209.85.222.181]:44817) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ljhva-0006YM-8r for 47849@debbugs.gnu.org; Thu, 20 May 2021 08:37:27 -0400 Received: by mail-qk1-f181.google.com with SMTP id h20so379261qko.11 for <47849@debbugs.gnu.org>; Thu, 20 May 2021 05:37:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=pTo0eo+3ZQhMC9qKLLAGKb+pb/tQcVPs+oXF+yzTB98=; b=SAnhaxzhGRUlZirgIkeO1nSR2ZIFFXQTSOhDoEJmSpDAIgbKpav5TDnKjJNWZroXlB aHQ3Jp/7XR1ggzFdo21tlNxjlalcbSR021SjtItAd4yW2aaZzBQ2EBY3eOVI/+0EsPWh 5VfqYfc/89eg9HO16VmnpNBB2+XSAj/14toXFVKyX/vZrJoJF4hFVn2s79XiGYQW5kFf zpO4XOKV6l4VBUrQPg5akeczTPZVoBDD3KSBFBZ5tQZhN/g+e4h+6xF1HLrj2HKgF5Kj wJNfglooVDzvLgGV9to40HbnpYvvku3ZC6wkeHFVMplHuRanz8riWC+CadD3Ujls8axz l80Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=pTo0eo+3ZQhMC9qKLLAGKb+pb/tQcVPs+oXF+yzTB98=; b=Wz54Mvau/FH82QT7u+Kse7pzSjA6a1hdcdD6qPtBJLMO3/GVAmG/kjMtl3xEgS5wG0 37anpRwQ6z/yt2HoXNFKJfaFA+hhhtVbhrm0iacJUWbT1/HRZSwwX6sKy//dmSl5ds+Q cJr5azMan06R7YqxfBgF3xGQA+OMgK0Xq91ka1V49FA7DjDCROW3OkR+NqsIk5q/tZOg RsaiCd5gV1qkIiPWOdYSJuD263HeFKPVNWd2uHgCvEhs8tJ4y9sRlD7SwXVN7J3hXTc2 Evhp5pIGpItwYyJ77KHCp6apSf4XgG2RvhwU3QLRMAFEzbBcXqzmisB4rbpRhocfN/rh xRDg== X-Gm-Message-State: AOAM533Tuq59cV2fFOQXiOOYVPGVDkFadcfCKC6n82Gv684sF0+n+RO1 DL4vR/rzNpQkmE7hw8H/lA9IEcJP1XI= X-Google-Smtp-Source: ABdhPJwlxYQVVYORRG1WyGdxpBJ+tVcnqExEKSExTef1S4748AE3vd0cordjL49SL4ff10chAmnAWA== X-Received: by 2002:a37:e312:: with SMTP id y18mr4739801qki.39.1621514240620; Thu, 20 May 2021 05:37:20 -0700 (PDT) Received: from hurd (dsl-150-81.b2b2c.ca. [66.158.150.81]) by smtp.gmail.com with ESMTPSA id y13sm1836559qkj.84.2021.05.20.05.37.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 May 2021 05:37:20 -0700 (PDT) From: Maxim Cournoyer To: Maxime Devos Subject: Re: [bug#47849] [PATCH 1/1] services: Add a service for the Jami daemon. References: <20210417200414.18050-1-maxim.cournoyer@gmail.com> <20210417200617.18182-1-maxim.cournoyer@gmail.com> <8f42495246e684121605e7cef2462a068130d5cc.camel@telenet.be> Date: Thu, 20 May 2021 08:37:19 -0400 In-Reply-To: <8f42495246e684121605e7cef2462a068130d5cc.camel@telenet.be> (Maxime Devos's message of "Sun, 18 Apr 2021 13:47:03 +0200") Message-ID: <87cztl1szk.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849 Cc: 47849@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hello Maxime. Maxime Devos writes: > Maxim Cournoyer schreef op za 17-04-2021 om 16:06 [-0400]: >> + ;; Start the daemon. >> + (define daemon-pid >> + (fork+exec-command >> + '#$(jami-daemon-configuration->command-line-arguments config) >> + #:user "jami" >> + #:group "jami" >> + #:environment-variables >> + (list (string-append "DBUS_SESSION_BUS_ADDRESS=" >> + "unix:path=/var/run/jami/bus")))) > > It would be nice if this could be run in a container > that only has access to the relevant parts of the file system > (and not, say, /run/setuid-programs). See, e.g., gnu/build/linux-container.scm. That's now the case in the just-sent v2, both for the D-Bus session service as well as the Jami process itself :-). I figured out I could simply call make-forkexec+constructor/container and execute apply the resulting procedure. I've also manage to (with much difficulty!) have the service properly start, stop or restart without races. The new tests proved really useful for the lengthy trial and error process that I had to go through. Thanks for your patience! Maxim From debbugs-submit-bounces@debbugs.gnu.org Thu May 20 10:49:50 2021 Received: (at control) by debbugs.gnu.org; 20 May 2021 14:49:50 +0000 Received: from localhost ([127.0.0.1]:34981 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ljjzh-0004Qa-Vq for submit@debbugs.gnu.org; Thu, 20 May 2021 10:49:50 -0400 Received: from mail-qk1-f177.google.com ([209.85.222.177]:43987) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ljjzg-0004QN-5i for control@debbugs.gnu.org; Thu, 20 May 2021 10:49:48 -0400 Received: by mail-qk1-f177.google.com with SMTP id 124so4084590qkh.10 for ; Thu, 20 May 2021 07:49:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:message-id:to:from:subject; bh=i1uNNtwniSMvkB680DAHLi5rYmCq8fErTS4aMSkIGpo=; b=Kw2yjXFL95zFO0pOjXuMHTg8X+o2rIymAiI2NakqToZtWYp3ldML8QNMXbCOiSut7f bn9GxRRswkCB+flK7yM6lArwU02gd6Mqo5zlYlhoMfeaU5M/9AHHc16dcJOW44lSIkeq AIBXrHTJKA2etFFOEqvd7XPFA6qUplJ9biC2LYUPe4pJ+83d9InFd4mDCwGM1YwjnyJW UklW4Cu0JfZvoBnEv7Mfn6nnC6oMNG2pAU5/gWcVjyQ1Vmk4rG7Iz+zNyh9XLxlZWNYH oJcoNbqEumvSDzgSyKrSyZSqHX2zZa+bblwk2+snvYTfIlL+ET4UAnmcPJAUKewzv0fv LiOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:to:from:subject; bh=i1uNNtwniSMvkB680DAHLi5rYmCq8fErTS4aMSkIGpo=; b=tHmJEoqLlted3pnOKeKWT5INpydX6IBiW2hZS6E58ZKVmMsFuDbhDfXGjNeIaS9tz3 ohwWuuPKmhginXJfpKRxIMIXav8Oa3a1Cx10ZvhfWbbwTk2MEfub6b9p+hxPnvWpE3mu /TDAzZTwNTN/Mff4qBOaAyIbz+l8D7y181ZjtX/5xcu3WG7nUlD3drFK0w0u9Q6zNJGE Iw9DJ6+7XI2Pgabi+efCZ740gfZdEmjKQ/ibi6oXujHR3nMg787Ay/omrxCohcCWIY4k nl+mZSNtj2pNQWUICkfAhajTfIT5h2cSoMN/yEuBVYgnTzVKP0MuzspRqBCsEDh5g5m5 7Tow== X-Gm-Message-State: AOAM5334TaHL4rFjlJCLce2PrpoS1RW4vApKRe4SPXiCOKlKAma90M0Z KzYuvr7rtQv6D5sclTaNGkk9kr77sUkLqA== X-Google-Smtp-Source: ABdhPJzHoYkhXQB9jbxirZ+8vqY5XXhW2InTX4X30Pz1iqSziqLiDXh0HEQEIWDHvDFGqFFbXINLfg== X-Received: by 2002:a05:620a:2226:: with SMTP id n6mr5762993qkh.496.1621522182373; Thu, 20 May 2021 07:49:42 -0700 (PDT) Received: from hurd (dsl-150-81.b2b2c.ca. [66.158.150.81]) by smtp.gmail.com with ESMTPSA id g64sm2097995qkf.41.2021.05.20.07.49.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 May 2021 07:49:42 -0700 (PDT) Date: Thu, 20 May 2021 10:49:41 -0400 Message-Id: <87a6opzchm.fsf@gmail.com> To: control@debbugs.gnu.org From: Maxim Cournoyer Subject: control message for bug #47849 X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) retitle 47849 [PATCH] Add a jami-daemon service. quit From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 01 02:59:26 2021 Received: (at 47849) by debbugs.gnu.org; 1 Aug 2021 06:59:26 +0000 Received: from localhost ([127.0.0.1]:35442 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5RW-0000oW-0A for submit@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:26 -0400 Received: from mail-qt1-f174.google.com ([209.85.160.174]:35416) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5RT-0000oG-Se for 47849@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:24 -0400 Received: by mail-qt1-f174.google.com with SMTP id a12so9582369qtb.2 for <47849@debbugs.gnu.org>; Sat, 31 Jul 2021 23:59:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=gwXurMKME59g3CHeZ6KH8GXhCnI04L9QCEj/vaJv2/I=; b=j844iwXhpf2Xw11lfr2bW/dkpPMX1wYNmTdwRWO3vTiH/9WXJkFoO8TZMrYIIHHCMT AS2idWXgDE/ny335OuujbZHvl3BeJ/AZaB80aNyWjf5MvGldFnONloWeIbjoDWgDyc8O +Y1uZsZNZz4FbtWRZnJlzHgSffZQYQ0dNbF24CyR+M3X7ddGLEVbSbybHFq6TQIqSIlo 7uauIv+2rFMcyNCE6T9q1EaSmZOvUjJO8lCrLkFw8vLwD6Mb3hJDCo6TmkiLsTyWo1qf y9NFkObE4sEfpLDMI01c74hU11EsJ94iPfn/wYGO3dDPugQ+J19shRzWcYdb+ccJLs+x NpBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=gwXurMKME59g3CHeZ6KH8GXhCnI04L9QCEj/vaJv2/I=; b=gXIOzMS6d45RE85Yt9jaKfTOPNTegUHZ5DFlkWGjmqikOuXEcLNJMPafJbbAhfOsb3 Nxx3T49d5CNViPyjXKIJf++r/G25RzVsf14SP3Jmoy+MVpo4oP0RHhCjeaCQQP0n3YbS r5FEE8lbGfMc/9AWxsy9oG+qDm+2hWOKezp73c4NtwjPkZrImaNyC39DaO/ydeub7ixl w3WMW4bM5j/vKc5r8tEICWvbNJNKkDQM4Pn5hAuNZzAz0tiMyv5RAsAVpUUZFh2fadks kjnlekxQkPPA9g8YnCrAe7Stoo+p+XTuSTwttrmfBVAduPji9NGrtKab/xKZpQiIdxJ3 y6Fg== X-Gm-Message-State: AOAM530/v/uK7zzRMqcOD5OwMtb5MmH+o4foywRdcbxX0CoMSq4o84My oDZPLh7c0iwycBv2df/zNF5NqDPkFDP/bA== X-Google-Smtp-Source: ABdhPJwABZl73F9yvp9zXPQ/ei5ezh4fLIa3362V0EiC5fsxHmppqd5OUkLKoeb0+xRz5syV8EeXPQ== X-Received: by 2002:ac8:6645:: with SMTP id j5mr8992878qtp.244.1627801158152; Sat, 31 Jul 2021 23:59:18 -0700 (PDT) Received: from localhost.localdomain (dsl-10-135-95.b2b2c.ca. [72.10.135.95]) by smtp.gmail.com with ESMTPSA id d16sm2834823qtj.69.2021.07.31.23.59.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 31 Jul 2021 23:59:17 -0700 (PDT) From: Maxim Cournoyer To: 47849@debbugs.gnu.org Subject: [PATCH v3] services: Add a service for the Jami daemon. Date: Sun, 1 Aug 2021 02:58:54 -0400 Message-Id: <20210801065857.27657-1-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 47849 Cc: Maxime Devos X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Maxime Devos Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hello! This is a much more featureful/refined version of the previously sent v2 Jami service. I think it's ready! Thank you, Maxim [PATCH v3 1/3] .dir-locals.el: Specify indentation rule for [PATCH v3 2/3] build: shepherd: Use autoload to lazily bind Shepherd [PATCH v3 3/3] services: Add a service for Jami. From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 01 02:59:29 2021 Received: (at 47849) by debbugs.gnu.org; 1 Aug 2021 06:59:29 +0000 Received: from localhost ([127.0.0.1]:35446 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5RZ-0000om-7J for submit@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:29 -0400 Received: from mail-qk1-f180.google.com ([209.85.222.180]:45820) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5RX-0000oL-Iy for 47849@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:27 -0400 Received: by mail-qk1-f180.google.com with SMTP id 190so13709989qkk.12 for <47849@debbugs.gnu.org>; Sat, 31 Jul 2021 23:59:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=3sEFCizgGAF5xsRnalW3Xi4iuj4JxpmkXljZgVPmUck=; b=pBjOanld6VGnDISrUEPBaxYagYe7Y+0Qq2ibRbPfBa5K1rcUWfbk9A9UDz/krKG9jR ZdxWKpdupkpvR9agCcC96n2d7N3qbFfosnNrXePvFYbDEU5ppNYiJNdf/XFar+voJwDT HIbzag6zvxVM5EDlizz5jVGTSwzUj3wvXXb+Tr2WRCxhuOLQ6zXyAVNfxMCKbQjSm2p4 QiXSp9ssPqXgUam+Gxu6Ehi9AW5Sgn8NMzbwAUfW60kv8DdqO8wAxxK4kbyo4JVH2d3C Sb62pW25A1FiliptP4G9nDGxzNh7bsaQsN+/u/zwUhyO79Ky2znLcMMztysbPNnNrZ31 JH7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=3sEFCizgGAF5xsRnalW3Xi4iuj4JxpmkXljZgVPmUck=; b=W6HbVJoCSnjlwHl1tvo5KRMfxQoKiUWmE0ZUBXnhvYn4wOY8LyKBMj4B8CcfG3zxSU kM5oJhr8fxxRgJ9yukhad8pX78EVKoDr/2dcrXMNEJ1/rog16UeN4pFm3fuRT+u8mWf7 3M7P+U6gyZM84Loh0Ba6Twpo0z4H3z/xJd0xLSxJD/uxA95wvTHH+HhAezwx4dS6JazQ O8m6/r9fs7OtHfrZ1+5kPp0PX2wvQbWyMVsN82Rmgfa8T/K2FlkmTEMjG/fCZ8wImR6T 6d9pqulgs/XXCLnIETL2BeRQ7/jrKkvmOFVgsnISecMDcwl45T36m2UTnpMy3jatuWe7 UJjA== X-Gm-Message-State: AOAM532WE1DkZAxTIexEr6Nr3BnPMRkcT8EsBsh/Zzm8w5alLohf2BEF cnDwvfOjNBBMRacZJJtQuO1Aq/sLzkK/yA== X-Google-Smtp-Source: ABdhPJwCfMdN4j5kHxjUI9YoS+QqRtHhhA6NWMUfVi3h8WjZ9MdYW/cVtEBiT2ddbNb4O85ELiZWTA== X-Received: by 2002:a05:620a:1327:: with SMTP id p7mr9883924qkj.483.1627801161955; Sat, 31 Jul 2021 23:59:21 -0700 (PDT) Received: from localhost.localdomain (dsl-10-135-95.b2b2c.ca. [72.10.135.95]) by smtp.gmail.com with ESMTPSA id d16sm2834823qtj.69.2021.07.31.23.59.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 31 Jul 2021 23:59:21 -0700 (PDT) From: Maxim Cournoyer To: 47849@debbugs.gnu.org Subject: [PATCH v3 1/3] .dir-locals.el: Specify indentation rule for with-shepherd-action. Date: Sun, 1 Aug 2021 02:58:55 -0400 Message-Id: <20210801065857.27657-2-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210801065857.27657-1-maxim.cournoyer@gmail.com> References: <20210801065857.27657-1-maxim.cournoyer@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 47849 Cc: Maxime Devos , Maxim Cournoyer X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Maxime Devos Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) * .dir-locals.el (scheme-mode) : New indentation rule. --- .dir-locals.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.dir-locals.el b/.dir-locals.el index a4fcbfe7ca..aaa48ab552 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -141,6 +141,8 @@ (eval . (put 'with-paginated-output-port 'scheme-indent-function 1)) + (eval . (put 'with-shepherd-action 'scheme-indent-function 3)) + ;; This notably allows '(' in Paredit to not insert a space when the ;; preceding symbol is one of these. (eval . (modify-syntax-entry ?~ "'")) -- 2.32.0 From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 01 02:59:30 2021 Received: (at 47849) by debbugs.gnu.org; 1 Aug 2021 06:59:30 +0000 Received: from localhost ([127.0.0.1]:35448 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5Ra-0000oz-FL for submit@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:30 -0400 Received: from mail-qk1-f175.google.com ([209.85.222.175]:42988) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5RZ-0000oN-3u for 47849@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:29 -0400 Received: by mail-qk1-f175.google.com with SMTP id o13so13730313qkk.9 for <47849@debbugs.gnu.org>; Sat, 31 Jul 2021 23:59:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=mQAe+BVWygempM578fVV7sqhKF1hu/Nbl5Qo0VUFRZM=; b=nsGU22prLQAlXaM7jfWtMRG4Hjg1TldoaIunA9TcpkcIFP24IDep6h1gecw1i6A1Fw Yq4x2PW0P4WSUNIUWp5oUIfiIF7JwlHbNu4znzYx1vQCqPFy+LM3EkdawQ+YkhV33lYF +2346CauCXhdEFQ0v6uUYT2bqTsFOSKAg2N3ce+fzyTtZg5QkmbCSYxROTZtGYwfMA6B SqdW+0mmOxURyoNlhL68VTC1rdU+v/jS1i/EL70cIJyAMNc+inoioImAxLi1SibDvxOX Vln+y/5Tt2IPG129JNLPFFyROoAkZohSlz32ZSOL2L2QEuY0Gcc+HIbG05oeyO7hJzN+ HqYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=mQAe+BVWygempM578fVV7sqhKF1hu/Nbl5Qo0VUFRZM=; b=Yg0Gr+lm+2T7y2ZlL42gV73b3POL24oqbncBPpuYiCjCNTMozlQBYw1Ro1mdUpzs4M J/o9J1nmVBo1zqdRMKI1hto5jlQ/o7kXILPd2i4sCcul+Ie/3GSHDJC65ZuuPx+SOJX0 4BkAACBp3gFxy+ukky22lk5tsKQM7kfFmi5J2OMEpyJ4SWCGan5eWrAriN5sgJ9rSuw/ XFU7qI2UIBlPG66SBmuf5K1qB+ol7nRD5xfZ83yUMKY6S5DCkelWj0JL7pyiNkBb6ZHu yVwVrguXVKdX/rPoqjxqr7reO1SAgl6VDTbL8XWjGULa5NNCWmn8q3A5XcSQ6GjksCm9 wEBw== X-Gm-Message-State: AOAM532sIuulfIRfT4A8XzsTPUeVEIgwAyhLvA4ah0yQRYzzK1EZQb6v 6/MQSCzVAMbX/M3ZFBSIgw5Ws4qafStB7w== X-Google-Smtp-Source: ABdhPJwyWzmE52UTo6mX7hc3M3qmycNXcz19KTYKykyym4dY9i7VAO6acrDavuEGFZgkPZlWrWvHig== X-Received: by 2002:a37:e04:: with SMTP id 4mr9954975qko.281.1627801163567; Sat, 31 Jul 2021 23:59:23 -0700 (PDT) Received: from localhost.localdomain (dsl-10-135-95.b2b2c.ca. [72.10.135.95]) by smtp.gmail.com with ESMTPSA id d16sm2834823qtj.69.2021.07.31.23.59.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 31 Jul 2021 23:59:23 -0700 (PDT) From: Maxim Cournoyer To: 47849@debbugs.gnu.org Subject: [PATCH v3 2/3] build: shepherd: Use autoload to lazily bind Shepherd modules. Date: Sun, 1 Aug 2021 02:58:56 -0400 Message-Id: <20210801065857.27657-3-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210801065857.27657-1-maxim.cournoyer@gmail.com> References: <20210801065857.27657-1-maxim.cournoyer@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 47849 Cc: Maxime Devos , Maxim Cournoyer X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Maxime Devos Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Instead of imperative module-autoload! directives. * gnu/build/shepherd.scm: Replace module-autoload! directives by autoload arguments for define-module. --- gnu/build/shepherd.scm | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/gnu/build/shepherd.scm b/gnu/build/shepherd.scm index d7b858dea4..778e3fc627 100644 --- a/gnu/build/shepherd.scm +++ b/gnu/build/shepherd.scm @@ -24,6 +24,12 @@ #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (ice-9 match) + ;; XXX: Lazy-bind the Shepherd to avoid a compile-time dependency. + #:autoload (shepherd service) (fork+exec-command + read-pid-file + exec-command + %precious-signals) + #:autoload (shepherd system) (unblock-signals) #:export (make-forkexec-constructor/container fork+exec-command/container)) @@ -92,14 +98,6 @@ (file-exists? (file-system-mapping-source mapping))) mappings))))) -;; XXX: Lazy-bind the Shepherd to avoid a compile-time dependency. -(module-autoload! (current-module) - '(shepherd service) - '(fork+exec-command read-pid-file exec-command - %precious-signals)) -(module-autoload! (current-module) - '(shepherd system) '(unblock-signals)) - (define* (read-pid-file/container pid pid-file #:key (max-delay 5)) "Read PID-FILE in the container namespaces of PID, which exists in a separate mount and PID name space. Return the \"outer\" PID. " -- 2.32.0 From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 01 02:59:33 2021 Received: (at 47849) by debbugs.gnu.org; 1 Aug 2021 06:59:33 +0000 Received: from localhost ([127.0.0.1]:35450 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5Rd-0000pE-QH for submit@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:33 -0400 Received: from mail-qv1-f53.google.com ([209.85.219.53]:42849) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA5Rc-0000of-TF for 47849@debbugs.gnu.org; Sun, 01 Aug 2021 02:59:33 -0400 Received: by mail-qv1-f53.google.com with SMTP id f91so7432796qva.9 for <47849@debbugs.gnu.org>; Sat, 31 Jul 2021 23:59:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=lc0GIGYc7kKgVQcRu/Hyd3K9adVcqDy3EXyUdccW1xA=; b=DlW5ok44HBxEOFy24hAqO6GG4XQQH9eizwlMjV/gi+orfc0mCdfj8hXJI1NcB5Qd4m jynaYa5mEurjstpC6OpnXMkfugTW1oiqg7t21mFusUC2QhK+GrzOZO+4ydhaU71Ewko9 C/45qHPfSnUaRPGNNjIyQQqI4tKjlxg9uIbpcV9wn/YXuziJP2mH0nfog5oE6VhgrBrf 5037ZnxGJt4Tmhf39noevXFgAzraiiQIRzdDnAn9LW++GAYu1AbCES/SaKpcwpkCsmBu IJOHKVfNu8ASoE0s0xFQAvjdPTQ6PwAsa95He/jWimgw0XzV0kaC6GU2wHYW1N2pUVBU 9cEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=lc0GIGYc7kKgVQcRu/Hyd3K9adVcqDy3EXyUdccW1xA=; b=gBCBwkMn0kIl80vN5WZJaTioBExh5DiC7PmJ9XDdYkz7WalKG4ZBA2qATJaYAF8ULD WJ3DwkMJvs3P9kK1fSi7EObPNaqhOnnS7lbj0jVHlrNYSiIIzDvta1HD1QhDCD38Tcis ECEX42nKV+XaFM6s2i3c7Z+oyc5XY/XqdNUeOFE7s5acL9R6FX6LCYeHZXy2jWXyyvcn 6LczikuaW0Tgm9GRQLkiY+44gyDFRPTXHMbNQoTEykeujedPJXwoPYZBLKgQGuok8Ph9 72br6M3+Lzjf/SA82x9qJ0kr1SXJdj7tx7M/dT24eIclBla2MIqw+fdC54DNxPv3/xgF wz5w== X-Gm-Message-State: AOAM532n2ADCIiXGDdh0FBwZwjmxFdxrC2K03q3Su2r5iosA96fFQH95 z1jum4e7832L0MiAPz+oEDNN+5gE4COn/w== X-Google-Smtp-Source: ABdhPJxQj78I5J0r5rlEEjs4IpkGqA2HrPCpKTZ5K5LoFkWfRKSFVoYU2K9H1Ord/mfj6OdShCh/lg== X-Received: by 2002:a0c:e70f:: with SMTP id d15mr10768142qvn.47.1627801166429; Sat, 31 Jul 2021 23:59:26 -0700 (PDT) Received: from localhost.localdomain (dsl-10-135-95.b2b2c.ca. [72.10.135.95]) by smtp.gmail.com with ESMTPSA id d16sm2834823qtj.69.2021.07.31.23.59.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 31 Jul 2021 23:59:26 -0700 (PDT) From: Maxim Cournoyer To: 47849@debbugs.gnu.org Subject: [PATCH v3 3/3] services: Add a service for Jami. Date: Sun, 1 Aug 2021 02:58:57 -0400 Message-Id: <20210801065857.27657-4-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210801065857.27657-1-maxim.cournoyer@gmail.com> References: <20210801065857.27657-1-maxim.cournoyer@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Debbugs-Envelope-To: 47849 Cc: Maxime Devos , Maxim Cournoyer X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Maxime Devos Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" * gnu/services/telephony.scm (string-or-computed-file?) (string-list?, account-fingerprint-list?): New procedures. (maybe-string-list, maybe-account-fingerprint-list) (maybe-boolean, maybe-string, jami-account-list): New configuration field types. (serialize-string-list, serialize-boolean, serialize-string) (jami-account, jami-account->alist, jami-configuration) (jami-account-list?, jami-account-list-maybe): New procedures. (%jami-accounts): New variable. (jami-configuration->command-line-arguments): New procedure. (jami-dbus-session-activation, jami-shepherd-services): New procedures. (jami-service-type): New variable. * gnu/build/jami-service.scm: New file. * gnu/tests/data/jami-dummy-account.dat: Likewise. * gnu/tests/telephony.scm: Likewise. * gnu/local.mk (GNU_SYSTEM_MODULES): Register them. * Makefile.am (SCM_TESTS): Register the test file. (dist_patch_DATA): Register the new data file. * doc/guix.texi (Telephony Services): Document it. --- Makefile.am | 1 + doc/guix.texi | 264 ++++++++++ gnu/build/jami-service.scm | 587 ++++++++++++++++++++++ gnu/local.mk | 5 +- gnu/services/telephony.scm | 684 +++++++++++++++++++++++++- gnu/tests/data/jami-dummy-account.dat | 392 +++++++++++++++ gnu/tests/telephony.scm | 366 ++++++++++++++ tests/services/telephony.scm | 446 +++++++++++++++++ 8 files changed, 2742 insertions(+), 3 deletions(-) create mode 100644 gnu/build/jami-service.scm create mode 100644 gnu/tests/data/jami-dummy-account.dat create mode 100644 gnu/tests/telephony.scm create mode 100644 tests/services/telephony.scm diff --git a/Makefile.am b/Makefile.am index d5ec909213..5542aa1c56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -489,6 +489,7 @@ SCM_TESTS = \ tests/services/file-sharing.scm \ tests/services/configuration.scm \ tests/services/linux.scm \ + tests/services/telephony.scm \ tests/sets.scm \ tests/size.scm \ tests/status.scm \ diff --git a/doc/guix.texi b/doc/guix.texi index 2298d512a1..c931cbeb93 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -22526,6 +22526,270 @@ and Error. @node Telephony Services @subsection Telephony Services +@cindex telephony, services +The @code{(gnu services telephony)} module contains Guix service +definitions for telephony services. Currently it provides the following +services: + +@subsubheading Jami + +@cindex jami, service + +This section describes how to configure a Jami server that can be used +to host video (or audio) conferences, among other uses. The following +example demonstrates how to specify Jami account archives (backups) to +be provisioned automatically: + +@lisp +(service jami-service-type + (jami-configuration + (accounts + (list (jami-account + (archive "/etc/jami/unencrypted-account-1.gz")) + (jami-account + (archive "/etc/jami/unencrypted-account-2.gz")))))) +@end lisp + +When the accounts field is specified, the Jami account files of the +service found under @file{/var/lib/jami} are recreated every time the +service starts. + +Jami accounts and their corresponding backup archives can be generated +using either the @code{jami-qt} or @code{jami-gnome} Jami clients. The +accounts should not be password-protected, but it is wise to ensure +their files are only readable by @samp{root}. + +The next example shows how to declare that only some contacts should be +allowed to communicate with a given account: + +@lisp +(service jami-service-type + (jami-configuration + (accounts + (list (jami-account + (archive "/etc/jami/unencrypted-account-1.gz") + (peer-discovery? #t) + (rendezvous-point? #t) + (allowed-contacts + '("1dbcb0f5f37324228235564b79f2b9737e9a008f" + "2dbcb0f5f37324228235564b79f2b9737e9a008f"))))))) +@end lisp + +In this mode, only the declared @code{allowed-contacts} can initiate +communication with the Jami account. This can be used, for example, +with rendezvous point accounts to create a private video conferencing +space. + +To put the system administrator in full control of the conferences +hosted on their system, the Jami service supports the following actions: + +@example sh +herd doc jami list-actions jami +(list-accounts + list-account-details + list-banned-contacts + list-contacts + list-moderators + add-moderator + ban-contact + enable-account + disable-account) +@end example + +The above actions aim to provide the most valuable actions for +moderation purposes, not to cover the whole Jami API. Users wanting to +interact with the Jami daemon from Guile may be interested in +experimenting with the @code{(gnu build jami-service)} module, which +powers the above Shepherd actions. + +@c TODO: This should be auto-generated from the doc already defined on +@c the shepherd-actions themselves in (gnu services telephony). +The @code{add-moderator} and @code{ban-contact} actions accept a contact +@emph{fingerprint} (40 characters long hash) as first argument and an +account fingerprint or username as second argument: + +@example sh +# herd add-moderator jami 1dbcb0f5f37324228235564b79f2b9737e9a008f \ + f3345f2775ddfe07a4b0d95daea111d15fbc1199 + +# herd list-moderators jami +Moderators for account f3345f2775ddfe07a4b0d95daea111d15fbc1199: + - 1dbcb0f5f37324228235564b79f2b9737e9a008f + +@end example + +In the case of @code{ban-contact}, the second username argument is +optional; when omitted, the account is banned from all Jami accounts: + +@example sh +# herd ban-contact jami 1dbcb0f5f37324228235564b79f2b9737e9a008f + +# herd list-banned-contacts jami +Banned contacts for account f3345f2775ddfe07a4b0d95daea111d15fbc1199: + - 1dbcb0f5f37324228235564b79f2b9737e9a008f + +@end example + +Banned contacts are also stripped from their moderation privileges. + +The @code{disable-account} action allows to completely disconnect an +account from the network, making it unreachable, while +@code{enable-account} does the inverse. They accept a single account +username or fingerprint as first argument: + +@example sh +# herd disable-account jami f3345f2775ddfe07a4b0d95daea111d15fbc1199 + +# herd list-accounts jami +The following Jami accounts are available: + - f3345f2775ddfe07a4b0d95daea111d15fbc1199 (dummy) [disabled] + +@end example + +The @code{list-account-details} action prints the detailed parameters of +each accounts in the Recutils format, which means the @command{recsel} +command can be used to select accounts of interest (@pxref{Selection +Expressions,,,recutils, GNU recutils manual}). Note that period +characters (@samp{.}) found in the account parameter keys are mapped to +underscores (@samp{_}) in the output, to meet the requirements of the +Recutils format. The following example shows how to print the account +fingerprints for all accounts operating in the rendezvous point mode: + +@example sh +# herd list-account-details jami | \ + recsel -p Account.username -e 'Account.rendezVous ~ "true"' +Account_username: f3345f2775ddfe07a4b0d95daea111d15fbc1199 +@end example + +The remaining actions should be self-explanatory. + +The complete set of available configuration options is detailed below. + +@c TODO: Ideally, the following fragments would be auto-generated at +@c build time, so that they needn't be manually duplicated. +@c Auto-generated via (configuration->documentation 'jami-configuration) +Available @code{jami-configuration} fields are: + +@deftypevr {@code{jami-configuration} parameter} package jamid +The Jami daemon package to use. + +@end deftypevr + +@deftypevr {@code{jami-configuration} parameter} package dbus +The D-Bus package to use to start the required D-Bus session. + +@end deftypevr + +@deftypevr {@code{jami-configuration} parameter} package nss-certs +The nss-certs package to use to provide TLS certificates. + +@end deftypevr + +@deftypevr {@code{jami-configuration} parameter} boolean enable-logging? +Whether to enable logging to syslog. + +Defaults to @samp{#t}. + +@end deftypevr + +@deftypevr {@code{jami-configuration} parameter} boolean debug? +Whether to enable debug level messages. + +Defaults to @samp{#f}. + +@end deftypevr + +@deftypevr {@code{jami-configuration} parameter} boolean auto-answer? +Whether to force automatic answer to incoming calls. + +Defaults to @samp{#f}. + +@end deftypevr + +@deftypevr {@code{jami-configuration} parameter} maybe-jami-account-list accounts +A list of Jami accounts to be (re-)provisioned every time the Jami +daemon service starts. When providing this field, the account +directories under @file{/var/lib/jami/} are recreated every time the +service starts, ensuring a consistent state. + +Defaults to @samp{disabled}. + +@end deftypevr + +@c Auto-generated via (configuration->documentation 'jami-account) +Available @code{jami-account} fields are: + +@deftypevr {@code{jami-account} parameter} string-or-computed-file archive +The account archive (backup) file name of the account. This is used to +provision the account when the service starts. The account archive +should @emph{not} be encrypted. It is highly recommended to make it +readable only to the @samp{root} user (i.e., not in the store), to guard +against leaking the secret key material of the Jami account it contains. + +@end deftypevr + +@deftypevr {@code{jami-account} parameter} maybe-account-fingerprint-list allowed-contacts +The list of allowed contacts for the account, entered as their 40 +characters long fingerprint. Messages or calls from accounts not in +that list will be rejected. When unspecified, the configuration of the +account archive is used as-is with respect to contacts and public +inbound calls/messaging allowance, which typically defaults to allow any +contact to communicate with the account. + +Defaults to @samp{disabled}. + +@end deftypevr + +@deftypevr {@code{jami-account} parameter} maybe-account-fingerprint-list moderators +The list of contacts that should have moderation privileges (to ban, +mute, etc. other users) in rendezvous conferences, entered as their 40 +characters long fingerprint. When unspecified, the configuration of the +account archive is used as-is with respect to moderation, which +typically defaults to allow anyone to moderate. + +Defaults to @samp{disabled}. + +@end deftypevr + +@deftypevr {@code{jami-account} parameter} maybe-boolean rendezvous-point? +Whether the account should operate in the rendezvous mode. In this +mode, all the incoming audio/video calls are mixed into a conference. +When left unspecified, the value from the account archive prevails. + +Defaults to @samp{disabled}. + +@end deftypevr + +@deftypevr {@code{jami-account} parameter} maybe-boolean peer-discovery? +Whether peer discovery should be enabled. Peer discovery is used to +discover other OpenDHT nodes on the local network, which can be useful +to maintain communication between devices on such network even when the +connection to the the Internet has been lost. When left unspecified, +the value from the account archive prevails. + +Defaults to @samp{disabled}. + +@end deftypevr + +@deftypevr {@code{jami-account} parameter} maybe-string-list bootstrap-hostnames +A list of hostnames or IPs pointing to OpenDHT nodes, that should be +used to initially join the OpenDHT network. When left unspecified, the +value from the account archive prevails. + +Defaults to @samp{disabled}. + +@end deftypevr + +@deftypevr {@code{jami-account} parameter} maybe-string name-server-uri +The URI of the name server to use, that can be used to retrieve the +account fingerprint for a registered username. + +Defaults to @samp{disabled}. + +@end deftypevr + +@subsubheading Murmur (VoIP server) + @cindex Murmur (VoIP server) @cindex VoIP server This section describes how to set up and run a Murmur server. Murmur is diff --git a/gnu/build/jami-service.scm b/gnu/build/jami-service.scm new file mode 100644 index 0000000000..bb43b578f9 --- /dev/null +++ b/gnu/build/jami-service.scm @@ -0,0 +1,587 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Maxim Cournoyer +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +;;; Commentary: +;;; +;;; This module contains helpers used as part of the jami-service-type +;;; definition. +;;; +;;; Code: + +(define-module (gnu build jami-service) + #:use-module (ice-9 format) + #:use-module (ice-9 match) + #:use-module (ice-9 peg) + #:use-module (ice-9 rdelim) + #:use-module (ice-9 regex) + #:use-module (rnrs io ports) + #:autoload (shepherd service) (fork+exec-command) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:export (account-fingerprint? + account-details->recutil + get-accounts + get-usernames + set-account-details + add-account + account->username + username->account + username->contacts + enable-account + disable-account + + add-contact + remove-contact + + set-all-moderators + set-moderator + username->all-moderators? + username->moderators + + dbus-available-services + dbus-service-available? + + %send-dbus-binary + %send-dbus-bus + %send-dbus-user + %send-dbus-group + %send-dbus-debug + send-dbus + + with-retries)) + +;;; +;;; Utilities. +;;; + +(define-syntax-rule (with-retries n delay body ...) + "Retry the code in BODY up to N times until it doesn't raise an exception +nor return #f, else raise an error. A delay of DELAY seconds is inserted +before each retry." + (let loop ((attempts 0)) + (catch #t + (lambda () + (let ((result (begin body ...))) + (if (not result) + (error "failed attempt" attempts) + result))) + (lambda args + (if (< attempts n) + (begin + (sleep delay) ;else wait and retry + (loop (+ 1 attempts))) + (error "maximum number of retry attempts reached" + body ... args)))))) + +(define (alist->list alist) + "Flatten ALIST into a list." + (append-map (match-lambda + (() '()) + ((key . value) + (list key value))) + alist)) + +(define account-fingerprint-rx (make-regexp "[0-9A-f]{40}")) + +(define (account-fingerprint? val) + "A Jami account fingerprint is 40 characters long and only contains +hexadecimal characters." + (and (string? val) + (regexp-exec account-fingerprint-rx val))) + + +;;; +;;; D-Bus reply parser. +;;; + +(define (parse-dbus-reply reply) + "Return the parse tree of REPLY, a string returned by the 'dbus-send' +command." + ;; Refer to 'man 1 dbus-send' for the grammar reference. Note that the + ;; format of the replies doesn't match the format of the input, which is the + ;; one documented, but it gives an idea. For an even better reference, see + ;; the `print_iter' procedure of the 'dbus-print-message.c' file from the + ;; 'dbus' package sources. + (define-peg-string-patterns + "contents <- header (item / container (item / container*)?) + item <-- WS type WS value NL + container <- array / dict / variant + array <-- array-start (item / container)* array-end + dict <-- array-start dict-entry* array-end + dict-entry <-- dict-entry-start item item dict-entry-end + variant <-- variant-start item + type <-- 'string' / 'int16' / 'uint16' / 'int32' / 'uint32' / 'int64' / + 'uint64' / 'double' / 'byte' / 'boolean' / 'objpath' + value <-- (!NL .)* NL + header < (!NL .)* NL + variant-start < WS 'variant' + array-start < WS 'array [' NL + array-end < WS ']' NL + dict-entry-start < WS 'dict entry(' NL + dict-entry-end < WS ')' NL + DQ < '\"' + WS < ' '* + NL < '\n'*") + + (peg:tree (match-pattern contents reply))) + +(define (strip-quotes text) + "Strip the leading and trailing double quotes (\") characters from TEXT." + (let* ((text* (if (string-prefix? "\"" text) + (string-drop text 1) + text)) + (text** (if (string-suffix? "\"" text*) + (string-drop-right text* 1) + text*))) + text**)) + +(define (deserialize-item item) + "Return the value described by the ITEM parse tree as a Guile object." + ;; Strings are printed wrapped in double quotes (see the print_iter + ;; procedure in dbus-print-message.c). + (match item + (('item ('type "string") ('value value)) + (strip-quotes value)) + (('item ('type "boolean") ('value value)) + (if (string=? "true" value) + #t + #f)) + (('item _ ('value value)) + value))) + +(define (serialize-boolean bool) + "Return the serialized format expected by dbus-send for BOOL." + (format #f "boolean:~:[false~;true~]" bool)) + +(define (dict->alist dict-parse-tree) + "Translate a dict parse tree to an alist." + (define (tuples->alist tuples) + (map (lambda (x) (apply cons x)) tuples)) + + (match dict-parse-tree + ('dict + '()) + (('dict ('dict-entry keys values) ...) + (let ((keys* (map deserialize-item keys)) + (values* (map deserialize-item values))) + (tuples->alist (zip keys* values*)))))) + +(define (array->list array-parse-tree) + "Translate an array parse tree to a list." + (match array-parse-tree + ('array + '()) + (('array items ...) + (map deserialize-item items)))) + + +;;; +;;; Low-level, D-Bus-related procedures. +;;; + +;;; The following parameters are used in the jami-service-type service +;;; definition to conveniently customize the behavior of the send-dbus helper, +;;; even when called indirectly. +(define %send-dbus-binary (make-parameter "dbus-send")) +(define %send-dbus-bus (make-parameter #f)) +(define %send-dbus-user (make-parameter #f)) +(define %send-dbus-group (make-parameter #f)) +(define %send-dbus-debug (make-parameter #f)) + +(define* (send-dbus #:key service path interface method + bus + dbus-send + user group + timeout + arguments) + "Return the response of DBUS-SEND, else raise an error. Unless explicitly +provided, DBUS-SEND takes the value of the %SEND-DBUS-BINARY parameter. BUS +can be used to specify the bus address, such as 'unix:path=/var/run/jami/bus'. +Alternatively, the %SEND-DBUS-BUS parameter can be used. ARGUMENTS can be +used to pass input values to a D-Bus method call. TIMEOUT is the amount of +time to wait for a reply in milliseconds before giving up with an error. USER +and GROUP allow choosing under which user/group the DBUS-SEND command is +executed. Alternatively, the %SEND-DBUS-USER and %SEND-DBUS-GROUP parameters +can be used instead." + (let* ((command `(,@(if dbus-send + (list dbus-send) + (list (%send-dbus-binary))) + ,@(if (or bus (%send-dbus-bus)) + (list (string-append "--bus=" + (or bus (%send-dbus-bus)))) + '()) + "--print-reply" + ,@(if timeout + (list (format #f "--reply-timeout=~d" timeout)) + '()) + ,(string-append "--dest=" service) ;e.g., cx.ring.Ring + ,path ;e.g., /cx/ring/Ring/ConfigurationManager + ,(string-append interface "." method) + ,@(or arguments '()))) + (temp-port (mkstemp! (string-copy "/tmp/dbus-send-output-XXXXXXX"))) + (temp-file (port-filename temp-port))) + (dynamic-wind + (lambda () + (let* ((uid (or (and=> (or user (%send-dbus-user)) + (compose passwd:uid getpwnam)) -1)) + (gid (or (and=> (or group (%send-dbus-group)) + (compose group:gid getgrnam)) -1))) + (chown temp-port uid gid))) + (lambda () + (let ((pid (fork+exec-command command + #:user (or user (%send-dbus-user)) + #:group (or group (%send-dbus-group)) + #:log-file temp-file))) + (match (waitpid pid) + ((_ . status) + (let ((exit-status (status:exit-val status)) + (output (call-with-port temp-port get-string-all))) + (if (= 0 exit-status) + output + (error "the send-dbus command exited with: " + command exit-status output))))))) + (lambda () + (false-if-exception (delete-file temp-file)))))) + +(define (parse-account-ids reply) + "Return the Jami account IDs from REPLY, which is assumed to be the output +of the Jami D-Bus `getAccountList' method." + (array->list (parse-dbus-reply reply))) + +(define (parse-account-details reply) + "Parse REPLY, which is assumed to be the output of the Jami D-Bus +`getAccountDetails' method, and return its content as an alist." + (dict->alist (parse-dbus-reply reply))) + +(define (parse-contacts reply) + "Parse REPLY, which is assumed to be the output of the Jamid D-Bus +`getContacts' method, and return its content as an alist." + (match (parse-dbus-reply reply) + ('array + '()) + (('array dicts ...) + (map dict->alist dicts)))) + + +;;; +;;; Higher-level, D-Bus-related procedures. +;;; + +(define (validate-fingerprint fingerprint) + "Validate that fingerprint is 40 characters long." + (unless (account-fingerprint? fingerprint) + (error "Account fingerprint is not valid:" fingerprint))) + +(define (dbus-available-services) + "Return the list of available (acquired) D-Bus services." + (let ((reply (parse-dbus-reply + (send-dbus #:service "org.freedesktop.DBus" + #:path "/org/freedesktop/DBus" + #:interface "org.freedesktop.DBus" + #:method "ListNames")))) + ;; Remove entries such as ":1.7". + (remove (cut string-prefix? ":" <>) + (array->list reply)))) + +(define (dbus-service-available? service) + "Predicate to check for the D-Bus SERVICE availability." + (member service (dbus-available-services))) + +(define* (send-dbus/configuration-manager #:key method arguments timeout) + "Query the Jami D-Bus ConfigurationManager service." + (send-dbus #:service "cx.ring.Ring" + #:path "/cx/ring/Ring/ConfigurationManager" + #:interface "cx.ring.Ring.ConfigurationManager" + #:method method + #:arguments arguments + #:timeout timeout)) + +;;; The following methods are for internal use; they make use of the account +;;; ID, an implementation detail of Jami the user should not need to be +;;; concerned with. +(define (get-account-ids) + "Return the available Jami account identifiers (IDs). Account IDs are an +implementation detail used to identify the accounts in Jami." + (parse-account-ids + (send-dbus/configuration-manager #:method "getAccountList"))) + +(define (id->account-details id) + "Retrieve the account data associated with the given account ID." + (parse-account-details + (send-dbus/configuration-manager + #:method "getAccountDetails" + #:arguments (list (string-append "string:" id))))) + +(define (id->volatile-account-details id) + "Retrieve the account data associated with the given account ID." + (parse-account-details + (send-dbus/configuration-manager + #:method "getVolatileAccountDetails" + #:arguments (list (string-append "string:" id))))) + +(define (id->account id) + "Retrieve the complete account data associated with the given account ID." + (append (id->volatile-account-details id) + (id->account-details id))) + +(define %username-to-id-cache #f) + +(define (invalidate-username-to-id-cache!) + (set! %username-to-id-cache #f)) + +(define (username->id username) + "Return the first account ID corresponding to USERNAME." + (unless (assoc-ref %username-to-id-cache username) + (set! %username-to-id-cache + (append-map + (lambda (id) + (let* ((account (id->account id)) + (username (assoc-ref account "Account.username")) + (registered-name (assoc-ref account + "Account.registeredName"))) + `(,@(if username + (list (cons username id)) + '()) + ,@(if registered-name + (list (cons registered-name id)) + '())))) + (get-account-ids)))) + (or (assoc-ref %username-to-id-cache username) + (let ((message (format #f "Could not retrieve a local account ID\ + for ~:[username~;fingerprint~]" (account-fingerprint? username)))) + (error message username)))) + +(define (account->username account) + "Return USERNAME, the registered username associated with ACCOUNT, else its +public key fingerprint." + (or (assoc-ref account "Account.registeredName") + (assoc-ref account "Account.username"))) + +(define (id->username id) + "Return USERNAME, the registered username associated with ID, else its +public key fingerprint, else #f." + (account->username (id->account id))) + +(define (get-accounts) + "Return the list of all accounts, as a list of alists." + (map id->account (get-account-ids))) + +(define (get-usernames) + "Return the list of the usernames associated with the present accounts." + (map account->username (get-accounts))) + +(define (username->account username) + "Return the first account associated with USERNAME, else #f. +USERNAME can be either the account 40 characters public key fingerprint or a +registered username." + (find (lambda (account) + (member username + (list (assoc-ref account "Account.username") + (assoc-ref account "Account.registeredName")))) + (get-accounts))) + +(define (add-account archive) + "Import the Jami account ARCHIVE and return its account ID. The archive +should *not* be encrypted with a password. Return the username associated +with the account." + (invalidate-username-to-id-cache!) + (let ((reply (send-dbus/configuration-manager + #:method "addAccount" + #:arguments (list (string-append + "dict:string:string:Account.archivePath," + archive + ",Account.type,RING"))))) + ;; The account information takes some time to be populated. + (let ((id (deserialize-item (parse-dbus-reply reply)))) + (with-retries 20 1 + (let ((username (id->username id))) + (if (string-null? username) + #f + username)))))) + +(define (remove-account username) + "Delete the Jami account associated with USERNAME, the account 40 characters +fingerprint or a registered username." + (let ((id (username->id username))) + (send-dbus/configuration-manager + #:method "removeAccount" + #:arguments (list (string-append "string:" id)))) + (invalidate-username-to-id-cache!)) + +(define* (username->contacts username) + "Return the contacts associated with the account of USERNAME as two values; +the first one being the regular contacts and the second one the banned +contacts. USERNAME can be either the account 40 characters public key +fingerprint or a registered username. The contacts returned are represented +using their 40 characters fingerprint." + (let* ((id (username->id username)) + (reply (send-dbus/configuration-manager + #:method "getContacts" + #:arguments (list (string-append "string:" id)))) + (all-contacts (parse-contacts reply)) + (banned? (lambda (contact) + (and=> (assoc-ref contact "banned") + (cut string=? "true" <>)))) + (banned (filter banned? all-contacts)) + (not-banned (filter (negate banned?) all-contacts)) + (fingerprint (cut assoc-ref <> "id"))) + (values (map fingerprint not-banned) + (map fingerprint banned)))) + +(define* (remove-contact contact username #:key ban?) + "Remove CONTACT, the 40 characters public key fingerprint of a contact, from +the account associated with USERNAME (either a fingerprint or a registered +username). When BAN? is true, also mark the contact as banned." + (validate-fingerprint contact) + (let ((id (username->id username))) + (send-dbus/configuration-manager + #:method "removeContact" + #:arguments (list (string-append "string:" id) + (string-append "string:" contact) + (serialize-boolean ban?))))) + +(define (add-contact contact username) + "Add CONTACT, the 40 characters public key fingerprint of a contact, to the +account of USERNAME (either a fingerprint or a registered username)." + (validate-fingerprint contact) + (let ((id (username->id username))) + (send-dbus/configuration-manager + #:method "addContact" + #:arguments (list (string-append "string:" id) + (string-append "string:" contact))))) + +(define* (set-account-details details username #:key timeout) + "Set DETAILS, an alist containing the key value pairs to set for the account +of USERNAME, a registered username or account fingerprint. The value of the +parameters not provided are unchanged. TIMEOUT is a value in milliseconds to +pass to the `send-dbus/configuration-manager' procedure." + (let* ((id (username->id username)) + (current-details (id->account-details id)) + (updated-details (map (match-lambda + ((key . value) + (or (and=> (assoc-ref details key) + (cut cons key <>)) + (cons key value)))) + current-details)) + ;; dbus-send does not permit sending null strings (it throws a + ;; "malformed dictionary" error). Luckily they seem to have the + ;; semantic of "default account value" in Jami; so simply drop them. + (updated-details* (remove (match-lambda + ((_ . value) + (string-null? value))) + updated-details))) + (send-dbus/configuration-manager + #:timeout timeout + #:method "setAccountDetails" + #:arguments + (list (string-append "string:" id) + (string-append "dict:string:string:" + (string-join (alist->list updated-details*) + ",")))))) + +(define (set-all-moderators enabled? username) + "Set the 'AllModerators' property to enabled? for the account of USERNAME, a +registered username or account fingerprint." + (let ((id (username->id username))) + (send-dbus/configuration-manager + #:method "setAllModerators" + #:arguments + (list (string-append "string:" id) + (serialize-boolean enabled?))))) + +(define (username->all-moderators? username) + "Return the 'AllModerators' property for the account of USERNAME, a +registered username or account fingerprint." + (let* ((id (username->id username)) + (reply (send-dbus/configuration-manager + #:method "isAllModerators" + #:arguments + (list (string-append "string:" id))))) + (deserialize-item (parse-dbus-reply reply)))) + +(define (username->moderators username) + "Return the moderators for the account of USERNAME, a registered username or +account fingerprint." + (let* ((id (username->id username)) + (reply (send-dbus/configuration-manager + #:method "getDefaultModerators" + #:arguments + (list (string-append "string:" id))))) + (array->list (parse-dbus-reply reply)))) + +(define (set-moderator contact enabled? username) + "Set the moderator flag to ENABLED? for CONTACT, the 40 characters public +key fingerprint of a contact for the account of USERNAME, a registered +username or account fingerprint." + (validate-fingerprint contact) + (let* ((id (username->id username))) + (send-dbus/configuration-manager #:method "setDefaultModerator" + #:arguments + (list (string-append "string:" id) + (string-append "string:" contact) + (serialize-boolean enabled?))))) + +(define (disable-account username) + "Disable the account known by USERNAME, a registered username or account +fingerprint." + (set-account-details '(("Account.enable" . "false")) username + ;; Waiting for the reply on this command takes a very + ;; long time that trips the default D-Bus timeout value + ;; (25 s), for some reason. + #:timeout 60000)) + +(define (enable-account username) + "Enable the account known by USERNAME, a registered username or account +fingerprint." + (set-account-details '(("Account.enable" . "true")) username)) + + +;;; +;;; Presentation procedures. +;;; + +(define (.->_ text) + "Map each period character to underscore characters." + (string-map (match-lambda + (#\. #\_) + (c c)) + text)) + +(define (account-details->recutil account-details) + "Serialize the account-details alist into a recutil string. Period +characters in the keys are normalized to underscore to meet Recutils' format +requirements." + (define (pair->recutil-property pair) + (match pair + ((key . value) + (string-append (.->_ key) ": " value)))) + + (define sorted-account-details + ;; Have the account username, display name and alias appear first, for + ;; convenience. + (let ((first-items '("Account.username" + "Account.displayName" + "Account.alias"))) + (append (map (cut assoc <> account-details) first-items) + (fold alist-delete account-details first-items)))) + + (string-join (map pair->recutil-property sorted-account-details) "\n")) + +;; Local Variables: +;; eval: (put 'with-retries 'scheme-indent-function 2) +;; End: diff --git a/gnu/local.mk b/gnu/local.mk index c530507b1a..0f094e580b 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -685,6 +685,7 @@ GNU_SYSTEM_MODULES = \ %D%/build/chromium-extension.scm \ %D%/build/cross-toolchain.scm \ %D%/build/image.scm \ + %D%/build/jami-service.scm \ %D%/build/file-systems.scm \ %D%/build/hurd-boot.scm \ %D%/build/install.scm \ @@ -722,6 +723,7 @@ GNU_SYSTEM_MODULES = \ %D%/tests/security-token.scm \ %D%/tests/singularity.scm \ %D%/tests/ssh.scm \ + %D%/tests/telephony.scm \ %D%/tests/version-control.scm \ %D%/tests/virtualization.scm \ %D%/tests/web.scm @@ -1879,7 +1881,8 @@ dist_patch_DATA = \ %D%/packages/patches/ytnef-CVE-2021-3403.patch \ %D%/packages/patches/ytnef-CVE-2021-3404.patch \ %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch \ - %D%/packages/patches/zziplib-CVE-2018-16548.patch + %D%/packages/patches/zziplib-CVE-2018-16548.patch \ + %D%/tests/data/jami-dummy-account.dat MISC_DISTRO_FILES = \ %D%/packages/ld-wrapper.in diff --git a/gnu/services/telephony.scm b/gnu/services/telephony.scm index e1259cc2df..fd90840324 100644 --- a/gnu/services/telephony.scm +++ b/gnu/services/telephony.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 nee +;;; Copyright © 2021 Maxim Cournoyer ;;; ;;; This file is part of GNU Guix. ;;; @@ -17,16 +18,45 @@ ;;; along with GNU Guix. If not, see . (define-module (gnu services telephony) - #:use-module (gnu services) + #:use-module ((gnu build jami-service) #:select (account-fingerprint?)) + #:use-module ((gnu services) #:hide (delete)) + #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (gnu packages admin) + #:use-module (gnu packages certs) + #:use-module (gnu packages glib) + #:use-module (gnu packages jami) #:use-module (gnu packages telephony) #:use-module (guix records) + #:use-module (guix modules) + #:use-module (guix packages) #:use-module (guix gexp) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-2) + #:use-module (srfi srfi-26) + #:use-module (ice-9 format) #:use-module (ice-9 match) - #:export (murmur-configuration + #:export (jami-account + jami-account-archive + jami-account-allowed-contacts + jami-account-moderators + jami-account-rendezvous-point? + jami-account-discovery? + jami-account-bootstrap-uri + jami-account-name-server-uri + + jami-configuration + jami-configuration-jamid + jami-configuration-dbus + jami-configuration-enable-logging? + jami-configuration-debug? + jami-configuration-auto-answer? + jami-configuration-accounts + + jami-service-type + + murmur-configuration make-murmur-configuration murmur-configuration? murmur-configuration-package @@ -74,6 +104,652 @@ murmur-service-type)) + +;;; +;;; Jami daemon. +;;; + +;;; XXX: Passing a computed-file object as the account is used for tests. +(define (string-or-computed-file? val) + (or (string? val) + (computed-file? val))) + +(define (string-list? val) + (and (list? val) + (and-map string? val))) + +(define (account-fingerprint-list? val) + (and (list? val) + (and-map account-fingerprint? val))) + +(define-maybe string-list) + +(define-maybe/no-serialization account-fingerprint-list) + +(define-maybe boolean) + +(define-maybe string) + +;;; The following serializers are used to derive an account details alist from +;;; a record. +(define (serialize-string-list _ val) + (string-join val ";")) + +(define (serialize-boolean _ val) + (format #f "~:[false~;true~]" val)) + +(define (serialize-string _ val) + val) + +;;; Note: Serialization is used to produce an account details alist that can +;;; be passed to the SET-ACCOUNT-DETAILS procedure. Fields that do not map to +;;; a Jami account 'detail' should have their serialization disabled via the +;;; 'empty-serializer' procedure. +(define-configuration jami-account + (archive + (string-or-computed-file) + "The account archive (backup) file name of the account. This is used to +provision the account when the service starts. The account archive should +@emph{not} be encrypted. It is highly recommended to make it readable only to +the @samp{root} user (i.e., not in the store), to guard against leaking the +secret key material of the Jami account it contains." + empty-serializer) + (allowed-contacts + (maybe-account-fingerprint-list 'disabled) + "The list of allowed contacts for the account, entered as their 40 +characters long fingerprint. Messages or calls from accounts not in that list +will be rejected. When unspecified, the configuration of the account archive +is used as-is with respect to contacts and public inbound calls/messaging +allowance, which typically defaults to allow any contact to communicate with +the account." + empty-serializer) + (moderators + (maybe-account-fingerprint-list 'disabled) + "The list of contacts that should have moderation privileges (to ban, mute, +etc. other users) in rendezvous conferences, entered as their 40 characters +long fingerprint. When unspecified, the configuration of the account archive +is used as-is with respect to moderation, which typically defaults to allow +anyone to moderate." + empty-serializer) + ;; The serializable fields below are to be set with set-account-details. + (rendezvous-point? + (maybe-boolean 'disabled) + "Whether the account should operate in the rendezvous mode. In this mode, +all the incoming audio/video calls are mixed into a conference. When left +unspecified, the value from the account archive prevails.") + (peer-discovery? + (maybe-boolean 'disabled) + "Whether peer discovery should be enabled. Peer discovery is used to +discover other OpenDHT nodes on the local network, which can be useful to +maintain communication between devices on such network even when the +connection to the the Internet has been lost. When left unspecified, the +value from the account archive prevails.") + (bootstrap-hostnames + (maybe-string-list 'disabled) + "A list of hostnames or IPs pointing to OpenDHT nodes, that should be used +to initially join the OpenDHT network. When left unspecified, the value from +the account archive prevails.") + (name-server-uri + (maybe-string 'disabled) + "The URI of the name server to use, that can be used to retrieve the +account fingerprint for a registered username.")) + +(define (jami-account->alist jami-account-object) + "Serialize the JAMI-ACCOUNT object as an alist suitable to be passed to +SET-ACCOUNT-DETAILS." + (define (field-name->account-detail name) + (match name + ('rendezvous-point? "Account.rendezVous") + ('peer-discovery? "Account.peerDiscovery") + ('bootstrap-hostnames "Account.hostname") + ('name-server-uri "RingNS.uri") + (_ #f))) + + (filter-map (lambda (field) + (and-let* ((name (field-name->account-detail + (configuration-field-name field))) + (value ((configuration-field-serializer field) + name ((configuration-field-getter field) + jami-account-object))) + ;; The define-maybe default serializer produces an + ;; empty string for the 'disabled value. + (value* (if (string-null? value) + #f + value))) + (cons name value*))) + jami-account-fields)) + +(define (jami-account-list? val) + (and (list? val) + (and-map jami-account? val))) + +(define-maybe/no-serialization jami-account-list) + +(define-configuration/no-serialization jami-configuration + (jamid + (package libring) + "The Jami daemon package to use.") + (dbus + (package dbus) + "The D-Bus package to use to start the required D-Bus session.") + (nss-certs + (package nss-certs) + "The nss-certs package to use to provide TLS certificates.") + (enable-logging? + (boolean #t) + "Whether to enable logging to syslog.") + (debug? + (boolean #f) + "Whether to enable debug level messages.") + (auto-answer? + (boolean #f) + "Whether to force automatic answer to incoming calls.") + (accounts + (maybe-jami-account-list 'disabled) + "A list of Jami accounts to be (re-)provisioned every time the Jami daemon +service starts. When providing this field, the account directories under +@file{/var/lib/jami/} are recreated every time the service starts, ensuring a +consistent state.")) + +(define %jami-accounts + (list (user-group (name "jami") (system? #t)) + (user-account + (name "jami") + (group "jami") + (system? #t) + (comment "Jami daemon user") + (home-directory "/var/lib/jami")))) + +(define (jami-configuration->command-line-arguments config) + "Derive the command line arguments to used to launch the Jami daemon from +CONFIG, a object." + (match-record config + (jamid dbus enable-logging? debug? auto-answer?) + `(,(file-append jamid "/lib/ring/dring") + "--persistent" ;stay alive after client quits + ,@(if enable-logging? + '() ;logs go to syslog by default + (list "--console")) ;else stdout/stderr + ,@(if debug? + (list "--debug") + '()) + ,@(if auto-answer? + (list "--auto-answer") + '())))) + +(define (jami-dbus-session-activation config) + "Create a directory to hold the Jami D-Bus session socket." + (with-imported-modules (source-module-closure '((gnu build activation))) + #~(begin + (use-modules (gnu build activation)) + (let ((user (getpwnam "jami"))) + (mkdir-p/perms "/var/run/jami" user #o700))))) + +(define (jami-shepherd-services config) + "Return a running the Jami daemon." + (let* ((jamid (jami-configuration-jamid config)) + (nss-certs (jami-configuration-nss-certs config)) + (dbus (jami-configuration-dbus config)) + (dbus-daemon (file-append dbus "/bin/dbus-daemon")) + (dbus-send (file-append dbus "/bin/dbus-send")) + (accounts (jami-configuration-accounts config)) + (declarative-mode? (not (eq? 'disabled accounts)))) + + (with-imported-modules (source-module-closure + '((gnu build jami-service) + (gnu build shepherd) + (gnu system file-systems))) + + (define list-accounts-action + (shepherd-action + (name 'list-accounts) + (documentation "List the available Jami accounts. Return the account +details alists keyed by their account username.") + (procedure + #~(lambda _ + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + ;; Print the accounts summary or long listing, according to + ;; user-provided option. + (let* ((usernames (get-usernames)) + (accounts (map-in-order username->account usernames))) + (match accounts + (() ;empty list + (format #t "There is no Jami account available.~%")) + ((one two ...) + (format #t "The following Jami accounts are available:~%") + (for-each + (lambda (account) + (define fingerprint (assoc-ref account + "Account.username")) + (define human-friendly-name + (or (assoc-ref account + "Account.registeredName") + (assoc-ref account + "Account.displayName") + (assoc-ref account + "Account.alias"))) + (define disabled? + (and=> (assoc-ref account "Account.enable") + (cut string=? "false" <>))) + + (format #t " - ~a~@[ (~a)~] ~:[~;[disabled]~]~%" + fingerprint human-friendly-name disabled?)) + accounts) + (display "\n"))) + ;; Return the account-details-list alist. + (map cons usernames accounts))))))) + + (define list-account-details-action + (shepherd-action + (name 'list-account-details) + (documentation "Display the account details of the available Jami +accounts in the @code{recutils} format. Return the account details alists +keyed by their account username.") + (procedure + #~(lambda _ + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + (let* ((usernames (get-usernames)) + (accounts (map-in-order username->account usernames))) + (for-each (lambda (account) + (display (account-details->recutil account)) + (display "\n\n")) + accounts) + (map cons usernames accounts))))))) + + (define list-contacts-action + (shepherd-action + (name 'list-contacts) + (documentation "Display the contacts for each Jami account. Return +an alist containing the contacts keyed by the account usernames.") + (procedure + #~(lambda _ + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + (let* ((usernames (get-usernames)) + (contacts (map-in-order username->contacts usernames))) + (for-each (lambda (username contacts) + (format #t "Contacts for account ~a:~%" + username) + (format #t "~{ - ~a~%~}~%" contacts)) + usernames contacts) + (map cons usernames contacts))))))) + + (define list-moderators-action + (shepherd-action + (name 'list-moderators) + (documentation "Display the moderators for each Jami account. Return +an alist containing the moderators keyed by the account usernames.") + (procedure + #~(lambda _ + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + (let* ((usernames (get-usernames)) + (moderators (map-in-order username->moderators + usernames))) + (for-each + (lambda (username moderators) + (if (username->all-moderators? username) + (format #t "Anyone can moderate for account ~a~%" + username) + (begin + (format #t "Moderators for account ~a:~%" username) + (format #t "~{ - ~a~%~}~%" moderators)))) + usernames moderators) + (map cons usernames moderators))))))) + + (define add-moderator-action + (shepherd-action + (name 'add-moderator) + (documentation "Add a moderator for a given Jami account. The +MODERATOR contact must be given as its 40 characters fingerprint, while the +Jami account can be provided as its registered USERNAME or fingerprint. + +@example +herd add-moderator jami 1dbcb0f5f37324228235564b79f2b9737e9a008f username +@end example + +Return the moderators for the account known by USERNAME.") + (procedure + #~(lambda (_ moderator username) + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + (set-all-moderators #f username) + (add-contact moderator username) + (set-moderator moderator #t username) + (username->moderators username)))))) + + (define ban-contact-action + (shepherd-action + (name 'ban-contact) + (documentation "Ban a contact for a given or all Jami accounts, and +clear their moderator flag. The CONTACT must be given as its 40 characters +fingerprint, while the Jami account can be provided as its registered USERNAME +or fingerprint, or omitted. When the account is omitted, CONTACT is banned +from all accounts. + +@example +herd ban-contact jami 1dbcb0f5f37324228235564b79f2b9737e9a008f [username] +@end example") + (procedure + #~(lambda* (_ contact #:optional username) + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + (let ((usernames (or (and=> username list) + (get-usernames)))) + (for-each (lambda (username) + (set-moderator contact #f username) + (remove-contact contact username #:ban? #t)) + usernames))))))) + + (define list-banned-contacts-action + (shepherd-action + (name 'list-banned-contacts) + (documentation "List the banned contacts for each accounts. Return +an alist of the banned contacts, keyed by the account usernames.") + (procedure + #~(lambda _ + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + + (define banned-contacts + (let ((usernames (get-usernames))) + (map cons usernames + (map-in-order (lambda (x) + (receive (_ banned) + (username->contacts x) + banned)) + usernames)))) + + (for-each (match-lambda + ((username . banned) + (unless (null? banned) + (format #t "Banned contacts for account ~a:~%" + username) + (format #t "~{ - ~a~%~}~%" banned)))) + banned-contacts) + banned-contacts))))) + + (define enable-account-action + (shepherd-action + (name 'enable-account) + (documentation "Enable an account. It takes USERNAME as an argument, +either a registered username or the fingerprint of the account.") + (procedure + #~(lambda (_ username) + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + (enable-account username)))))) + + (define disable-account-action + (shepherd-action + (name 'disable-account) + (documentation "Disable an account. It takes USERNAME as an +argument, either a registered username or the fingerprint of the account.") + (procedure + #~(lambda (_ username) + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + (disable-account username)))))) + + (list (shepherd-service + (documentation "Run a D-Bus session for the Jami daemon.") + (provision '(jami-dbus-session)) + (modules `((gnu build shepherd) + (gnu build jami-service) + (gnu system file-systems) + ,@%default-modules)) + ;; The requirement on dbus-system is to ensure other required + ;; activation for D-Bus, such as a /etc/machine-id file. + (requirement '(dbus-system syslogd)) + (start + #~(lambda args + (define pid + ((make-forkexec-constructor/container + (list #$dbus-daemon "--session" + "--address=unix:path=/var/run/jami/bus" + "--nofork" "--syslog-only" "--nopidfile") + #:mappings (list (file-system-mapping + (source "/dev/log") ;for syslog + (target source)) + (file-system-mapping + (source "/var/run/jami") + (target source) + (writable? #t))) + #:user "jami" + #:group "jami" + #:environment-variables + ;; This is so that the cx.ring.Ring service D-Bus + ;; definition is found by dbus-send. + (list (string-append "XDG_DATA_DIRS=" + #$jamid "/share"))))) + + ;; XXX: This manual synchronization probably wouldn't be + ;; needed if we were using a PID file, but providing it via a + ;; customized config file with would not override + ;; the one inherited from the base config of D-Bus. + (let ((sock (socket PF_UNIX SOCK_STREAM 0))) + (with-retries 20 1 (catch 'system-error + (lambda () + (connect sock AF_UNIX + "/var/run/jami/bus") + (close-port sock) + #t) + (lambda args + #f)))) + + pid)) + (stop #~(make-kill-destructor))) + + (shepherd-service + (documentation "Run the Jami daemon.") + (provision '(jami)) + (actions (list list-accounts-action + list-account-details-action + list-contacts-action + list-moderators-action + add-moderator-action + ban-contact-action + list-banned-contacts-action + enable-account-action + disable-account-action)) + (requirement '(jami-dbus-session)) + (modules `((ice-9 format) + (ice-9 ftw) + (ice-9 match) + (ice-9 receive) + (srfi srfi-1) + (srfi srfi-26) + (gnu build jami-service) + (gnu build shepherd) + (gnu system file-systems) + ,@%default-modules)) + (start + #~(lambda args + (define (delete-file-recursively/safe file) + ;; Ensure we're not deleting things outside of + ;; /var/lib/jami. This prevents a possible attack in case + ;; the daemon is compromised and an attacker gains write + ;; access to /var/lib/jami. + (let ((parent-directory (dirname file))) + (if (eq? 'symlink (stat:type (stat parent-directory))) + (error "abnormality detected; unexpected symlink found at" + parent-directory) + (delete-file-recursively file)))) + + (when #$declarative-mode? + ;; Clear the Jami configuration and accounts, to enforce the + ;; declared state. + (catch #t + (lambda () + (for-each (cut delete-file-recursively/safe <>) + '("/var/lib/jami/.cache/jami" + "/var/lib/jami/.config/jami" + "/var/lib/jami/.local/share/jami" + "/var/lib/jami/accounts"))) + (lambda args + #t)) + ;; Copy the Jami account archives from somewhere readable + ;; by root to a place only the jami user can read. + (let* ((accounts-dir "/var/lib/jami/accounts/") + (pwd (getpwnam "jami")) + (user (passwd:uid pwd)) + (group (passwd:gid pwd))) + (mkdir-p accounts-dir) + (chown accounts-dir user group) + (for-each (lambda (f) + (let ((dest (string-append accounts-dir + (basename f)))) + (copy-file f dest) + (chown dest user group))) + '#$(and declarative-mode? + (map jami-account-archive accounts))))) + + ;; Start the daemon. + (define daemon-pid + ((make-forkexec-constructor/container + '#$(jami-configuration->command-line-arguments config) + #:mappings + (list (file-system-mapping + (source "/dev/log") ;for syslog + (target source)) + (file-system-mapping + (source "/var/lib/jami") + (target source) + (writable? #t)) + (file-system-mapping + (source "/var/run/jami") + (target source) + (writable? #t)) + ;; Expose TLS certificates for GnuTLS. + (file-system-mapping + (source #$(file-append nss-certs "/etc/ssl/certs")) + (target "/etc/ssl/certs"))) + #:user "jami" + #:group "jami" + #:environment-variables + (list (string-append "DBUS_SESSION_BUS_ADDRESS=" + "unix:path=/var/run/jami/bus") + ;; Expose TLS certificates for OpenSSL. + "SSL_CERT_DIR=/etc/ssl/certs")))) + + (parameterize ((%send-dbus-binary #$dbus-send) + (%send-dbus-bus "unix:path=/var/run/jami/bus") + (%send-dbus-user "jami") + (%send-dbus-group "jami")) + + ;; Wait until the service name has been acquired by D-Bus. + (with-retries 20 1 + (dbus-service-available? "cx.ring.Ring")) + + (when #$declarative-mode? + ;; Provision the accounts via the D-Bus API of the daemon. + (let* ((jami-account-archives + (map (cut string-append + "/var/lib/jami/accounts/" <>) + (scandir "/var/lib/jami/accounts/" + (lambda (f) + (not (member f '("." ".."))))))) + (usernames (map-in-order (cut add-account <>) + jami-account-archives))) + + (define (archive-name->username archive) + (list-ref + usernames + (list-index (lambda (f) + (string-suffix? (basename archive) f)) + jami-account-archives))) + + (for-each + (lambda (archive allowed-contacts moderators + account-details) + (let ((username (archive-name->username + archive))) + (when (not (eq? 'disabled allowed-contacts)) + ;; Reject calls from unknown contacts. + (set-account-details + '(("DHT.PublicInCalls" . "false")) username) + ;; Remove all contacts. + (for-each (cut remove-contact <> username) + (username->contacts username)) + ;; Add allowed ones. + (for-each (cut add-contact <> username) + allowed-contacts)) + (when (not (eq? 'disabled moderators)) + ;; Disable the 'AllModerators' property. + (set-all-moderators #f username) + ;; Remove all moderators. + (for-each (cut set-moderator <> #f username) + (username->moderators username)) + ;; Add declared moderators. + (for-each (cut set-moderator <> #t username) + moderators)) + ;; Set the various account parameters. + (set-account-details account-details username))) + '#$(and declarative-mode? + (map-in-order (cut jami-account-archive <>) + accounts)) + '#$(and declarative-mode? + (map-in-order + (cut jami-account-allowed-contacts <>) + accounts)) + '#$(and declarative-mode? + (map-in-order (cut jami-account-moderators <>) + accounts)) + '#$(and declarative-mode? + (map-in-order jami-account->alist accounts)))))) + + ;; Finally, return the PID of the daemon process. + daemon-pid)) + (stop + #~(lambda (pid . args) + (kill pid SIGKILL) + ;; Wait for the process to exit; this prevents overlapping + ;; processes when issuing 'herd restart'. + (waitpid pid) + #f))))))) + +(define jami-service-type + (service-type + (name 'jami) + (default-value (jami-configuration)) + (extensions + (list (service-extension shepherd-root-service-type + jami-shepherd-services) + (service-extension account-service-type + (const %jami-accounts)) + (service-extension activation-service-type + jami-dbus-session-activation))) + (description "Run the Jami daemon (@command{dring}). This service is +geared toward the use case of hosting Jami rendezvous points over a headless +server. If you use Jami on your local machine, you may prefer to setup a user +Shepherd service for it instead; this way, the daemon will be shared via your +normal user D-Bus session bus."))) + + +;;; +;;; Murmur. +;;; + ;; https://github.com/mumble-voip/mumble/blob/master/scripts/murmur.ini (define-record-type* murmur-configuration @@ -305,3 +981,7 @@ suite.") (service-extension account-service-type murmur-accounts))) (default-value (murmur-configuration)))) + +;; Local Variables: +;; eval: (put 'with-retries 'scheme-indent-function 2) +;; End: diff --git a/gnu/tests/data/jami-dummy-account.dat b/gnu/tests/data/jami-dummy-account.dat new file mode 100644 index 0000000000..0e908396ca --- /dev/null +++ b/gnu/tests/data/jami-dummy-account.dat @@ -0,0 +1,392 @@ +;;; -*- mode: scheme; -*- +;;; JSON extracted from an actual Jami account and processed with +;;; Emacs/guile-json. +(define %jami-account-content-sexp + '(("RINGCAKEY" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQURBTkJna3F\ +oa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRQzBxWUozSkYvTzhQRGEKRnUwRnpRcHBCaD\ +gybGJMdURrNTlVU0I0MUJSaS9kdDZGV1BRN29YOVpsY25vNGZzM2dmUHQ0dU1hRVBkVFBGKwowbGN2Q\ +jc2cytQTEFlcjlOZGpVQzQ2ZXp0UnNiNE9aQXc4ZUk1M3EwSU04QWJFd0o0ZjllLzBmQUFueHgrK3Qw\ +CmZDeGV1YTBUaVBqVHBpZVJMNmpwQkd5UGI2Qk5pU2ViTkZCNzJOMTBnbzI4REVQYlhkNE9CNkN1blZ\ +5RGZKSU0KOC9PRy8rMndNamI4WkRwT3JrYy93U2ZHbnQyZXA3U0xKSkgwOFIzV1FKWklsSndrcGdLTH\ +FRakVwWFNpclN4dAozSkdtdXdBdE9LaXFFTXh1R043elV3ZlNINEtHdkRaUFNkZklZVXJ3eEp4aDJZZ\ +3lobG5RRC9SSnhRN3d4YlJBCjFhMUZVV0FzbDhLODk5cEtESk1GL09VOWZMRUx6QlViblpaRDRmSlg1\ +NmcyTlluUnJobS94NG9FbFk0MFNYMUUKcHYzb01hNnZrVGN5RjJnUFhKL2FkUVJoS0dFaGRjaHBpeDl\ +5UVphaDFCUFBGYW5jNzBMcjhOaDZJeHFNQ1hiMQozMG9vWHpWZmZNMVFOd28rL3hzRnBlRkRqUTAxQ0\ +9pdWZocitKREcyc0txb0o0V0JwYVhubWI1YXVrVWUvV1RKCjAxVmRyaEkvSVExd3V4QzNMMnpac3dVU\ +1NTaDk0aXg1M0hpU3pWbkI5UkxmaVhZUUVCcFEyNHVoRTdiYlo0bm0KZTczZC9zenpPTXMzYUt3OWtW\ +a2VLMTVtYWhSVWZjdEdhSVQxTkhGWUNYYXByaWExakdNdVpmSk1pSUtZUzNidQpMbUhZckF6dEptNDZ\ +0aHpjdnN3NHlhMnFoa2xUUlFJREFRQUJBb0lDQVFDaHZaUm85KzZ5aFhFTHZ6U3FXZHcxCkZGOERibG\ +hIMmhVWkNuV0kxMDM5SmdyRkxMczFSU1krSzg1aFZYMk9hV1VTNk44TmNCYzUyL1hrdFltS09HUFQKM\ +WZqMnE2M3pPcDNSSFdGNWVPMXhNeExRN3JZSDhqMGZZTFFTUytKemdwb3ZRVnJLSXkrb21JSSt3aUN6\ +R1laRApGQUM0ODJzL0J5MHdtRjVjdC9JTEdIeVY3ZXNVUlo1Vi9iL0ltQzUwQ1lDUWpQR2xBb3JkeUx\ +1MHp2NjZZUXc2CkQycTg0VHAyVUg3SExEVmhFNytUbDg4Q04xWll0VGtpSkthbkNpMFVmbStPKzJFM0\ +5HM01hajk1aDl2NktqYkoKUlkxeTNDRTVmQmkyUFNLbVVzRjN3SzdhbzJDRks5MTgybmlxL2FaNm5WO\ +Xc3NmVrRjhEOWUvS1pqUE5ZT0xkaApFczBSL2laV3RpbUx2RHdXQWNWNFNnSFFjNXJvNU9yOEFUS1ZK\ +VmlzZGFuWXkvdUhmVXZWN3U5cDVLK2E4SHU2CllabW13ZTh4bnF5M3V2M0VabE9LY20zTnZvWllVMnJ\ +HUUFQQW1sWWQ4WlRsZGxPa1JCSGxxYzllMmJuSnNTQW8KNUhhS0N3aDJsWmZpalVGNXFrMXNQcm1kN3\ +BlMld2VVV3QmVuSjJnS1ZoTE5VVGtHWmtTWGhzNlV3WWRRMjVtRQppQzl6WjhXNkQ2OXBvb0lsTTVXT\ +01ySEs0Rng1ck9vT05kUHQ4NEk1bTI3cnpnbXM4QnJXVUlGLytZZjJ0bGdmClBIR0V4c3ZCK3JRQk52\ +WHU3dXoxcVdFTlJTL2YwR2E3dVF4ZW5sZ2dubHc5M1pNOW1GWXpXb1RpdWFmdnphTnAKWEsrTEVrV2F\ +RYUs1Q0VaNEhmUlhBUUtDQVFFQTUyK240OUxQODlyQkR2bFdsTkxNanJqTDdSb0xyQ3FVZGpQWQpyT1\ +hZS3ZkTkxyS2NTc1hNdkY4YW5HQng1UG5oVDZGY05ic2dzQ3BUUXowMThZYmcrbUUxQno5ZTdFNTJGZ\ +i9NCk9BbWZqSllXUnZueUtiNnB3SGlvOHlXUXlVVk1zZU1CcmpvWk1kNkpPZEZ0K2JITHBWOS9iSkdR\ +a3NTRE04WTkKbWxGQUlUL0gyNTh1K1ZKTWsrT0prU28zZmJQSk5Ja1Q2WVBKVmNaSnZTRGI5QU83WDF\ +lendCOXVRL0FEblZ6YwpSQkJOUVZaTStZS2ZNWFJBdmFuWnlmWFFwaUxCQW8rRVRPSHJCR1dDRUhtSF\ +RCaEZIMTkyamtxNlcrTStvS0R1Cm1xMitMc2hZWTVFc2NpL2hPOVZjK2FCM0hhaGliME03M092MHFNc\ +WZoTncyU1BncHdRS0NBUUVBeDlaR1gxQnQKL3MwdGtNcGV1QWhlWjFqTklnZmFEY0RRTWlmU0k4QjRx\ +WUhiL1hOREQ5NjFQME9zMDdCN2wzNE1iZ3U2QlNwcwpXdSt0Y1hjSFlqQVJUc0Qzd0pSaVRIb0RSQzR\ +YYkxEa2pHRUVCVzRKbFVqZTA1QWZrU0QrdkZSMkJwZStxQlBLCm5yb3Mwd1BWL3RXa3MzY2VFOUlBTV\ +pWWDhQeFA3RVNXbitVZDJEWkZhcVFLb0JybHZXRXhxelpYUEJSVjhoS3QKcFBqWnFkZXFQLzhUZTBtS\ +zh5MEVreXVXOWhFdGZ2Sm5HWXhMNStrSG9xd2hQVk1tODZ5YlZNVHRQYWJTdCtPUwp0WHhJTE9RMWRN\ +QkFabzRxSnNkUUZJcTJnSHA5WFYwa2ZNUms1ajdJT1Q4c2Z6TlpKVkRNK1k5VHVlSGJXSnduCnZsWld\ +VZ2NVZTlBaWhRS0NBUUVBbFJaK2h1ckUvNGdLR2dWUld5bTRrTEJHM2dTTFJHdGhuQXVtSnlzaFoveE\ +wKZ2l1Wk55bll5L2hRQWpDMjdoUnlxb04rRFRid3hjdGVPOUJ3c1poNzBZOVJROHYwOERGVExMVE43O\ +E56UG5OcApBbXY5TGhzZTYxaFBMZU1qTkNVcVZPV3hyWFRMeWk1YkpCM2Z4SnhlWGJmNU5BMUpudUpz\ +eXF1SC82TWJ0cytKCmhkY3p3WFRjMCtBZVBKOS9nOENQZXdKYkMzRFVBQ2R1VlNHWHo4ZWZxcm1xbDd\ +jbnB5ZzBpK2pJRkNpVU8rVEcKVFcxeDg3KzUvUFF2MGtSQ0Z1UUloZ2ZCNkcwWW9vcHBrUWRZdXhKZl\ +pPaHdUUldpbTVMMlF5K294WWZySGVQOQozSlltbGFCMmJiN3kxL1FoQjcvek9VMk1nTEtYdHl4Z09ve\ +EpoQlFwZ1FLQ0FRQkIwSUE4dy9CMkNuMEhRcDhQClhUSTZOelRZRUYzd1NhQkg1SFdBOE5MTWdNaERJ\ +TUxsWnlPcVFrK1pLSGFMM2llWjFxTGRNS3VmQjNESC9idWcKeXRQb2JBVXNsN0lJSGVjVmZWaVpvMml\ +pRXhHUCtEMlB2UUFtRFVGWU90V3FrT2FPSlV2VmJ5ODhOM1NyeW9lZgo5aHpZUGxMWmxFQWNGR055S3\ +FibjJXOENHaU5LSWhXYW1Zd21UclY3T1pkeUcrTi9GZk40Vms1NkZyc1pCTDQ5CmRYU2xGZ045TTBaZ\ +WNleTEvZEpPRE9lSHNuME5VK0gvNFZEUk1hR1NmelpwSkxJOXE4T2FiSWpVM0ttb24wQTcKdzFWeWNU\ +L1FwYlBxRUFVckt5dytvMzV3MlAyaUZ1czZiMlBvUUxFTGFTRVl6K3R6UEw5UTM1ejNRdGdMQytuagp\ +IUmxCQW9JQkFES0Q4NGhrYkphczlIQ00zanNNSU9kb213ZEMvcktxVUxKNHFWZU5QR0xDY2VpNEdocn\ +dlQnNICnNoN0hibFlZSDN2U2Y3RW1iZEVCb2xlWVJsaUx5ZzJDQU1ZOGpNK0lpUEwydk1yM2Y3SzZPT\ +mU0UkVPUFJSZkcKWlJDcTh4a0ZPQlg1SUJUbkVCV3QzdVdyb1NGY2x4RTdUa2I4VkUyVzExTG9ZNlkw\ +TUNPaHdxN21xYXRUVnNrawpTRDNySmkrTFR6a2Y4OEx1bjZZNjdiaFNOTWpKZkFaUXNQc0FTRkJBUTJ\ +rQnE5alRLZGVuaU4yYTJIbm0xNCtrCnJDeU9ZVE14Q2hQbWNpS25pVy9MWnFUL0U1dlNRUGdBVzc0dT\ +VLazJoSjRBajNjRW9NVEwxSytZbStWYWh2U0cKTi8xOFdYQ1JRQkg1d0p2eXJYczBtT29GQlRnTWg4d\ +z0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=") + ("ringAccountKey" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTk\ +Jna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRRDNCdDRnOUVUdk9EVnYKM3hWV0ZlS\ +1Nnbk5uVEF3S2dYa3IrQ1FhdU8vTGZWM01RenNSNHliL3hoaWhhb1Z2c2FtZ3ZRU1haL0M1R3I5QQpE\ +YlAxbHNHclRCK1pXMC9uMXVEb3hmVWdZRWY3SGtVanJtdVFjUGlFWGlUVkNiY002U0NzdVNrMnRxdE1\ +BNjBNClRacVo2LzAvbkEvblR5TnFNaUJNSmFRN0NUb2xOTTh2Z2tvd0tBRW14OGpJUG9YZEttMnd6MD\ +Z6SnhwU1d4WjUKc0FBTkdSSHU0b2ZXNWJiMERvamtnRzFBYUJ6Nm9uSmdKK1JFSWV1UkpNQWFHYmtzW\ +TQ4Z1Z1b21BVTU0UFNvUApFb3psVGdHd1k0cnhJTGE0V1Y0RVZMVExrR240ZTYrRUYrSjIvRURBUFdN\ +bXREdFpUeURCc2t5bStLaDRUT2xPCjdnN3JlUUhLdDd1R21YU0RnbzVKZ2hOOHNVRFUxL1Z2YmFFcUZ\ +tTDJrZWNGOVlVZmNsUWRGY1ZncmIrMkh5R3AKRVc0b3RkZjlYYzhOMWxrbGk1dFBqRGZuQ1U3OHB6QT\ +BxQmV1SWhZTnF1VjhGSm1NemhXeVFDbE1MUEFYbXFVdwpWYlY0MWduM0NkektuUlVhZXFONXlzOG5KQ\ +mRJNDBleWlYRUlvU0VKcFpyT1Z5ck1icnNCQzltaVFpZUFhSnlBClFvcjFaRGlwMkpZNUFza2phUGQ0\ +NGk0MGNkeFpob1RhNnpzako5UjZScllFYjhWTmZQemFLaElwSXJSd2NpbCsKWjFrbUUwSE1kY21ITXR\ +hbWZhK0l6WUR4dDV6OGVOZys1RGpVVG1MRkdyQUVWRW5hNDcxdllxYnk5UCs1T1cvNQpSdkxtUER2Tj\ +dlUURpTlZENlBYRFk5OTY4bTZaaHdJREFRQUJBb0lDQURjOEkrTCtlNE41OEFqcHV0MmEyeVNqCllxY\ +VFUSWowMW1GTWhOWXMwQUdTTUswQncyMkdleXZwNFl3R1EzdnNIOSsvSkEydXdoYkJzazNpUW9FQmlx\ +Q0EKenZmOWdPcDRFNlk0elV6RitwSmQvRnUwSG4wWHBab0Rhdnp2eFN4djNFeUN3b0puYWZuL1FHeGw\ +xZEhoQUtsKwpmZGZjekRCc3NPZ1Y2cGtBd1MyY2wwOHFOT2g3cVhaQWFkYk1sQ1lWM0owU1hhaVZiNz\ +lHZXNvTzNwUVBMUUZiClNjQjFjT2sxYnNxWkpOU244d0xmMis5QVBEdzMwWEtNNHg5eTdRTE42Q3oxQ\ +WpvcFJLQ0NIS3R1SEc4UmVETTIKcnRTbjJmTnltQ0VqeDZGVTB6MHFldDV3Y01UbU5weEZuYXdEMU5s\ +dFpnZXBsSllwTjVKZXNEUmo2cFlnWXBPKwo5UDU2cEdtZVNTVzVxcHRoWFFLQmFsdy8wWXp2YUlYdHp\ +hTnZyNUJzRFNrWkU3cldzODIvQmFzUE1RckFmOGpLClZFMU9pSzcrVllUVTRFVWVoZ0FZOXdzNjFqYk\ +lSSEpQbW9VQXpkWHcyL0d0Vk9JUTFwUFJnOXNYN0JaMmUyV1YKdmd5aThPUEJxRWtwblBiMkU5Z0d1U\ +25rY01OeWFVbUl0c3pFandadW14dnZrUW5HanlTb3pjY2R3dnNQNnBJagpoN0g5VUNQTHdOM0N5N1lp\ +UmliSlZBWlNjZkF6QzhubXNLODQrTzJUZHBzTXk0SEZDMmM4dlZiclpteTVkWC9qCk1ESnBzS25JWlZ\ +JMmpXSzRpRS82aUdIWVdoY3JvWnYvVEJ0YW1SQUxTWDVOYkhhWTI0bXVRSG5yMldtaytld3EKbHRGbC\ +90bXgyVkpWUitMZ0JCUGhBb0lCQVFENEI0MjQyVTgvbkJ4d2RzelhCdWxBOVFTa0I5Zktud0RlRkV3S\ +wp3Nks0eU14YVdRU04ycjRxRDhLcW93OVZVMzRYdkRWbFh0RUlDaVh3Q0hZdW5IL3g3cXNSdEVzbHJM\ +aWg4UHRPClpDSU8zUml4RmlIQXFlQUh2YXF0NVhXdndaREx6WnV2THRJOTdINkZ1QjYxck5qMnhxdlR\ +IN05pUmp2S0R0WXgKR1VtNURoQ094cm9tR0NkWHRnWHJGaS9WRU1TSmpQMkM3OTNrN1pTNmNZL0Nkc1\ +RqWEsrZ1UzeWM3OC9kN1pYbwpKMGg2WFlSdmhlQW9Bd2dkVTl4MWtYL2ZmY2tZK1hUcFRwV2xXWmtlU\ +ytsejBpQkRnUlJzMm45OFZDeTZDRmRZCldsZXZaZy9SWXZ6dzlKdWFVcXArOHpHbHNXR2xuOEhtZW5X\ +Q1luSHJnNFBxQnRkL0FvSUJBUUQrOXhDL1N5ZGIKVWZxMUJHYy95YktZc3RLb3A1azB0d3M0SlUwTzN\ +aT1U3MlZ5YTdLT2lTemdPSzVnL2QzckhMMXR2dHViTDBWNAo1dEF4a1AzSkVYbmxZZU5IVkpROTc2RH\ +NGS3Ztc0FGL2JJdVBsdFBRT1dyM3g1eW1RU3lCOTBUczV0dFdWMTVQCktYYVNnMTZidDhwNS9MeERkZ\ +ng2c1YzN1o5RDFRd21EQllreVFIcWQ4clljTm9ad1M5ZnI3UTZhN1ZNSDVtT3IKbEF5dzBCYVdZQk9k\ +bjFGd0pVV3NlRlpmTy9vNUVqZk9Hd0xMR1hiOEVmQ1hqdlRYcUNHLzNrT1JvN1NkOWY1eQowVjIxMmt\ +YVVNINHNDbFB0SmwzeHpaMWJxQ2RMVDNITWNLUTk5UGFFVFppQnNXQ1lOcXg1c0Q0RGhoMzdZQ2hKCm\ +hlN3VUM1E0MElINUFvSUJBREN1VXR1b0UweloyQjhld2grbUpKdnlPMEh5cENFSnlrTE1Xd3gxejNkV\ +E9nQzEKbmhZMWk4TjNxbTZSYUk0SHdDVHFkTlI3b3ExZ1NJZnZNVHIrem9IdXBUYnBXeUorM3hJeDJU\ +Rk9wL3lnMnByUApURHFqWE94SUJycnc0WU5vaTRIa3poeTVKTnl3a1RpdnBaOWsySVMvQTdTQmNWVGx\ +raENianVDK0pPRWthSTJOClpiWGFZY1p1WElVQ3FzcTM2c3RRbCtWZUxRQWt2VjlHc0wrclRnT09Dbz\ +UrTkdRZEVZQnVoRkMzZlJzL1JhSVoKOWFBRTBFL3BTTWp1a05tTnQ2Mm1NSk1tTUdydXhnWFRRblBRR\ +npNSW43aXB2Z0hxQjRsUDM4emdsbnMvbmZVcgo1NWRuZXk3ejhMRFFETHVIc0RHd3hINzNKQjgrTVR2\ +WGFVbkNwQU1DZ2dFQVNBSGxBL0dvdXR6TFRvWmcxcDRUClI1YnhjZHBycFh5d3VYbW5hclJmY3VldG9\ +nUVNtTGpiS0xRNVk0RXZSTENJTzA5MDNENGNnOG5FTU10L01XTXoKSnZwZll3emJGU2J4THR1anRQSX\ +VhaHR3eXV2UkJIVEM1aG5FL3h0WEE1bWZLTDBHWXpzbmtubm1WL2lzSnBSZwpwZFVnSW5sWEJodkRyR\ +FlreUsvWEp0N1FZWlhlUzI5NXlUd0krZndoamlzVVBlTWEyUmRUUE9rQ01JbUVaNUhZCjJHSmZjS25H\ +SkxDVHpDKzNPcGtQazdFRE4vTUlMS2F3YVUxaGp1cVlKWVVUVmpXQzFEM2VUL1ViWHptM0VQNHMKVEN\ +uYWpCYVMzN0N2YVd4ek5JektXZS9TSXdGbEFmYWNSTHlneUR4Z3Q3bHp1akVObEtvU2xya3h3ckpEND\ +Z2WAptUUtDQVFBcTVQWWxSQjgvNnFiWWt1OTA0NUZRdXk2QWtlYXBaMW0raS9SQzZtbFRvUXB6NDlPU\ +Gs4ZGx5YjVtCndvSVhpaEo2V05jN1RsWlRYMnpQTTRBS0M5VFNBUWJrWDg5bjEyU2VDSUlHbXVINnk0\ +TjZiY2lxZjVVcSsvc0IKcHJKeFRNYlRSUFpqS0VVd1N0SFg1MUQ1bi9sQnZERGY3Y2VEZytsYlE0RjR\ +KMTlPd09oZ1lGcjFheGQvNXd2VgpURjNoVlQwbFZGN2RyRC9iMHZOcmxnbUNjbEk4UDg1a2dkRUhZbG\ +ZtTFoxeXJIMkNXVy9SS0lsWk9ZdFVuNFNpCkp5a2VlNDROWElXU3ovalRBdFRta3VQTzRvUjF5d3dRc\ +jdhUTF5a3hRVm9rVm5vY2xqU0tyQlk4R294a0I0eDIKUDNrb3F1UnkvcUd3QzBnN1o4ZjBTQjNQZVZt\ +eQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==") + ("ringAccountCert" . "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZXakNDQTBLZ\ +0F3SUJBZ0lJRm1tNmZuaWRndEl3RFFZSktvWklodmNOQVFFTUJRQXdUREVRTUE0R0ExVUUKQXhNSFNt\ +RnRhU0JEUVRFNE1EWUdDZ21TSm9tVDhpeGtBUUVUS0RjNVpqSTJaVFZpWTJNeU9EWXlPREppT0dFMwp\ +PRFF6TUdOak1EWXpNakV4T1RFNFkyWm1PVGd3SGhjTk1qRXdOREUyTVRjek1qRXdXaGNOTXpFd05ERT\ +BNVGN6Ck1qRXdXakJKTVEwd0N3WURWUVFERXdSS1lXMXBNVGd3TmdZS0NaSW1pWlB5TEdRQkFSTW9aa\ +k16TkRWbU1qYzMKTldSa1ptVXdOMkUwWWpCa09UVmtZV1ZoTVRFeFpERTFabUpqTVRFNU9UQ0NBaUl3\ +RFFZSktvWklodmNOQVFFQgpCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFQY0czaUQwUk84NE5XL2ZGVllWNHB\ +LQ2MyZE1EQXFCZVN2NEpCcTQ3OHQ5ClhjeERPeEhqSnYvR0dLRnFoVyt4cWFDOUJKZG44TGthdjBBTn\ +MvV1d3YXRNSDVsYlQrZlc0T2pGOVNCZ1Ivc2UKUlNPdWE1QncrSVJlSk5VSnR3enBJS3k1S1RhMnEwd\ +0RyUXhObXBuci9UK2NEK2RQSTJveUlFd2xwRHNKT2lVMAp6eStDU2pBb0FTYkh5TWcraGQwcWJiRFBU\ +ck1uR2xKYkZubXdBQTBaRWU3aWg5Ymx0dlFPaU9TQWJVQm9IUHFpCmNtQW41RVFoNjVFa3dCb1p1U3h\ +qanlCVzZpWUJUbmc5S2c4U2pPVk9BYkJqaXZFZ3RyaFpYZ1JVdE11UWFmaDcKcjRRWDRuYjhRTUE5WX\ +lhME8xbFBJTUd5VEtiNHFIaE02VTd1RHV0NUFjcTN1NGFaZElPQ2prbUNFM3l4UU5UWAo5Vzl0b1NvV\ +1l2YVI1d1gxaFI5eVZCMFZ4V0N0djdZZklha1JiaWkxMS8xZHp3M1dXU1dMbTArTU4rY0pUdnluCk1E\ +U29GNjRpRmcycTVYd1VtWXpPRmJKQUtVd3M4QmVhcFRCVnRYaldDZmNKM01xZEZScDZvM25Lenlja0Y\ +wamoKUjdLSmNRaWhJUW1sbXM1WEtzeHV1d0VMMmFKQ0o0Qm9uSUJDaXZWa09LbllsamtDeVNObzkzam\ +lMalJ4M0ZtRwpoTnJyT3lNbjFIcEd0Z1J2eFUxOC9Ob3FFaWtpdEhCeUtYNW5XU1lUUWN4MXlZY3kxc\ +Vo5cjRqTmdQRzNuUHg0CjJEN2tPTlJPWXNVYXNBUlVTZHJqdlc5aXB2TDAvN2s1Yi9sRzh1WThPODN0\ +NUFPSTFVUG85Y05qMzNyeWJwbUgKQWdNQkFBR2pRekJCTUIwR0ExVWREZ1FXQkJUek5GOG5kZDMrQjZ\ +TdzJWMnVvUkhSWDd3Um1UQVBCZ05WSFJNQgpBZjhFQlRBREFRSC9NQThHQTFVZER3RUIvd1FGQXdNSE\ +JnQXdEUVlKS29aSWh2Y05BUUVNQlFBRGdnSUJBRDMrCjlscFluMjZyeG5pekY2UkNvZFFFVmgvOVF2R\ +Wp1V3dHUWZqa3gxb3VlVjdDMzUyWnpIT2hWU3VGcG43TUxkVFcKamI2dWhMRkpoMWtlTDlYZ0pHalMy\ +V0UwdDlJUGp2UWx5UHIwRWJoWGRJNDJMYUR0NDk0dWQ2MEE0bWg0bW1zbwovcjY2NERKOWMwUjZBOUd\ +QZUJjWi9zekhMQjJ4VmM5M3hYNjVjcmNoVTFLMDBVK2ZZUWtHS0xidFFXeUZzdnlKCmRHdFRxamVlYV\ +VNeGt5dFFWNWFxVHJ1SG4vV3U2RWRZejYrZ0ViQXJHUURRK1J3QmMxMDNGcWRIU0xReWdEWHoKd0pNV\ +GhDREdBVmR6V2NCemJYL1JIZms5bTZzK01HblNJUFBrNG9FOUdFbGdQc2JUZ2FrTzc3aElUdzRxZXJi\ +TAp2M0tiaTVOeVZZVFNVa3hDb0VRSkIrWlZJT3BVNFhRdVAvNkZkWldBRk1LU0Jkd1JLcnRmT1hZT1E\ +xcVBvYU1uCjZPR1VGMU0rYWZ0dTNCMkNhZ2ZMaE5hbVBoSjdxWTNSMzJhK2VRVllvYWlESXZKMElIUH\ +FnQ0NuWXlIaVBHTjQKS3VvaE9IZFpXTkxOUXdIQTg3SDV5NEwrSGZISmdFZFppdWYrbTNMa3JJcnN5M\ +WFoUjgyaEpZVkhreHVyZVRDcQpIR2NJaUIvTHpkSG91WFVrWGNrNjRvWXVRQnM3ZE9KVEx6bGlibU8x\ +elRzVWRoc0d4dE9zc2lYWkFjUURmZHBnCjNHdFJ3UkRwd0ZtL2k5TC9UWjMzMjBwY0VZd21aN1dBSzJ\ +Ra3Z6eWZlelRGeXdLWmh3c0RQRkwycllzLzhXdWsKRk1sek5BVmRMTytTS1RxeGlkM0l1elFaQ0FwU0\ +5ybTJMY2ZVN2grWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBV\ +EUtLS0tLQpNSUlGWFRDQ0EwV2dBd0lCQWdJSXV0T3MxUXBsSVRvd0RRWUpLb1pJaHZjTkFRRU1CUUF3\ +VERFUU1BNEdBMVVFCkF4TUhTbUZ0YVNCRFFURTRNRFlHQ2dtU0pvbVQ4aXhrQVFFVEtEYzVaakkyWlR\ +WaVkyTXlPRFl5T0RKaU9HRTMKT0RRek1HTmpNRFl6TWpFeE9URTRZMlptT1Rnd0hoY05NakV3TkRFMk\ +1UY3pNakExV2hjTk16RXdOREUwTVRjegpNakExV2pCTU1SQXdEZ1lEVlFRREV3ZEtZVzFwSUVOQk1UZ\ +3dOZ1lLQ1pJbWlaUHlMR1FCQVJNb056bG1NalpsCk5XSmpZekk0TmpJNE1tSTRZVGM0TkRNd1kyTXdO\ +ak15TVRFNU1UaGpabVk1T0RDQ0FpSXdEUVlKS29aSWh2Y04KQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0l\ +CQUxTcGduY2tYODd3OE5vVzdRWE5DbWtHSHphVnN1NE9UbjFSSUhqVQpGR0w5MjNvVlk5RHVoZjFtVn\ +llamgremVCOCszaTR4b1E5MU04WDdTVnk4SHZxejQ4c0I2djAxMk5RTGpwN08xCkd4dmc1a0REeDRqb\ +mVyUWd6d0JzVEFuaC8xNy9SOEFDZkhINzYzUjhMRjY1clJPSStOT21KNUV2cU9rRWJJOXYKb0UySko1\ +czBVSHZZM1hTQ2pid01ROXRkM2c0SG9LNmRYSU44a2d6ejg0Yi83YkF5TnZ4a09rNnVSei9CSjhhZQo\ +zWjZudElza2tmVHhIZFpBbGtpVW5DU21Bb3VwQ01TbGRLS3RMRzNja2FhN0FDMDRxS29Rekc0WTN2Tl\ +RCOUlmCmdvYThOazlKMThoaFN2REVuR0haaURLR1dkQVA5RW5GRHZERnRFRFZyVVZSWUN5WHdyejMya\ +29Na3dYODVUMTgKc1F2TUZSdWRsa1BoOGxmbnFEWTFpZEd1R2IvSGlnU1ZqalJKZlVTbS9lZ3hycStS\ +TnpJWGFBOWNuOXAxQkdFbwpZU0YxeUdtTEgzSkJscUhVRTg4VnFkenZRdXZ3Mkhvakdvd0pkdlhmU2l\ +oZk5WOTh6VkEzQ2o3L0d3V2w0VU9OCkRUVUk2SzUrR3Y0a01iYXdxcWduaFlHbHBlZVp2bHE2UlI3OV\ +pNblRWVjJ1RWo4aERYQzdFTGN2Yk5tekJSSkoKS0gzaUxIbmNlSkxOV2NIMUV0K0pkaEFRR2xEYmk2R\ +VR0dHRuaWVaN3ZkMyt6UE00eXpkb3JEMlJXUjRyWG1acQpGRlI5eTBab2hQVTBjVmdKZHFtdUpyV01Z\ +eTVsOGt5SWdwaExkdTR1WWRpc0RPMG1ianEySE55K3pEakpyYXFHClNWTkZBZ01CQUFHalF6QkJNQjB\ +HQTFVZERnUVdCQlI1OG01YnpDaGlncmluaERETUJqSVJrWXovbURBUEJnTlYKSFJNQkFmOEVCVEFEQV\ +FIL01BOEdBMVVkRHdFQi93UUZBd01IQmdBd0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQgpBRWFDblluY\ +m9yWmRhWWZRUmxSb0dtSE94T1g5VFdNMXY0dWEweCtFcG11RDVWRDVlWEY1QVZkMlZadEdaeHYvCkd2\ +VnFBU2l0UTk3ampKV2p2bURWTUZtb3hQSmRYWDFkYTd5cmJYeFRmYm1mM1pac1RpdmZVdWQxYThxdUN\ +3dTUKTnBrdHFjV0JyMHRnNzFhOXlidHJOdm1GczZGRE1WMXkrY2JxYlp1UWlDWnc0WmZhekFaeTRQRG\ +NocE9SNjRCSwpBWFZIT05HcWFoV2hwcDkwd2E0TFEwUTE1U3FDR25kYVI4SHg5MHJOeEdkRjM1T1BLU\ +jd1TDdrWDU4ZGxaWStDClJJK1pKMndYMzJUZzgrc1RtTmNaUTliWDdvS0t3R3E5Uk94SjZJSUhOSnN2\ +bXhaSnlPcmE2N21hNTd3OWxiQnUKSzJlQ3cwZjRDeHdLNU1LNStkbWx6R3dhZmJlMG00TTBvVjlhWUx\ +ZTzAwR3Iza05heW9PdjRRVGtEM2pCMzVSMQpDMGJnQmk2eU1sTVJ2akZ5eEZkOFJpL003VG1jcXNObT\ +B5aklqbkZaenVtMFZTR1NLMXlRU3Flak40S0Y2R0JMCllpZ2JpM3c4WG5HYm9pZGdBUE9ncVVJeTJ1d\ +EU1MllzVXFsVHVncXhtM2xDOUhzaDM2UFJLNURDUG93eHVUNlgKcXo1M1ZiN2h6TkxLelpiRlJzbUdF\ +OFY2cWM2bXZTbUFXa25nL3QwaStXVmdGVkZuZFQrQ0oyNTJsa0ZacGljdAp6ekdETW44VUNDRUp4TDR\ +KTklTM2lLOUhlRys2MlZuay9QOEM3YVpLSXpVdjFud25rcVdUUUFYWDBKckJGdDdICjI5ZDk1RElmRT\ +RuT0FyS0JFNHc2Z1R4SU1uZzVzWi9ZbDFjcG5wUHlsR3VICi0tLS0tRU5EIENFUlRJRklDQVRFLS0tL\ +S0K") + ("ethKey" . "fN8cOT1lYNziaW0+pjBIgZ8r6+zMMhHsukkWBNPDsFo=") + ("TURN.username" . "ring") + ("TURN.server" . "turn.jami.net") + ("TURN.realm" . "ring") + ("TURN.password" . "ring") + ("TURN.enable" . "true") + ("TLS.verifyServer" . "true") + ("TLS.verifyClient" . "true") + ("TLS.serverName" . "") + ("TLS.requireClientCertificate" . "true") + ("TLS.privateKeyFile" . "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQU\ +RBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRQzM5b1Z0cXNtUGdaSUgKcHpTV\ +GtlT3BlWC9CSEx2KzFTYnJPSFpVRHEwNFZCUU5BNmJmSFNSWTJpbHE1WEVheXNVSmwzQmsvM0txZEhS\ +cQpEV01wQ1dpcE1Vc2FwSGxJR0tSWHEwbXhQZ29WODZSUVBub1dCRTdhWVVEZTlJZXlxMmllZXpDK1l\ +YSnBtWTljCk5tblpaMFlHOHJGMEVpWFA0SHpVWGphZklTKzdKTTJ5ZTZyUlpINXBvdHBQNmV4NXhqVU\ +VuNEFFdWhuWGJ6U0EKNnZMaC9wYnhIUVBHMVlmNHFhcU9TY1lXV0ZWaE5ySVBCVFJNZ2RaTWRGRTh0W\ +VFyaUNkNTV4dUhrYncrQmY1VQpmVENqN25tVEcybDJNbGcrSXBHVkFXUFRWNkl0NFNiS3VadW5MZmRD\ +S2FrSU03SnA3V2dJWjZNRHdkaFFQWjJNClJPQzN0b0c1ajh4aFZOU0Q5QlZiOGZBcnRmeHdldlliQk1\ +yOEdRV2JQYlRKYk9tZHZnUGRGcXNTb1F4QnRUcWQKSG1TMG53RjJ4UGZrdm1Cd3BSWWhHNHpuZlVtMl\ +BQcDBIK1g5Sk96d0R1QWI5K0c0cWZtK3Z6bDd1N0o3anJ0TQpHQlJlSlREdGFNd2RHa0lmcUNRZGREZ\ +HFpM1hzVHVVOVNubVN4NkdxT2V6ZU04bk55dmtZWjR2Uk9vODFzU1JjCjQ4L3pZZjJ1OFBJUm4vVy9x\ +Zk9hbjVIbkcxeFNBUDZkcHAzQ1Y0YTgwUFduZyszcXQ4NW5Ha2k2Nk00NUlnRjgKNHZwRGUyM2YyZnp\ +rTk5OOTk1VTBvUStKVGg5eG1HaWJmenlCaXk5d3RUVHVYWDB3Y3gwTm9wNjdYaFFDVVBGSApybVd6Wj\ +V5bXhEdkRhcUN1U3NwcG0vTkRVRWQyc1FJREFRQUJBb0lDQUYyWXo4bzhXdERvMjZPSkx2Ym1BeTcyC\ +jRra2VsWWZTYXpyQ1AzSUZCWnpqS2xCMHl6STVZWVRUZXI4b2ZhTmtCMXdaOE5WeUlxVVhHeVBhSzls\ +MU1BcmwKU1pFRW5iQlEyVXpCbVh6VVU4MVhhUUpxeHpMc2ZqSWR5U09teG1QaFVobFFGRHpJMTYxaXM\ +4MzI0V1A3WjJXaApsU2U1RkFQdjg1TVpYREVhY1c2R0N5SUVTYVMvdkpHQ2loQ2VzL0pCSmpoejdtNT\ +VRU3liSjl0dnJxUE5KSDhJCmhDTm1BUWhEU3NPYVJXNlpBdGV6UEdUb0FQUHNHMXhLMGdwUlVDM1YyR\ +C90bGRRa0VlSjhxaW5TaUN6ZjZIc3cKTnpncjVUbTMzTm96R3Rjc2Z4ZFl0cVB1UzRPRG40bktLSFpE\ +MTBLTng2Qi9HakdQTHIra21jUUVSMUV4U2s2QwpSemtzSTRzRml6VnVLYTFNK2ZqaVNVc3RTdHV1cTJ\ +QQTJJNzFNTTZlMHJmU3ZKM3VESEJYOWY5T1RFaGxZUFBkCnB1VWM2ek1pdEJKRTg2SFo1M08wR0MzdG\ +p1M1BnSnhmWnJyMHBCU20rSzQ3ajVTUFNkaytiVGh3UDZDZDhzWGUKNmljS3YvMXI0SjVqd1pFTmRna\ +2hKeHVuMkE1WVA0c0NBU21JSFFXWmU1cGdFQ0ljUXBHZjNBVllVdVpGeXZ6cApLL3VBRTc0L3NMK0VU\ +UnhDUlhkN0ZJM2cwZFVySTA2WUFIV1FkY1JpdWpIUU12ZXB3V2RrdUdkaE9wV3VRTy9oCjc0MGgvRlZ\ +0dFdOMjc3ajhhc3ptSDA3T2lRWFIwTU1mN2FEaldMaElMYkd2YkV4TzN0TnRBYXZ6cGxmMUNSNk8KUm\ +1nNDdhVTZpR3lON1MwTE85RUJBb0lCQVFEWWMwelh2UmJHTWxkVVZnOFFTT1ZHKzV4NXVocTVyQ2xtQ\ +lp2ZApvYitWS1hkMXBONThraWkxTFBiYUJmZG9JcWVUamdOK0E0YnVpT3RGNjdCWUdISkp0WTk4ZWR5\ +RkpZREtCSzIyCmthRml2eWVuV01UWG5jaHMvUmNXMnVGS1M3cFAyNDRXYkF2clQxZGxmTTF3L1JzbTZ\ +QVjF1dndPSmNJcEdLSzgKWWgyN2hiaThUbEF6bnJCSS9TbGZwNlpxV3Y0MFRLanNNdmVGVFNWRU5yd1\ +F2MVl4TjcxbjA1UWRVUkIrT0lJSQpPenpNMWpNcm43cjNmS3RKTEx0RllEdUhJZzJDL2E0cUZORmpjM\ +296V1laQkhlcDkrWlEyOTgxdy96VTJIZ0oxCkxiajZjMy9qQU5EakI3MnRkcWMxVUkvMWhwVUh2WDJz\ +emY2czM0L3VSY3RlaFgxWEFvSUJBUURaazVaT01RdVMKNzlVQkhCeTRFbFR2cVkvUUxjMUd1aG9LVXE\ +0dzhONEtJZlpMSDk5TTcwek9JWjNoaEdaYWJDREZHN3RqSDl4Vwo3UnhXVWt5cFRDK1h5TTc1YjF0YW\ +9jRVVyZ1hnUnE4R1JFRXg3OUtwWUE3ei95TVc1OHJCTWhHTWlGZ1JTM00zCmNQSzg2dHBvaTFDN2crd\ +lUxcjJwcDEzN0habzZiUHpKTFRPNXA1OG1tTFRPQVpKd1VSZ3pzZWJnc1dsWXZlR0wKZWNBZ3lYbUtt\ +WmVSeGRNUFlCK0NmMno1TWZ5Ujk4MHRVSDJPaitGQjlJNExzRTExREphZ2wwS1lHMWxKRTBFagpodEV\ +1cTFOTG9DcVkzYXVKYjhtRUpqNlA2Ylc2SytCZTBlUi9CS1MraGxxb3VOYWEySnlhSDc4Qis2U1VZWE\ +RuCnd6MityWUhVZEI4M0FvSUJBRFlXc2ZnaloyS0Z4KzdxUm45aVIvRXlCUXNpSjNXSWdSdmVnUEdrY\ +nRTZWRSeXYKNDIwcnRRSjVSd0o2aFRXL216S3pSVW9qSlgvTU5VYld1ODEzNW05bThJRkJqb3F6TVhq\ +S0xJSzM1NlZlY1ZGUApUSGs1RTVHd3VTbGI3dnA2N0FieXJaSUswL3VzYXdHUWEySTF6YWd1aE5BenR\ +yTHVXcE9jZFdZditwQVd2WEJJCi9aKzRvd0xLU0tGL3FvVmZVYkRPQzFSaTlCbWFpcHArTndiVVdYeV\ +pHanFzMDVGejVYUTFPTUZIMUV5M3BqZmIKaFlRODRpeTZBZDQzU3dqY3lKV1lRUUtCQzBZWDRFeWVyW\ +Dd1TTkvaEUxbWRHUGlJdmNwVk8zWCt3Ly9LQndZNQorUGtTd1NKc3lTSDRqTkRsSGE2K2VuNUpSNy81\ +YWVVNENiY0lFcWNDZ2dFQkFLelMvNnhDWnZnalN5V2poK2hxCm4wN3plQW1icUJmTEVZNHJtTFBGVUF\ +ucWFqSElNbDV4SXFnRnFkd05pQ1BCQ2RLbnNaUU9KYjVpZjRUTndKa2wKckJRNzdMUFRVVlJQY2dnVU\ +p4Uzc4S0Rnckl5Vys5V1FPTEIxZEJEb3MzUDhhbFlmb3h5eHV1Wko4SFpCY3BWaQpQQkdHdTFnSDd3V\ +0lyUzBmbVhkWlJQNGp5cGRvM3hFUWNXWEZkK1dCZE9EektmcEcwZkFzZTdDSFdDWnpBdmttCkFYQklH\ +OXQxdGZHNWQvMEZTS05GbTVPb0FPT3h3L0xZNTgrL0RmZXd0U0VBcFdRZkxTL1BmSWxVdUdvQ3FwcEM\ +Kc2pOVXVNSGxxc011Z2JsY29mNHNoZityWjMzQldYOEJSNWdIb21mRE1ibDNDQWp5TXd1dHpybzVxcD\ +BBUTBWWApxOGNDZ2dFQkFLakFXVVRYY1F2TE8yYkxOZmJBTUlSVXk1T2lTZmJCbDNYRThSZnNzaUt2V\ +VBnTFcwSlV1V3FLCjdGdUFxTlJPRHhrS0pMSTdyQlo2YVNqNitFWHpUMnJwY2dFWktnSjFOUEFRdFNs\ +UjNJUkcyU3JJdjBFK3UzbkUKK1laa3pOa2Q0MUJqTkRjRm1HV21lZk5ROUJmaVIrZlZFSkZmcE5oSkl\ +mNUloSWU0RUtZUE5VUXNua0tSVTlxUApzWi9idXBXc2w4bWVFcko3bllJQ05ucHpnSHRpNXdSMlliVF\ +VXT01odmRFUldxMnhTV3BBYmtNMElhZDBUc05kCmUrYVRQVmJOMXFibFZLMm1qUTl2YS9JSkVuSE51V\ +E9TREtJeUpvcVArQkxiRTVjQU5acXQ2OFFadWdOc2RxNHkKV2FoeStydU5LS1F3Mk5MYzQzZUtsNmxv\ +bXdtRlFZOD0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=") + ("TLS.password" . "") + ("TLS.negotiationTimeoutSec" . "-1") + ("TLS.method" . "Automatic") + ("TLS.ciphers" . "") + ("TLS.certificateFile" . "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZHVENDQ\ +XdHZ0F3SUJBZ0lJU1pUdlZPQnh3akF3RFFZSktvWklodmNOQVFFTUJRQXdTVEVOTUFzR0ExVUUKQXhN\ +RVNtRnRhVEU0TURZR0NnbVNKb21UOGl4a0FRRVRLR1l6TXpRMVpqSTNOelZrWkdabE1EZGhOR0l3WkR\ +rMQpaR0ZsWVRFeE1XUXhOV1ppWXpFeE9Ua3dIaGNOTWpFd05ERTJNVGN6TWpFd1doY05NekV3TkRFME\ +1UY3pNakV3CldqQlFNUlF3RWdZRFZRUURFd3RLWVcxcElHUmxkbWxqWlRFNE1EWUdDZ21TSm9tVDhpe\ +GtBUUVUS0dFM09XTmwKTURVNE16VmhPRFV5WlRsbU5qWmxOelF3TURjeU5EUXdPVFZpTVdaa1kyVXdO\ +bVV3Z2dJaU1BMEdDU3FHU0liMwpEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUUMzOW9WdHFzbVBnWkl\ +IcHpTVGtlT3BlWC9CSEx2KzFTYnJPSFpVCkRxMDRWQlFOQTZiZkhTUlkyaWxxNVhFYXlzVUpsM0JrLz\ +NLcWRIUnFEV01wQ1dpcE1Vc2FwSGxJR0tSWHEwbXgKUGdvVjg2UlFQbm9XQkU3YVlVRGU5SWV5cTJpZ\ +WV6QytZWEpwbVk5Y05tblpaMFlHOHJGMEVpWFA0SHpVWGphZgpJUys3Sk0yeWU2clJaSDVwb3RwUDZl\ +eDV4alVFbjRBRXVoblhielNBNnZMaC9wYnhIUVBHMVlmNHFhcU9TY1lXCldGVmhOcklQQlRSTWdkWk1\ +kRkU4dFlRcmlDZDU1eHVIa2J3K0JmNVVmVENqN25tVEcybDJNbGcrSXBHVkFXUFQKVjZJdDRTYkt1Wn\ +VuTGZkQ0tha0lNN0pwN1dnSVo2TUR3ZGhRUFoyTVJPQzN0b0c1ajh4aFZOU0Q5QlZiOGZBcgp0Znh3Z\ +XZZYkJNcjhHUVdiUGJUSmJPbWR2Z1BkRnFzU29ReEJ0VHFkSG1TMG53RjJ4UGZrdm1Cd3BSWWhHNHpu\ +CmZVbTJQUHAwSCtYOUpPendEdUFiOStHNHFmbSt2emw3dTdKN2pydE1HQlJlSlREdGFNd2RHa0lmcUN\ +RZGREZHEKaTNYc1R1VTlTbm1TeDZHcU9lemVNOG5OeXZrWVo0dlJPbzgxc1NSYzQ4L3pZZjJ1OFBJUm\ +4vVy9xZk9hbjVIbgpHMXhTQVA2ZHBwM0NWNGE4MFBXbmcrM3F0ODVuR2tpNjZNNDVJZ0Y4NHZwRGUyM\ +2YyZnprTk5OOTk1VTBvUStKClRoOXhtR2liZnp5Qml5OXd0VFR1WFgwd2N4ME5vcDY3WGhRQ1VQRkhy\ +bVd6WjV5bXhEdkRhcUN1U3NwcG0vTkQKVUVkMnNRSURBUUFCTUEwR0NTcUdTSWIzRFFFQkRBVUFBNEl\ +DQVFCZmRCc0p4RVVWeFRBeG5vNll1bEFoR1ZvUAplWG8xMHIwOE5DcDZRZlJxeGJlTkZ5aXEvKzEwSE\ +NpL1RoZk41OVdLNlpudFF4NlFNZUxEUVZTb0NjNzlaaWQ4ClE2RUdsWkp1c2RTTmg0VjVteXRCQVZHZ\ +2J2aXJFWU1Wcm5jWWg3bHR2LzVuSGRsbyt2WXV3Vzh0aEhHTk1TUkIKQmhJN2xydmpqY3NkbVl6L1Bp\ +NFNZdkg3c3RaVWpRYmUzNzh3UE90b3lBMTNybEtQUTF4QjJFbUxISDYya21WTQowa25wL1hQQ2o2alR\ +zakpFWko1NzZNMmloYy9DTzkvREVlWWZ4RFlJb004NEF5dTc0UU9UUVN1cnVHRjF5T1RKCmlxRkltTH\ +hMcWRxNk1Zdmx1QjFmTzlKaU9QaS84UEJFTTVpeGYzajlGOFVMQTZUTU1NSklFR1ROeUNzOWpzQloKR\ +UNiWVgweTY4WWtGYnYzQmNWaGk2K1VVWVhBVUd0akhwQ3Z2VThYaHowL0RVZFVaTkpqejRJeWl1ZE5N\ +dnFjQgppSEJDdkxFS1B4VFd1ZlFZaGM5ZkVXTm1valc1WSsvalBVeDcrQWxPM1RXZm1OclBpWDJuSEd\ +5UG5tYjZIR2hWCmp3UU0wT1h4cGxnZ2dQMWpVZ0VYWWRucStjYzdRMy94RFIvdi9Fd244T1d4OVB3eV\ +Y0WFZwZXY5QnpmeWwyQTMKdFhWVkFKMzJtcTlPQmVadXczdWlWU2E2TWdCVG80eXcrYnBjU2VIU2xXO\ +XNRc1NYY3dUNjhvOUdhR2hMNjdXMApwQWx4R2VxSWRtbTZ0MkxIUCtQQnBtL3BweTMvTmh1NFIwMTNv\ +Znp5V2Y0bEcrVnpWVGE0eXVqU1J3UlluYmZyCjlSWER0L0I5VEg5TnNsamdBQT09Ci0tLS0tRU5EIEN\ +FUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZXakNDQTBLZ0F3SU\ +JBZ0lJRm1tNmZuaWRndEl3RFFZSktvWklodmNOQVFFTUJRQXdUREVRTUE0R0ExVUUKQXhNSFNtRnRhU\ +0JEUVRFNE1EWUdDZ21TSm9tVDhpeGtBUUVUS0RjNVpqSTJaVFZpWTJNeU9EWXlPREppT0dFMwpPRFF6\ +TUdOak1EWXpNakV4T1RFNFkyWm1PVGd3SGhjTk1qRXdOREUyTVRjek1qRXdXaGNOTXpFd05ERTBNVGN\ +6Ck1qRXdXakJKTVEwd0N3WURWUVFERXdSS1lXMXBNVGd3TmdZS0NaSW1pWlB5TEdRQkFSTW9aak16Tk\ +RWbU1qYzMKTldSa1ptVXdOMkUwWWpCa09UVmtZV1ZoTVRFeFpERTFabUpqTVRFNU9UQ0NBaUl3RFFZS\ +ktvWklodmNOQVFFQgpCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFQY0czaUQwUk84NE5XL2ZGVllWNHBLQ2My\ +ZE1EQXFCZVN2NEpCcTQ3OHQ5ClhjeERPeEhqSnYvR0dLRnFoVyt4cWFDOUJKZG44TGthdjBBTnMvV1d\ +3YXRNSDVsYlQrZlc0T2pGOVNCZ1Ivc2UKUlNPdWE1QncrSVJlSk5VSnR3enBJS3k1S1RhMnEwd0RyUX\ +hObXBuci9UK2NEK2RQSTJveUlFd2xwRHNKT2lVMAp6eStDU2pBb0FTYkh5TWcraGQwcWJiRFBUck1uR\ +2xKYkZubXdBQTBaRWU3aWg5Ymx0dlFPaU9TQWJVQm9IUHFpCmNtQW41RVFoNjVFa3dCb1p1U3hqanlC\ +VzZpWUJUbmc5S2c4U2pPVk9BYkJqaXZFZ3RyaFpYZ1JVdE11UWFmaDcKcjRRWDRuYjhRTUE5WXlhME8\ +xbFBJTUd5VEtiNHFIaE02VTd1RHV0NUFjcTN1NGFaZElPQ2prbUNFM3l4UU5UWAo5Vzl0b1NvV1l2YV\ +I1d1gxaFI5eVZCMFZ4V0N0djdZZklha1JiaWkxMS8xZHp3M1dXU1dMbTArTU4rY0pUdnluCk1EU29GN\ +jRpRmcycTVYd1VtWXpPRmJKQUtVd3M4QmVhcFRCVnRYaldDZmNKM01xZEZScDZvM25Lenlja0YwamoK\ +UjdLSmNRaWhJUW1sbXM1WEtzeHV1d0VMMmFKQ0o0Qm9uSUJDaXZWa09LbllsamtDeVNObzkzamlMalJ\ +4M0ZtRwpoTnJyT3lNbjFIcEd0Z1J2eFUxOC9Ob3FFaWtpdEhCeUtYNW5XU1lUUWN4MXlZY3kxcVo5cj\ +RqTmdQRzNuUHg0CjJEN2tPTlJPWXNVYXNBUlVTZHJqdlc5aXB2TDAvN2s1Yi9sRzh1WThPODN0NUFPS\ +TFVUG85Y05qMzNyeWJwbUgKQWdNQkFBR2pRekJCTUIwR0ExVWREZ1FXQkJUek5GOG5kZDMrQjZTdzJW\ +MnVvUkhSWDd3Um1UQVBCZ05WSFJNQgpBZjhFQlRBREFRSC9NQThHQTFVZER3RUIvd1FGQXdNSEJnQXd\ +EUVlKS29aSWh2Y05BUUVNQlFBRGdnSUJBRDMrCjlscFluMjZyeG5pekY2UkNvZFFFVmgvOVF2RWp1V3\ +dHUWZqa3gxb3VlVjdDMzUyWnpIT2hWU3VGcG43TUxkVFcKamI2dWhMRkpoMWtlTDlYZ0pHalMyV0Uwd\ +DlJUGp2UWx5UHIwRWJoWGRJNDJMYUR0NDk0dWQ2MEE0bWg0bW1zbwovcjY2NERKOWMwUjZBOUdQZUJj\ +Wi9zekhMQjJ4VmM5M3hYNjVjcmNoVTFLMDBVK2ZZUWtHS0xidFFXeUZzdnlKCmRHdFRxamVlYVVNeGt\ +5dFFWNWFxVHJ1SG4vV3U2RWRZejYrZ0ViQXJHUURRK1J3QmMxMDNGcWRIU0xReWdEWHoKd0pNVGhDRE\ +dBVmR6V2NCemJYL1JIZms5bTZzK01HblNJUFBrNG9FOUdFbGdQc2JUZ2FrTzc3aElUdzRxZXJiTAp2M\ +0tiaTVOeVZZVFNVa3hDb0VRSkIrWlZJT3BVNFhRdVAvNkZkWldBRk1LU0Jkd1JLcnRmT1hZT1ExcVBv\ +YU1uCjZPR1VGMU0rYWZ0dTNCMkNhZ2ZMaE5hbVBoSjdxWTNSMzJhK2VRVllvYWlESXZKMElIUHFnQ0N\ +uWXlIaVBHTjQKS3VvaE9IZFpXTkxOUXdIQTg3SDV5NEwrSGZISmdFZFppdWYrbTNMa3JJcnN5MWFoUj\ +gyaEpZVkhreHVyZVRDcQpIR2NJaUIvTHpkSG91WFVrWGNrNjRvWXVRQnM3ZE9KVEx6bGlibU8xelRzV\ +WRoc0d4dE9zc2lYWkFjUURmZHBnCjNHdFJ3UkRwd0ZtL2k5TC9UWjMzMjBwY0VZd21aN1dBSzJRa3Z6\ +eWZlelRGeXdLWmh3c0RQRkwycllzLzhXdWsKRk1sek5BVmRMTytTS1RxeGlkM0l1elFaQ0FwU05ybTJ\ +MY2ZVN2grWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS\ +0tLQpNSUlGWFRDQ0EwV2dBd0lCQWdJSXV0T3MxUXBsSVRvd0RRWUpLb1pJaHZjTkFRRU1CUUF3VERFU\ +U1BNEdBMVVFCkF4TUhTbUZ0YVNCRFFURTRNRFlHQ2dtU0pvbVQ4aXhrQVFFVEtEYzVaakkyWlRWaVky\ +TXlPRFl5T0RKaU9HRTMKT0RRek1HTmpNRFl6TWpFeE9URTRZMlptT1Rnd0hoY05NakV3TkRFMk1UY3p\ +NakExV2hjTk16RXdOREUwTVRjegpNakExV2pCTU1SQXdEZ1lEVlFRREV3ZEtZVzFwSUVOQk1UZ3dOZ1\ +lLQ1pJbWlaUHlMR1FCQVJNb056bG1NalpsCk5XSmpZekk0TmpJNE1tSTRZVGM0TkRNd1kyTXdOak15T\ +VRFNU1UaGpabVk1T0RDQ0FpSXdEUVlKS29aSWh2Y04KQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUxT\ +cGduY2tYODd3OE5vVzdRWE5DbWtHSHphVnN1NE9UbjFSSUhqVQpGR0w5MjNvVlk5RHVoZjFtVnllamg\ +remVCOCszaTR4b1E5MU04WDdTVnk4SHZxejQ4c0I2djAxMk5RTGpwN08xCkd4dmc1a0REeDRqbmVyUW\ +d6d0JzVEFuaC8xNy9SOEFDZkhINzYzUjhMRjY1clJPSStOT21KNUV2cU9rRWJJOXYKb0UySko1czBVS\ +HZZM1hTQ2pid01ROXRkM2c0SG9LNmRYSU44a2d6ejg0Yi83YkF5TnZ4a09rNnVSei9CSjhhZQozWjZu\ +dElza2tmVHhIZFpBbGtpVW5DU21Bb3VwQ01TbGRLS3RMRzNja2FhN0FDMDRxS29Rekc0WTN2TlRCOUl\ +mCmdvYThOazlKMThoaFN2REVuR0haaURLR1dkQVA5RW5GRHZERnRFRFZyVVZSWUN5WHdyejMya29Na3\ +dYODVUMTgKc1F2TUZSdWRsa1BoOGxmbnFEWTFpZEd1R2IvSGlnU1ZqalJKZlVTbS9lZ3hycStSTnpJW\ +GFBOWNuOXAxQkdFbwpZU0YxeUdtTEgzSkJscUhVRTg4VnFkenZRdXZ3Mkhvakdvd0pkdlhmU2loZk5W\ +OTh6VkEzQ2o3L0d3V2w0VU9OCkRUVUk2SzUrR3Y0a01iYXdxcWduaFlHbHBlZVp2bHE2UlI3OVpNblR\ +WVjJ1RWo4aERYQzdFTGN2Yk5tekJSSkoKS0gzaUxIbmNlSkxOV2NIMUV0K0pkaEFRR2xEYmk2RVR0dH\ +RuaWVaN3ZkMyt6UE00eXpkb3JEMlJXUjRyWG1acQpGRlI5eTBab2hQVTBjVmdKZHFtdUpyV01ZeTVsO\ +Gt5SWdwaExkdTR1WWRpc0RPMG1ianEySE55K3pEakpyYXFHClNWTkZBZ01CQUFHalF6QkJNQjBHQTFV\ +ZERnUVdCQlI1OG01YnpDaGlncmluaERETUJqSVJrWXovbURBUEJnTlYKSFJNQkFmOEVCVEFEQVFIL01\ +BOEdBMVVkRHdFQi93UUZBd01IQmdBd0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQgpBRWFDblluYm9yWm\ +RhWWZRUmxSb0dtSE94T1g5VFdNMXY0dWEweCtFcG11RDVWRDVlWEY1QVZkMlZadEdaeHYvCkd2VnFBU\ +2l0UTk3ampKV2p2bURWTUZtb3hQSmRYWDFkYTd5cmJYeFRmYm1mM1pac1RpdmZVdWQxYThxdUN3dTUK\ +TnBrdHFjV0JyMHRnNzFhOXlidHJOdm1GczZGRE1WMXkrY2JxYlp1UWlDWnc0WmZhekFaeTRQRGNocE9\ +SNjRCSwpBWFZIT05HcWFoV2hwcDkwd2E0TFEwUTE1U3FDR25kYVI4SHg5MHJOeEdkRjM1T1BLUjd1TD\ +drWDU4ZGxaWStDClJJK1pKMndYMzJUZzgrc1RtTmNaUTliWDdvS0t3R3E5Uk94SjZJSUhOSnN2bXhaS\ +nlPcmE2N21hNTd3OWxiQnUKSzJlQ3cwZjRDeHdLNU1LNStkbWx6R3dhZmJlMG00TTBvVjlhWUxZTzAw\ +R3Iza05heW9PdjRRVGtEM2pCMzVSMQpDMGJnQmk2eU1sTVJ2akZ5eEZkOFJpL003VG1jcXNObTB5akl\ +qbkZaenVtMFZTR1NLMXlRU3Flak40S0Y2R0JMCllpZ2JpM3c4WG5HYm9pZGdBUE9ncVVJeTJ1dEU1Ml\ +lzVXFsVHVncXhtM2xDOUhzaDM2UFJLNURDUG93eHVUNlgKcXo1M1ZiN2h6TkxLelpiRlJzbUdFOFY2c\ +WM2bXZTbUFXa25nL3QwaStXVmdGVkZuZFQrQ0oyNTJsa0ZacGljdAp6ekdETW44VUNDRUp4TDRKTklT\ +M2lLOUhlRys2MlZuay9QOEM3YVpLSXpVdjFud25rcVdUUUFYWDBKckJGdDdICjI5ZDk1RElmRTRuT0F\ +yS0JFNHc2Z1R4SU1uZzVzWi9ZbDFjcG5wUHlsR3VICi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K") + ("STUN.server" . "") + ("STUN.enable" . "false") + ("SRTP.rtpFallback" . "false") + ("SRTP.keyExchange" . "sdes") + ("SRTP.enable" . "true") + ("RingNS.uri" . "") + ("RingNS.account" . "0790738ce15fa05933b49dd77034312787da86c3") + ("DHT.PublicInCalls" . "true") + ("Account.videoPortMin" . "49152") + ("Account.videoPortMax" . "65534") + ("Account.videoEnabled" . "true") + ("Account.username" . "f3345f2775ddfe07a4b0d95daea111d15fbc1199") + ("Account.useragent" . "") + ("Account.upnpEnabled" . "true") + ("Account.type" . "RING") + ("Account.ringtoneEnabled" . "true") + ("Account.rendezVous" . "true") + ("Account.publishedSameAsLocal" . "true") + ("Account.publishedPort" . "5060") + ("Account.publishedAddress" . "") + ("Account.presenceSubscribeSupported" . "true") + ("Account.peerDiscovery" . "false") + ("Account.managerUsername" . "") + ("Account.managerUri" . "") + ("Account.mailbox" . "") + ("Account.localModeratorsEnabled" . "true") + ("Account.localInterface" . "default") + ("Account.hostname" . "bootstrap.jami.net") + ("Account.hasCustomUserAgent" . "false") + ("Account.enable" . "true") + ("Account.dtmfType" . "overrtp") + ("Account.displayName" . "dummy") + ("Account.defaultModerators" . "") + ("Account.audioPortMin" . "16384") + ("Account.audioPortMax" . "32766") + ("Account.archiveHasPassword" . "false") + ("Account.allowCertFromTrusted" . "true") + ("Account.allowCertFromHistory" . "true") + ("Account.allowCertFromContact" . "true") + ("Account.allModeratorEnabled" . "true") + ("Account.alias" . "dummy") + ("Account.activeCallLimit" . "-1") + ("Account.accountPublish" . "false") + ("Account.accountDiscovery" . "false"))) diff --git a/gnu/tests/telephony.scm b/gnu/tests/telephony.scm new file mode 100644 index 0000000000..1155a9dbc2 --- /dev/null +++ b/gnu/tests/telephony.scm @@ -0,0 +1,366 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Maxim Cournoyer . +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu tests telephony) + #:use-module (gnu) + #:use-module (gnu packages) + #:use-module (gnu packages guile) + #:use-module (gnu tests) + #:use-module (gnu system vm) + #:use-module (gnu services) + #:use-module (gnu services dbus) + #:use-module (gnu services networking) + #:use-module (gnu services ssh) + #:use-module (gnu services telephony) + #:use-module (guix gexp) + #:use-module (guix modules) + #:export (%test-jami + %test-jami-provisioning)) + +;;; +;;; Jami daemon. +;;; + +(include "data/jami-dummy-account.dat") ;defines %jami-account-content-sexp + +(define %dummy-jami-account-archive + ;; A Jami account archive is a gzipped JSON file. + (computed-file + "dummy-jami-account.gz" + (with-extensions (list guile-json-4 guile-zlib) + #~(begin + (use-modules (json) (zlib)) + (let ((port (open-output-file #$output))) + (call-with-gzip-output-port port + (lambda (port) + (scm->json '#$%jami-account-content-sexp port)))))))) + +(define %allowed-contacts '("1dbcb0f5f37324228235564b79f2b9737e9a008f" + "2dbcb0f5f37324228235564b79f2b9737e9a008f")) + +(define %moderators '("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")) + +(define %dummy-jami-account (jami-account + (archive %dummy-jami-account-archive) + (allowed-contacts %allowed-contacts) + (moderators %moderators) + (rendezvous-point? #t) + (peer-discovery? #f) + (bootstrap-hostnames '("bootstrap.me" + "fallback.another.host")) + (name-server-uri "https://my.name.server"))) + +(define* (make-jami-os #:key provisioning?) + (operating-system + (host-name "jami") + (timezone "America/Montreal") + (locale "en_US.UTF-8") + + (bootloader (bootloader-configuration + (bootloader grub-bootloader) + (target "/dev/sdX"))) + (file-systems (cons (file-system + (device (file-system-label "my-root")) + (mount-point "/") + (type "ext4")) + %base-file-systems)) + (firmware '()) + + (services (cons* (service jami-service-type + (if provisioning? + (jami-configuration + (debug? #t) + (accounts (list %dummy-jami-account))) + (jami-configuration + (debug? #t)))) + (service dbus-root-service-type) + ;; The following services/packages are added for + ;; debugging purposes. + (service dhcp-client-service-type) + (service openssh-service-type + (openssh-configuration + (permit-root-login #t) + (allow-empty-passwords? #t))) + %base-services)) + (packages (cons* (specification->package "recutils") + (specification->package "strace") + %base-packages)))) + +(define %jami-os + (make-jami-os)) + +(define %jami-os-provisioning + (make-jami-os #:provisioning? #t)) + +(define* (run-jami-test #:key provisioning?) + "Run tests in %JAMI-OS. When PROVISIONING? is true, test the +accounts provisioning feature of the service." + (define os (marionette-operating-system + (if provisioning? + %jami-os-provisioning + %jami-os) + #:imported-modules '((gnu services herd) + (guix combinators)))) + (define vm (virtual-machine + (operating-system os) + (memory-size 512))) + + (define username (assoc-ref %jami-account-content-sexp + "Account.username")) + + (define test + (with-imported-modules (source-module-closure + '((gnu build marionette) + (gnu build jami-service))) + #~(begin + (use-modules (rnrs base) + (srfi srfi-11) + (srfi srfi-64) + (gnu build marionette) + (gnu build jami-service)) + + (define marionette + (make-marionette (list #$vm))) + + (mkdir #$output) + (chdir #$output) + + (test-begin "jami") + + (test-assert "service is running" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (match (start-service 'jami) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) (number? pid)))))) + marionette)) + + (test-assert "service can be stopped" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + (setenv "PATH" "/run/current-system/profile/bin") + (let ((pid (match (start-service 'jami) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid)))))) + + (assert (number? pid)) + + (match (stop-service 'jami) + (services ;a list of service symbols + (member 'jami services))) + ;; Sometimes, the process still appear in pgrep, even + ;; though we are using waitpid after sending it SIGTERM + ;; in the service; use retries. + (with-retries 20 1 + (not (zero? (status:exit-val + (system* "pgrep" "dring"))))))) + marionette)) + + (test-assert "service can be restarted" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + ;; Start and retrieve the current PID. + (define pid (match (start-service 'jami) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid))))) + (assert (number? pid)) + + ;; Restart the service. + (restart-service 'jami) + + (define new-pid (match (start-service 'jami) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) pid))))) + (assert (number? new-pid)) + + (not (eq? pid new-pid))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami accounts provisioning, account present" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + ;; Accounts take some time to appear after being added. + (with-retries 20 1 + (with-shepherd-action 'jami ('list-accounts) results + (let ((account (assoc-ref (car results) #$username))) + (assert (string=? #$username + (assoc-ref account + "Account.username"))))))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami accounts provisioning, allowed-contacts" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base) + (srfi srfi-1)) + + ;; Public mode is disabled. + (with-shepherd-action 'jami ('list-account-details) + results + (let ((account (assoc-ref (car results) #$username))) + (assert (string=? "false" + (assoc-ref account + "DHT.PublicInCalls"))))) + + ;; Allowed contacts match those declared in the configuration. + (with-shepherd-action 'jami ('list-contacts) results + (let ((contacts (assoc-ref (car results) #$username))) + (assert (lset= string-ci=? contacts '#$%allowed-contacts))))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami accounts provisioning, moderators" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base) + (srfi srfi-1)) + + ;; Moderators match those declared in the configuration. + (with-shepherd-action 'jami ('list-moderators) results + (let ((moderators (assoc-ref (car results) #$username))) + (assert (lset= string-ci=? moderators '#$%moderators)))) + + ;; Moderators can be added via the Shepherd action. + (with-shepherd-action 'jami + ('add-moderator "cccccccccccccccccccccccccccccccccccccccc" + #$username) results + (let ((moderators (car results))) + (assert (lset= string-ci=? moderators + (cons "cccccccccccccccccccccccccccccccccccccccc" + '#$%moderators)))))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami service actions, ban/unban contacts" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base) + (srfi srfi-1)) + + ;; Globally ban a contact. + (with-shepherd-action 'jami + ('ban-contact "1dbcb0f5f37324228235564b79f2b9737e9a008f") _ + (with-shepherd-action 'jami ('list-banned-contacts) results + (every (match-lambda + ((username . banned-contacts) + (member "1dbcb0f5f37324228235564b79f2b9737e9a008f" + banned-contacts))) + (car results)))) + + ;; Ban a contact for a single account. + (with-shepherd-action 'jami + ('ban-contact "dddddddddddddddddddddddddddddddddddddddd" + #$username) _ + (with-shepherd-action 'jami ('list-banned-contacts) results + (every (match-lambda + ((username . banned-contacts) + (let ((found? (member "dddddddddddddddddddddddddddddddddddddddd" + banned-contacts))) + (if (string=? #$username username) + found? + (not found?))))) + (car results))))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami service actions, enable/disable accounts" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base)) + + (with-shepherd-action 'jami + ('disable-account #$username) _ + (with-shepherd-action 'jami ('list-accounts) results + (let ((account (assoc-ref (car results) #$username))) + (assert (string= "false" + (assoc-ref account "Account.enable")))))) + + (with-shepherd-action 'jami + ('enable-account #$username) _ + (with-shepherd-action 'jami ('list-accounts) results + (let ((account (assoc-ref (car results) #$username))) + (assert (string= "true" + (assoc-ref account "Account.enable"))))))) + marionette)) + + (unless #$provisioning? (test-skip 1)) + (test-assert "jami account parameters" + (marionette-eval + '(begin + (use-modules (gnu services herd) + (rnrs base) + (srfi srfi-1)) + + (with-shepherd-action 'jami ('list-account-details) results + (let ((account-details (assoc-ref (car results) + #$username))) + (assert (lset<= + equal? + '(("Account.hostname" . + "bootstrap.me;fallback.another.host") + ("Account.peerDiscovery" . "false") + ("Account.rendezVous" . "true") + ("RingNS.uri" . "https://my.name.server")) + account-details))))) + marionette)) + + (test-end) + (exit (= (test-runner-fail-count (test-runner-current)) 0))))) + + (gexp->derivation (if provisioning? + "jami-provisioning-test" + "jami-test") + test)) + +(define %test-jami + (system-test + (name "jami") + (description "Basic tests for the jami service.") + (value (run-jami-test)))) + +(define %test-jami-provisioning + (system-test + (name "jami-provisioning") + (description "Provisioning test for the jami service.") + (value (run-jami-test #:provisioning? #t)))) + +;; Local Variables: +;; eval: (put 'with-retries 'scheme-indent-function 2) +;; End: diff --git a/tests/services/telephony.scm b/tests/services/telephony.scm new file mode 100644 index 0000000000..b4a0f120d4 --- /dev/null +++ b/tests/services/telephony.scm @@ -0,0 +1,446 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Maxim Cournoyer +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (tests services telephony) + #:use-module (gnu build jami-service) + #:use-module (gnu services telephony) + #:use-module (srfi srfi-64)) + +;;; Tests for the (gnu services telephony) and related modules. + +(test-begin "jami-service") + +(define parse-dbus-reply + (@@ (gnu build jami-service) parse-dbus-reply)) + +(define parse-account-ids + (@@ (gnu build jami-service) parse-account-ids)) + +(define parse-account-details + (@@ (gnu build jami-service) parse-account-details)) + +(define parse-contacts + (@@ (gnu build jami-service) parse-contacts)) + +(define jami-account->alist + (@@ (gnu services telephony) jami-account->alist)) + +;; $ dbus-send --print-reply --dest="cx.ring.Ring" \ +;; "/cx/ring/Ring/ConfigurationManager" \ +;; "cx.ring.Ring.ConfigurationManager.getAccountList" +(define getAccountList-reply "\ +method return time=1622217253.386711 sender=:1.7 -> destination=:1.14 serial=140 reply_serial=2 + array [ + string \"addf37fbb558d6a0\" + string \"d5cbeb7d08c98a65\" + string \"398af0c6b74ce101\" + ] +") + +(test-equal "parse-account-ids" + '("addf37fbb558d6a0" "d5cbeb7d08c98a65" "398af0c6b74ce101") + (parse-account-ids getAccountList-reply)) + +;; $ dbus-send --print-reply --dest="cx.ring.Ring" \ +;; "/cx/ring/Ring/ConfigurationManager" \ +;; "cx.ring.Ring.ConfigurationManager.getAccountDetails" \ +;; 'string:398af0c6b74ce101' +(define getAccountDetails-reply "\ +method return time=1622254991.789588 sender=:1.7 -> destination=:1.19 serial=145 reply_serial=2 + array [ + dict entry( + string \"Account.accountDiscovery\" + string \"false\" + ) + dict entry( + string \"Account.accountPublish\" + string \"false\" + ) + dict entry( + string \"Account.activeCallLimit\" + string \"-1\" + ) + dict entry( + string \"Account.alias\" + string \"some-rendezvous-point-name\" + ) + dict entry( + string \"Account.allModeratorEnabled\" + string \"true\" + ) + dict entry( + string \"Account.allowCertFromContact\" + string \"true\" + ) + dict entry( + string \"Account.allowCertFromHistory\" + string \"true\" + ) + dict entry( + string \"Account.allowCertFromTrusted\" + string \"true\" + ) + dict entry( + string \"Account.archiveHasPassword\" + string \"false\" + ) + dict entry( + string \"Account.audioPortMax\" + string \"32766\" + ) + dict entry( + string \"Account.audioPortMin\" + string \"16384\" + ) + dict entry( + string \"Account.autoAnswer\" + string \"false\" + ) + dict entry( + string \"Account.defaultModerators\" + string \"\" + ) + dict entry( + string \"Account.deviceID\" + string \"94b4070fc7a8afa8482c777a9822c52e6af2e1bd\" + ) + dict entry( + string \"Account.deviceName\" + string \"some-device\" + ) + dict entry( + string \"Account.dhtProxyListUrl\" + string \"https://config.jami.net/proxyList\" + ) + dict entry( + string \"Account.displayName\" + string \"some-rendezvous-point-name\" + ) + dict entry( + string \"Account.dtmfType\" + string \"overrtp\" + ) + dict entry( + string \"Account.enable\" + string \"true\" + ) + dict entry( + string \"Account.hasCustomUserAgent\" + string \"false\" + ) + dict entry( + string \"Account.hostname\" + string \"bootstrap.jami.net\" + ) + dict entry( + string \"Account.localInterface\" + string \"default\" + ) + dict entry( + string \"Account.localModeratorsEnabled\" + string \"true\" + ) + dict entry( + string \"Account.mailbox\" + string \"\" + ) + dict entry( + string \"Account.managerUri\" + string \"\" + ) + dict entry( + string \"Account.managerUsername\" + string \"\" + ) + dict entry( + string \"Account.peerDiscovery\" + string \"false\" + ) + dict entry( + string \"Account.presenceSubscribeSupported\" + string \"true\" + ) + dict entry( + string \"Account.proxyEnabled\" + string \"false\" + ) + dict entry( + string \"Account.proxyPushToken\" + string \"\" + ) + dict entry( + string \"Account.proxyServer\" + string \"dhtproxy.jami.net:[80-95]\" + ) + dict entry( + string \"Account.publishedAddress\" + string \"\" + ) + dict entry( + string \"Account.publishedPort\" + string \"5060\" + ) + dict entry( + string \"Account.publishedSameAsLocal\" + string \"true\" + ) + dict entry( + string \"Account.rendezVous\" + string \"true\" + ) + dict entry( + string \"Account.ringtoneEnabled\" + string \"true\" + ) + dict entry( + string \"Account.ringtonePath\" + string \"/usr/share/ring/ringtones/default.opus\" + ) + dict entry( + string \"Account.type\" + string \"RING\" + ) + dict entry( + string \"Account.upnpEnabled\" + string \"true\" + ) + dict entry( + string \"Account.useragent\" + string \"\" + ) + dict entry( + string \"Account.username\" + string \"ccb8bbe2382343f7feb140710ab48aaf1b55634e\" + ) + dict entry( + string \"Account.videoEnabled\" + string \"true\" + ) + dict entry( + string \"Account.videoPortMax\" + string \"65534\" + ) + dict entry( + string \"Account.videoPortMin\" + string \"49152\" + ) + dict entry( + string \"DHT.PublicInCalls\" + string \"true\" + ) + dict entry( + string \"DHT.port\" + string \"7766\" + ) + dict entry( + string \"RingNS.account\" + string \"3989b55313a911b6f0c004748b49b254f35c9ef6\" + ) + dict entry( + string \"RingNS.uri\" + string \"\" + ) + dict entry( + string \"SRTP.enable\" + string \"true\" + ) + dict entry( + string \"SRTP.keyExchange\" + string \"sdes\" + ) + dict entry( + string \"SRTP.rtpFallback\" + string \"false\" + ) + dict entry( + string \"STUN.enable\" + string \"false\" + ) + dict entry( + string \"STUN.server\" + string \"\" + ) + dict entry( + string \"TLS.certificateFile\" + string \"/var/lib/jami/.local/share/jami/398af0c6b74ce101/ring_device.crt\" + ) + dict entry( + string \"TLS.certificateListFile\" + string \"\" + ) + dict entry( + string \"TLS.ciphers\" + string \"\" + ) + dict entry( + string \"TLS.method\" + string \"Automatic\" + ) + dict entry( + string \"TLS.negotiationTimeoutSec\" + string \"-1\" + ) + dict entry( + string \"TLS.password\" + string \"\" + ) + dict entry( + string \"TLS.privateKeyFile\" + string \"/var/lib/jami/.local/share/jami/398af0c6b74ce101/ring_device.key\" + ) + dict entry( + string \"TLS.requireClientCertificate\" + string \"true\" + ) + dict entry( + string \"TLS.serverName\" + string \"\" + ) + dict entry( + string \"TLS.verifyClient\" + string \"true\" + ) + dict entry( + string \"TLS.verifyServer\" + string \"true\" + ) + dict entry( + string \"TURN.enable\" + string \"true\" + ) + dict entry( + string \"TURN.password\" + string \"ring\" + ) + dict entry( + string \"TURN.realm\" + string \"ring\" + ) + dict entry( + string \"TURN.server\" + string \"turn.jami.net\" + ) + dict entry( + string \"TURN.username\" + string \"ring\" + ) + ] +") + +(test-equal "parse-account-details; username, alias and display name" + '("ccb8bbe2382343f7feb140710ab48aaf1b55634e" ;username + "some-rendezvous-point-name" ;alias + "some-rendezvous-point-name") ;displayName + (let ((account-details (parse-account-details getAccountDetails-reply))) + (list (assoc-ref account-details "Account.username") + (assoc-ref account-details "Account.alias") + (assoc-ref account-details "Account.displayName")))) + +(define getContacts-reply "\ +method return time=1627014042.752673 sender=:1.113 -> destination=:1.186 serial=220 reply_serial=2 + array [ + array [ + dict entry( + string \"added\" + string \"1578883327\" + ) + dict entry( + string \"confirmed\" + string \"true\" + ) + dict entry( + string \"id\" + string \"1c7d5a09464223442549fef172a3cf6f4de9b01c\" + ) + ] + array [ + dict entry( + string \"added\" + string \"1623107941\" + ) + dict entry( + string \"confirmed\" + string \"true\" + ) + dict entry( + string \"id\" + string \"5903c6c9ac5cb863c64e559add3d5d1c8c563449\" + ) + ] + array [ + dict entry( + string \"added\" + string \"1595996256\" + ) + dict entry( + string \"confirmed\" + string \"true\" + ) + dict entry( + string \"id\" + string \"ff2d72a548693214fb3a0f0f7a943b5e2bb9be03\" + ) + ] + ]") + +(test-equal "parse-account-contacts" + '((("added" . "1578883327") + ("confirmed" . "true") + ("id" . "1c7d5a09464223442549fef172a3cf6f4de9b01c")) + (("added" . "1623107941") + ("confirmed" . "true") + ("id" . "5903c6c9ac5cb863c64e559add3d5d1c8c563449")) + (("added" . "1595996256") + ("confirmed" . "true") + ("id" . "ff2d72a548693214fb3a0f0f7a943b5e2bb9be03"))) + (parse-contacts getContacts-reply)) + +(define getContacts-empty-reply "\ +method return time=1627400787.873988 sender=:1.1197 -> destination=:1.1463 serial=2127 reply_serial=2 + array [ + ]") + +(test-equal "parse-account-contacts, empty array" + '() + (parse-contacts getContacts-empty-reply)) + +(define %dummy-jami-account (jami-account + (archive "/tmp/dummy.gz"))) + +(define %dummy-jami-account-2 (jami-account + (archive "/tmp/dummy.gz") + (rendezvous-point? #t) + (peer-discovery? #f) + (bootstrap-hostnames '("bootstrap.me" + "fallback.another.host")) + (name-server-uri "https://my.name.server"))) + +(test-equal "jami-account->alist, no account detail value set" + '() + (jami-account->alist %dummy-jami-account)) + +(test-equal "jami-account->alist, with account detail values" + '(("Account.hostname" . "bootstrap.me;fallback.another.host") + ("Account.peerDiscovery" . "false") + ("Account.rendezVous" . "true") + ("RingNS.uri" . "https://my.name.server")) + (sort (jami-account->alist %dummy-jami-account-2) + (lambda (x y) + (string<=? (car x) (car y))))) + +(test-end) -- 2.32.0 From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 01 03:58:39 2021 Received: (at 47849) by debbugs.gnu.org; 1 Aug 2021 07:58:39 +0000 Received: from localhost ([127.0.0.1]:35481 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA6Mo-0002Cl-Ql for submit@debbugs.gnu.org; Sun, 01 Aug 2021 03:58:39 -0400 Received: from mailrelay.tugraz.at ([129.27.2.202]:32834) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mA6Mm-0002Cb-AR for 47849@debbugs.gnu.org; Sun, 01 Aug 2021 03:58:37 -0400 Received: from [10.0.0.4] (194-118-35-216.adsl.highway.telekom.at [194.118.35.216]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4Gctmh6cLGz3xMn; Sun, 1 Aug 2021 09:58:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1627804709; bh=YSCQQUP6MMArAGGNfMtwyeSsAHAnqwcdQSJU++51lD0=; h=Subject:From:To:Cc:Date:In-Reply-To:References; b=UXixnBvQcXyV4IOjz0PaSYUCzKTSbIeFWCBG1DWEiolvJ/07G8imQLEtx4P8s0Fsf /fwMymqNOTsbubeRYuOV2JgT9K+0ESQrJg3Q48mGWs14AoUjpjtOu49DAkpJeMmRlm s62Z9zcNjOkJa1uSju9SfnaPbTbbW70du9q34wk4= Message-ID: Subject: Re: [PATCH v3 3/3] services: Add a service for Jami. From: Leo Prikler To: Maxime Devos , 47849@debbugs.gnu.org Date: Sun, 01 Aug 2021 09:58:02 +0200 In-Reply-To: <20210801065857.27657-4-maxim.cournoyer@gmail.com> References: <20210801065857.27657-1-maxim.cournoyer@gmail.com> <20210801065857.27657-4-maxim.cournoyer@gmail.com> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.34.2 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-TUG-Backscatter-control: bt4lQm5Tva3SBgCuw0EnZw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -1.9 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.117 X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 47849 Cc: Maxim Cournoyer X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Hi, Am Sonntag, den 01.08.2021, 02:58 -0400 schrieb Maxim Cournoyer: > [...] > + (let* ((command `(,@(if dbus-send > + (list dbus-send) > + (list (%send-dbus-binary))) You can use non-splicing comma notation for things that are never supposed to be lists. > + ,@(if (or bus (%send-dbus-bus)) > + (list (string-append "--bus=" > + (or bus (%send-dbus- > bus)))) > + '()) You use this style here, but > + (let* ((uid (or (and=> (or user (%send-dbus-user)) > + (compose passwd:uid getpwnam)) -1)) > + (gid (or (and=> (or group (%send-dbus-group)) > + (compose group:gid getgrnam)) -1))) this style here. I personally think using and=> everywhere would make things a little clearer. More importantly, though > +(define* (send-dbus #:key service path interface method > + bus > + dbus-send > + user group > + timeout > + arguments) If you e.g. write (bus (%send-dbus-bus)), I think the argument should already be correctly passed upon the function call, no? > + (chown temp-port uid gid))) > + (lambda () > + (let ((pid (fork+exec-command command > + #:user (or user (%send-dbus- > user)) > + #:group (or group (%send-dbus- > group)) > + #:log-file temp-file))) > + (match (waitpid pid) > + ((_ . status) > + (let ((exit-status (status:exit-val status)) > + (output (call-with-port temp-port get-string- > all))) > + (if (= 0 exit-status) > + output > + (error "the send-dbus command exited with: " > + command exit-status output))))))) Since output is unused in the error case, I think you can move the get- string-all there. It would make a difference if you were to e.g. close temp-port before that. I did not look at the rest of this patch, but 1+2 LGTM. Regards, From debbugs-submit-bounces@debbugs.gnu.org Mon Aug 02 15:17:26 2021 Received: (at 47849-done) by debbugs.gnu.org; 2 Aug 2021 19:17:26 +0000 Received: from localhost ([127.0.0.1]:39305 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mAdRG-0001jm-CV for submit@debbugs.gnu.org; Mon, 02 Aug 2021 15:17:26 -0400 Received: from mail-qv1-f54.google.com ([209.85.219.54]:39552) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mAdRE-0001ja-JL for 47849-done@debbugs.gnu.org; Mon, 02 Aug 2021 15:17:25 -0400 Received: by mail-qv1-f54.google.com with SMTP id d3so9401292qvq.6 for <47849-done@debbugs.gnu.org>; Mon, 02 Aug 2021 12:17:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=tVWSt5E4pi4Rc8vFEdsY0uAXOABTes/j0Gxv9nekRU0=; b=NiDvAAI7GU9u4N3iIGa2dWYgnYanjESr06syuWMLtevx5cdcX4J5H3kd4W43+HAay+ NxNSDC+fEY2OHwkxK0b5niTTxwWqENV5STnXN5MRLAxJEvz6DnMRzX5cB507swSBEYvN i/ryp6Zm+T61OAL36fEwK24w87KNqlNdMXVwFgdLpEqf2fhU2TviPIHSBAIeD640eW43 9/1lIauoFTDu2lBVAe6PpuDeVuMzeEhKg7LXxJB0Pk34rr24dXNnlw+ZJxqgej3pUCEb OuEOzW4NEadDocSSzTe/vIC9fULlh3T1ELexyjinVk639DXadLRqg70L6h0eAvP66Jkx eeKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=tVWSt5E4pi4Rc8vFEdsY0uAXOABTes/j0Gxv9nekRU0=; b=qqqIfWoF4eqborJ26hHUaV4k7Jr617IJN44WSfKUkon2ftA3F7pa3oQUBX2zvI1SVK A+XLg6CNxPEuXI/LiE7GBXe9OetquExi8uzZFoMQ+7eD0oKSGo15AYkLExp5/KIG1vVC Z1r3+jMTiSakp/rV6NGyf5jfu75Y59TQr2i6ek7EJiDDe1xehq9eGkh1PM5+2D6c/feC ma0/2CFR6UBZB5K0eB9Q2FZBmx0vhG35qRQx5+2Wyyju0YHNY4z+9udQso7I1I6eYeRL 0n+326Ae9HRwZoiASzO7o4kOrUVmuGQnnw6MKWXkJ45KeF1nsLe1MbriN29FnBVWpYXD cBbw== X-Gm-Message-State: AOAM533gRDSLO6uQhlMjS8+WGrAQGIjpnxSmYn0FSokqOJOPSKx3OBAx 81bctFGkgGLiXNDa3M1SknI+SN9H6z1dXg== X-Google-Smtp-Source: ABdhPJyK+9RqQ0o2bHodSo+R2i1V50dcU2RBB2n5oSYbdtnHje4dvihCEeRIZct/R7g1A8fWbboeHQ== X-Received: by 2002:a05:6214:1bcf:: with SMTP id m15mr9069344qvc.62.1627931839065; Mon, 02 Aug 2021 12:17:19 -0700 (PDT) Received: from hurd ([207.35.94.204]) by smtp.gmail.com with ESMTPSA id t26sm4970377qtc.44.2021.08.02.12.17.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Aug 2021 12:17:18 -0700 (PDT) From: Maxim Cournoyer To: Leo Prikler Subject: Re: bug#47849: [PATCH] Add a jami-daemon service. References: <20210801065857.27657-1-maxim.cournoyer@gmail.com> <20210801065857.27657-4-maxim.cournoyer@gmail.com> Date: Mon, 02 Aug 2021 15:17:17 -0400 In-Reply-To: (Leo Prikler's message of "Sun, 01 Aug 2021 09:58:02 +0200") Message-ID: <878s1j8xmq.fsf_-_@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849-done Cc: Maxime Devos , 47849-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi Leo, Leo Prikler writes: > Hi, > > Am Sonntag, den 01.08.2021, 02:58 -0400 schrieb Maxim Cournoyer: >> [...] > >> + (let* ((command `(,@(if dbus-send >> + (list dbus-send) >> + (list (%send-dbus-binary))) > You can use non-splicing comma notation for things that are never > supposed to be lists. Good catch! >> + ,@(if (or bus (%send-dbus-bus)) >> + (list (string-append "--bus=" >> + (or bus (%send-dbus- >> bus)))) >> + '()) > You use this style here, but >> + (let* ((uid (or (and=> (or user (%send-dbus-user)) >> + (compose passwd:uid getpwnam)) -1)) >> + (gid (or (and=> (or group (%send-dbus-group)) >> + (compose group:gid getgrnam)) -1))) > this style here. I personally think using and=> everywhere would make > things a little clearer. I tried, but it seemed it had a bigger cognitive load to follow (or, and=>, compose, list, cut all in the same expression), so ended up keeping it as is. > More importantly, though >> +(define* (send-dbus #:key service path interface method >> + bus >> + dbus-send >> + user group >> + timeout >> + arguments) > If you e.g. write (bus (%send-dbus-bus)), I think the argument should > already be correctly passed upon the function call, no? the %send-dbus-bus is a parameter; if we were to provide it as a default value, it would be evaluated at the time the module is read (IIUC), but I want its value to be read at run time, when the procedure is called instead. >> + (chown temp-port uid gid))) >> + (lambda () >> + (let ((pid (fork+exec-command command >> + #:user (or user (%send-dbus- >> user)) >> + #:group (or group (%send-dbus- >> group)) >> + #:log-file temp-file))) >> + (match (waitpid pid) >> + ((_ . status) >> + (let ((exit-status (status:exit-val status)) >> + (output (call-with-port temp-port get-string- >> all))) >> + (if (= 0 exit-status) >> + output >> + (error "the send-dbus command exited with: " >> + command exit-status output))))))) > Since output is unused in the error case, I think you can move the get- > string-all there. It would make a difference if you were to e.g. close > temp-port before that. It's actually used as the last argument of the 'error' call :-). I added it as it was helpful to debug stderr messages from dbus-send. > I did not look at the rest of this patch, but 1+2 LGTM. > > Regards, Thanks a lot for having a look! It's been long in the making. Pushed as commit 69dcc24c9f. Closing. Maxim From debbugs-submit-bounces@debbugs.gnu.org Tue Aug 03 03:35:30 2021 Received: (at 47849) by debbugs.gnu.org; 3 Aug 2021 07:35:30 +0000 Received: from localhost ([127.0.0.1]:39765 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mAoxW-00073u-7O for submit@debbugs.gnu.org; Tue, 03 Aug 2021 03:35:30 -0400 Received: from mailrelay.tugraz.at ([129.27.2.202]:34190) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mAoxT-00073k-3u for 47849@debbugs.gnu.org; Tue, 03 Aug 2021 03:35:28 -0400 Received: from nijino.local (194-118-35-216.adsl.highway.telekom.at [194.118.35.216]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4Gf6974b7Vz1LWpc; Tue, 3 Aug 2021 09:35:23 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 mailrelay.tugraz.at 4Gf6974b7Vz1LWpc DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1627976123; bh=d5qFHldXDqYI/8zq7FMRpk76zhPcB+bbNb0XjbWb4ZU=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=EuCN6cEQtUWiUMjs69TEvb91Tip0X5nIjoO3lIyBNM0ahNbiAmEtZ2d4KYX08faD5 TnfXwu8Q3IjlAInE6e5JFsxmKezzYP+dQSaY/c98hQne2r6+NeeVk3ONeBfk6/PIpU UQfssWu2OBJj6gDdAEUGTag/8lHlcjJX7mwRLZpk= Message-ID: <2a559e87966b2383d39ccfddbb667d67b9d21632.camel@student.tugraz.at> Subject: Re: bug#47849: [PATCH] Add a jami-daemon service. From: Leo Prikler To: Maxim Cournoyer Date: Tue, 03 Aug 2021 09:35:22 +0200 In-Reply-To: <878s1j8xmq.fsf_-_@gmail.com> References: <20210801065857.27657-1-maxim.cournoyer@gmail.com> <20210801065857.27657-4-maxim.cournoyer@gmail.com> <878s1j8xmq.fsf_-_@gmail.com> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.34.2 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-TUG-Backscatter-control: bt4lQm5Tva3SBgCuw0EnZw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -1.9 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.117 X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 47849 Cc: 47849@debbugs.gnu.org, Maxime Devos X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Hi Maxim, Am Montag, den 02.08.2021, 15:17 -0400 schrieb Maxim Cournoyer: > > > + ,@(if (or bus (%send-dbus-bus)) > > > + (list (string-append "--bus=" > > > + (or bus (%send- > > > dbus- > > > bus)))) > > > + '()) > > You use this style here, but > > > + (let* ((uid (or (and=> (or user (%send-dbus-user)) > > > + (compose passwd:uid getpwnam)) > > > -1)) > > > + (gid (or (and=> (or group (%send-dbus-group)) > > > + (compose group:gid getgrnam)) > > > -1))) > > this style here. I personally think using and=> everywhere would > > make > > things a little clearer. > > I tried, but it seemed it had a bigger cognitive load to follow (or, > and=>, compose, list, cut all in the same expression), so ended up > keeping it as is. I think the cognitive burden would in both cases be lessened if we didn't need to write (or stuff (%send-dbus-stuff)) everywhere, which see below. > > More importantly, though > > > +(define* (send-dbus #:key service path interface method > > > + bus > > > + dbus-send > > > + user group > > > + timeout > > > + arguments) > > If you e.g. write (bus (%send-dbus-bus)), I think the argument > > should > > already be correctly passed upon the function call, no? > > the %send-dbus-bus is a parameter; if we were to provide it as a > default > value, it would be evaluated at the time the module is read (IIUC), > but > I want its value to be read at run time, when the procedure is called > instead. That's how define* works though, in my experience: --8<---------------cut here---------------start------------->8--- ;; foo.scm (define-module (foo) #:export (*rand* rand)) (define *rand* (make-parameter 4)) (define* (rand #:optional (value (*rand*))) value) --8<---------------cut here---------------end--------------->8--- --8<---------------cut here---------------start------------->8--- scheme@(guile-user)> ,use (foo) ;; alternatively (load-compiled "foo.go") scheme@(guile-user)> (rand) $1 = 4 scheme@(guile-user)> (parameterize ((*rand* 5)) (rand)) $2 = 5 scheme@(guile-user)> (rand 6) $3 = 6 --8<---------------cut here---------------end--------------->8--- > > > + (chown temp-port uid gid))) > > > + (lambda () > > > + (let ((pid (fork+exec-command command > > > + #:user (or user (%send- > > > dbus- > > > user)) > > > + #:group (or group (%send- > > > dbus- > > > group)) > > > + #:log-file temp-file))) > > > + (match (waitpid pid) > > > + ((_ . status) > > > + (let ((exit-status (status:exit-val status)) > > > + (output (call-with-port temp-port get-string- > > > all))) > > > + (if (= 0 exit-status) > > > + output > > > + (error "the send-dbus command exited with: " > > > + command exit-status output))))))) > > Since output is unused in the error case, I think you can move the > > get- > > string-all there. It would make a difference if you were to e.g. > > close > > temp-port before that. > > It's actually used as the last argument of the 'error' call :-). I > added it as it was helpful to debug stderr messages from dbus-send. My bad, nvm then. > > I did not look at the rest of this patch, but 1+2 LGTM. > > > > Regards, > > Thanks a lot for having a look! It's been long in the making. > > Pushed as commit 69dcc24c9f. As I said, I only looked at parts of it, so this push was perhaps a bit hasty. I recently also hastily pushed something and had to fix it up later. Let's try to keep a cool head and not let the heat get to us :) Regards, From debbugs-submit-bounces@debbugs.gnu.org Tue Aug 03 10:36:54 2021 Received: (at 47849) by debbugs.gnu.org; 3 Aug 2021 14:36:55 +0000 Received: from localhost ([127.0.0.1]:41174 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mAvXK-0005A5-L3 for submit@debbugs.gnu.org; Tue, 03 Aug 2021 10:36:54 -0400 Received: from mail-qt1-f171.google.com ([209.85.160.171]:46931) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mAvXI-00059r-OH for 47849@debbugs.gnu.org; Tue, 03 Aug 2021 10:36:53 -0400 Received: by mail-qt1-f171.google.com with SMTP id c5so1105657qtp.13 for <47849@debbugs.gnu.org>; Tue, 03 Aug 2021 07:36:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=kLhmMUoW5sp5PYZHZS3YHJc3rl7HT8eEuGse+ZNpYno=; b=LkHoDFwwFanIj6luKuF7HC/FIfrDTLtN043Jj3ub1EmLsz+Kn4CcgLZ5y3X8PY1Uib RFncsE8E32QpFGptu1KYkXfwz+QMd/Dmv+U3zAVYK9zMn0b70mbwCPLOy8YKxwCM2ZwQ iflhvd4IExC7pdeWz6C5RQNkSHeaBJ3m6kU9hjo95iR9iVBWEjL4+by422ku6arTJVpD BEFebz17IRGQ9EkSflUDbF04EboOaF6QtWBIyeAHY2dYwnHrSXNL+JhhcdKM/ETPzNNM GpEClZSg0oKaZbU6SLEolu4ezVKf2ZajBR/lleJFxwPTw6E1QB3VYVCE588n3D604C2K DZHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=kLhmMUoW5sp5PYZHZS3YHJc3rl7HT8eEuGse+ZNpYno=; b=o9awSMZJKfg8H+Hw4npHwRNsm4jiWFYdSEnr7JlFHN38+X3utL45J1A03jUy1CPOVy O0OiOFqzNx/h7Y2IqbOxYIQYEkHs0ccyvWN83xMHvIDANX2xrVSYdak/cigTQx831Bry HhEZ/dJDwwJYPeexps2/2a/lWFIAXrLYh5mXps8ATo8HBekB6h6ilTU3DNjChlBu7Bu3 D/2KfjYGgfvhVxrpJ75reb7FqT64rgW7QmigvZGRuNmyb0wrfwiJaFtZsSktIvub0vNd al6fbIQkXmQxM2vsAPFugw3QsmHzJEHV9yUMoi5GZe2WxjHWr24NQrHfxu9YhnFCjtXF AktQ== X-Gm-Message-State: AOAM531qH0/vP+1w7vjpSUF3ycDozXlawbebZy35aBSWrnh7CDJZl9zP Kr4OHtqnRBZqdvDkd5QeOmeusasxHIC85UDC X-Google-Smtp-Source: ABdhPJw0WYVvdNNhqnmv4PpN5zJe5q9M5rD+XXoM0CZehbDskTZwiGTpGovB3LjCOdgE75X+q2fpYw== X-Received: by 2002:ac8:5f86:: with SMTP id j6mr18976608qta.5.1628001406938; Tue, 03 Aug 2021 07:36:46 -0700 (PDT) Received: from hurd (dsl-10-129-132.b2b2c.ca. [72.10.129.132]) by smtp.gmail.com with ESMTPSA id d25sm6074303qtq.55.2021.08.03.07.36.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Aug 2021 07:36:46 -0700 (PDT) From: Maxim Cournoyer To: Leo Prikler Subject: Re: bug#47849: [PATCH] Add a jami-daemon service. References: <20210801065857.27657-1-maxim.cournoyer@gmail.com> <20210801065857.27657-4-maxim.cournoyer@gmail.com> <878s1j8xmq.fsf_-_@gmail.com> <2a559e87966b2383d39ccfddbb667d67b9d21632.camel@student.tugraz.at> Date: Tue, 03 Aug 2021 10:36:45 -0400 In-Reply-To: <2a559e87966b2383d39ccfddbb667d67b9d21632.camel@student.tugraz.at> (Leo Prikler's message of "Tue, 03 Aug 2021 09:35:22 +0200") Message-ID: <87eeba7fya.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 47849 Cc: 47849@debbugs.gnu.org, Maxime Devos X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi Leo, [...] >> > I did not look at the rest of this patch, but 1+2 LGTM. >> > >> > Regards, >> >> Thanks a lot for having a look! It's been long in the making. >> >> Pushed as commit 69dcc24c9f. > As I said, I only looked at parts of it, so this push was perhaps a bit > hasty. I recently also hastily pushed something and had to fix it up > later. Let's try to keep a cool head and not let the heat get to us > :) Point taken; there was an adjustment to be made in (guix self) that I had overlooked; the push ended up breaking 'guix pull' (I quickly reverted and fixed it with the help of Chris Baines -- thank you!). Letting some more time would have perhaps allowed someone to catch that issue (or running 'make as-derivation'). Thanks again, Maxim From unknown Fri Jun 20 07:17:07 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Wed, 01 Sep 2021 11:24:08 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator