;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2018, 2020 Oleg Pykhalov ;;; Copyright © 2020 Liliana Marie Prikler ;;; Copyright © 2020 Marius Bakke ;;; Copyright © 2022 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 services sound) #:use-module (gnu services base) #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu services) #:use-module (gnu system pam) #:use-module (gnu system shadow) #:use-module (guix diagnostics) #:use-module (guix gexp) #:use-module (guix packages) #:use-module (guix records) #:use-module (guix store) #:use-module (guix ui) #:use-module (gnu packages audio) #:use-module (gnu packages linux) #:use-module (gnu packages pulseaudio) #:use-module (ice-9 match) #:use-module (srfi srfi-1) #:export (alsa-configuration alsa-configuration? alsa-configuration-alsa-plugins alsa-configuration-pulseaudio? alsa-configuration-extra-options alsa-service-type pulseaudio-configuration pulseaudio-configuration? pulseaudio-configuration-client-conf pulsea
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 muradm <mail@muradm.net>
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
;;;
;;; 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 <http://www.gnu.org/licenses/>.

(define-module (gnu services security)
  #:use-module (gnu packages admin)
  #:use-module (gnu services)
  #:use-module (gnu services configuration)
  #:use-module (gnu services shepherd)
  #:use-module (guix gexp)
  #:use-module (guix packages)
  #:use-module (guix records)
  #:use-module (guix ui)
  #:use-module (ice-9 format)
  #:use-module (ice-9 match)
  #:use-module (srfi srfi-1)
  #:export (fail2ban-configuration
            fail2ban-ignore-cache-configuration
            fail2ban-jail-action-configuration
            fail2ban-jail-configuration
            fail2ban-jail-filter-configuration
            fail2ban-jail-service
            fail2ban-service-type))

(define-configuration/no-serialization fail2ban-ignore-cache-configuration
  (key string "Cache key.")
  (max-count integer "Cache size.")
  (max-time integer "Cache time."))

(define (serialize-fail2ban-ignore-cache-configuration config)
  (match-record config <fail2ban-ignore-cache-configuration>
    (key max-count max-time)
    (format #f "key=\"~a\", max-count=~d, max-time=~d"
            key max-count max-time)))

(define-maybe/no-serialization string)

(define-configuration/no-serialization fail2ban-jail-filter-configuration
  (name string "Filter to use.")
  (mode maybe-string "Mode for filter."))

(define (serialize-fail2ban-jail-filter-configuration config)
  (match-record config <fail2ban-jail-filter-configuration>
    (name mode)
    (format #f "~a~@[[mode=~a]~]" name (maybe-value mode))))

(define (argument? a)
  (and (pair? a)
       (string? (car a))
       (or (string? (cdr a))
           (list-of-strings? (cdr a)))))

(define list-of-arguments? (list-of argument?))

(define-configuration/no-serialization fail2ban-jail-action-configuration
  (name string "Action name.")
  (arguments (list-of-arguments '()) "Action arguments."))

(define list-of-fail2ban-jail-actions?
  (list-of fail2ban-jail-action-configuration?))

(define (serialize-fail2ban-jail-action-configuration-arguments args)
  (let* ((multi-value
          (lambda (v)
            (format #f "~a" (string-join v ","))))
         (any-value
          (lambda (v)
            (if (list? v) (string-append "\"" (multi-value v) "\"") v)))
         (key-value
          (lambda (e)
            (format #f "~a=~a" (car e) (any-value (cdr e))))))
    (format #f "~a" (string-join (map key-value args) ","))))

(define (serialize-fail2ban-jail-action-configuration config)
  (match-record config <fail2ban-jail-action-configuration>
    (name arguments)
    (format
     #f "~a~a"
     name
     (if (null? arguments) ""
         (format
          #f "[~a]"
          (serialize-fail2ban-jail-action-configuration-arguments
           arguments))))))

(define fail2ban-backend->string
  (match-lambda
    ('auto "auto")
    ('pyinotify "pyinotify")
    ('gamin "gamin")
    ('polling "polling")
    ('systemd "systemd")
    (unknown
     (leave (G_ "fail2ban: '~a' is not a supported backend~%") unknown))))

(define fail2ban-log-encoding->string
  (match-lambda
    ('auto "auto")
    ('utf-8 "utf-8")
    ('ascii "ascii")
    (unknown
     (leave (G_ "fail2ban: '~a' is not a supported log encoding~%") unknown))))

(define (fail2ban-jail-configuration-serialize-field-name name)
  (cond ((symbol? name)
         (fail2ban-jail-configuration-serialize-field-name
          (symbol->string name)))
        ((string-suffix? "?" name)
         (fail2ban-jail-configuration-serialize-field-name
          (string-drop-right name 1)))
        ((string-prefix? "ban-time-" name)
         (fail2ban-jail-configuration-serialize-field-name
          (string-append "bantime." (substring name 9))))
        ((string-contains name "-")
         (fail2ban-jail-configuration-serialize-field-name
          (string-filter (lambda (c) (not (equal? c #\-))) name)))
        (else name)))

(define (fail2ban-jail-configuration-serialize-string field-name value)
  #~(string-append
     #$(fail2ban-jail-configuration-serialize-field-name field-name)
     " = " #$value "\n"))

(define (fail2ban-jail-configuration-serialize-integer field-name value)
  (fail2ban-jail-configuration-serialize-string
   field-name (number->string value)))

(define (fail2ban-jail-configuration-serialize-boolean field-name value)
  (fail2ban-jail-configuration-serialize-string
   field-name (if value "true" "false")))

(define (fail2ban-jail-configuration-serialize-backend field-name value)
  (if (maybe-value-set? value)
      (fail2ban-jail-configuration-serialize-string
       field-name (fail2ban-backend->string value))
      ""))

(define (fail2ban-jail-configuration-serialize-fail2ban-ignore-cache-configuration field-name value)
  (fail2ban-jail-configuration-serialize-string
   field-name (serialize-fail2ban-ignore-cache-configuration value)))

(define (fail2ban-jail-configuration-serialize-fail2ban-jail-filter-configuration field-name value)
  (fail2ban-jail-configuration-serialize-string
   field-name (serialize-fail2ban-jail-filter-configuration value)))

(define (fail2ban-jail-configuration-serialize-log-encoding field-name value)
  (if (maybe-value-set? value)
      (fail2ban-jail-configuration-serialize-string
       field-name (fail2ban-log-encoding->string value))
      ""))

(define (fail2ban-jail-configuration-serialize-list-of-strings field-name value)
  (if (null? value)
      ""
      (fail2ban-jail-configuration-serialize-string
       field-name (string-join value " "))))

(define (fail2ban-jail-configuration-serialize-list-of-fail2ban-jail-actions field-name value)
  (if (null? value)
      ""
      (fail2ban-jail-configuration-serialize-string
       field-name (string-join
                   (map serialize-fail2ban-jail-action-configuration value) "\n"))))

(define (fail2ban-jail-configuration-serialize-symbol field-name value)
  (fail2ban-jail-configuration-serialize-string field-name (symbol->string value)))

(define-maybe integer (prefix fail2ban-jail-configuration-))
(define-maybe string (prefix fail2ban-jail-configuration