/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2023-02-11 06:58:15 UTC
  • Revision ID: teddy@recompile.se-20230211065815-jtffi61tbdrgr875
Suppress warnings

Suppress warnings about mlock()ing uninitialized memory and reading an
ievent struct.

* dracut-module/password-agent.c (send_password_to_socket): Suppress
  "-Wmaybe-uninitialized" when mlock()ing password send buffer.
  (test_read_inotify_event_IN_DELETE_badname): When reading from
    a struct ievent, suppress "-Wstringop-overread".

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python3 -bI
2
 
# -*- mode: python; after-save-hook: (lambda () (let ((command (if (fboundp 'file-local-name) (file-local-name (buffer-file-name)) (or (file-remote-p (buffer-file-name) 'localname) (buffer-file-name))))) (if (= (progn (if (get-buffer "*Test*") (kill-buffer "*Test*")) (process-file-shell-command (format "%s --check" (shell-quote-argument command)) nil "*Test*")) 0) (let ((w (get-buffer-window "*Test*"))) (if w (delete-window w))) (progn (with-current-buffer "*Test*" (compilation-mode)) (display-buffer "*Test*" '(display-buffer-in-side-window)))))); coding: utf-8 -*-
 
2
# -*- coding: utf-8; lexical-binding: t -*-
3
3
#
4
4
# Mandos server - give out binary blobs to connecting clients.
5
5
#
11
11
# "AvahiService" class, and some lines in "main".
12
12
#
13
13
# Everything else is
14
 
# Copyright © 2008-2020 Teddy Hogeborn
15
 
# Copyright © 2008-2020 Björn Påhlsson
 
14
# Copyright © 2008-2022 Teddy Hogeborn
 
15
# Copyright © 2008-2022 Björn Påhlsson
16
16
#
17
17
# This file is part of Mandos.
18
18
#
31
31
#
32
32
# Contact the authors at <mandos@recompile.se>.
33
33
#
34
 
 
35
34
from __future__ import (division, absolute_import, print_function,
36
35
                        unicode_literals)
37
36
 
40
39
except ImportError:
41
40
    pass
42
41
 
 
42
import sys
 
43
import unittest
 
44
import argparse
 
45
import logging
 
46
import os
43
47
try:
44
48
    import SocketServer as socketserver
45
49
except ImportError:
46
50
    import socketserver
47
51
import socket
48
 
import argparse
49
52
import datetime
50
53
import errno
51
54
try:
52
55
    import ConfigParser as configparser
53
56
except ImportError:
54
57
    import configparser
55
 
import sys
56
58
import re
57
 
import os
58
59
import signal
59
60
import subprocess
60
61
import atexit
61
62
import stat
62
 
import logging
63
63
import logging.handlers
64
64
import pwd
65
65
import contextlib
77
77
import itertools
78
78
import collections
79
79
import codecs
80
 
import unittest
81
80
import random
82
81
import shlex
83
82
 
94
93
if sys.version_info.major == 2:
95
94
    __metaclass__ = type
96
95
    str = unicode
 
96
    input = raw_input
97
97
 
98
98
# Add collections.abc.Callable if it does not exist
99
99
try:
143
143
if sys.version_info < (3, 2):
144
144
    configparser.Configparser = configparser.SafeConfigParser
145
145
 
146
 
version = "1.8.14"
 
146
version = "1.8.16"
147
147
stored_state_file = "clients.pickle"
148
148
 
149
149
log = logging.getLogger(os.path.basename(sys.argv[0]))
1045
1045
        if getattr(self, "enabled", False):
1046
1046
            # Already enabled
1047
1047
            return
1048
 
        self.expires = datetime.datetime.utcnow() + self.timeout
1049
1048
        self.enabled = True
1050
1049
        self.last_enabled = datetime.datetime.utcnow()
1051
1050
        self.init_checker()
1074
1073
    def __del__(self):
1075
1074
        self.disable()
1076
1075
 
1077
 
    def init_checker(self):
1078
 
        # Schedule a new checker to be started an 'interval' from now,
1079
 
        # and every interval from then on.
 
1076
    def init_checker(self, randomize_start=False):
 
1077
        # Schedule a new checker to be started a randomly selected
 
1078
        # time (a fraction of 'interval') from now.  This spreads out
 
1079
        # the startup of checkers over time when the server is
 
1080
        # started.
1080
1081
        if self.checker_initiator_tag is not None:
1081
1082
            GLib.source_remove(self.checker_initiator_tag)
 
1083
        interval_milliseconds = int(self.interval.total_seconds()
 
1084
                                    * 1000)
 
1085
        if randomize_start:
 
1086
            delay_milliseconds = random.randrange(
 
1087
                interval_milliseconds + 1)
 
1088
        else:
 
1089
            delay_milliseconds = interval_milliseconds
1082
1090
        self.checker_initiator_tag = GLib.timeout_add(
1083
 
            random.randrange(int(self.interval.total_seconds() * 1000
1084
 
                                 + 1)),
1085
 
            self.start_checker)
1086
 
        # Schedule a disable() when 'timeout' has passed
 
1091
            delay_milliseconds, self.start_checker, randomize_start)
 
1092
        delay = datetime.timedelta(0, 0, 0, delay_milliseconds)
 
1093
        # A checker might take up to an 'interval' of time, so we can
 
1094
        # expire at the soonest one interval after a checker was
 
1095
        # started.  Since the initial checker is delayed, the expire
 
1096
        # time might have to be extended.
 
1097
        now = datetime.datetime.utcnow()
 
1098
        self.expires = now + delay + self.interval
 
1099
        # Schedule a disable() at expire time
1087
1100
        if self.disable_initiator_tag is not None:
1088
1101
            GLib.source_remove(self.disable_initiator_tag)
1089
1102
        self.disable_initiator_tag = GLib.timeout_add(
1090
 
            int(self.timeout.total_seconds() * 1000), self.disable)
1091
 
        # Also start a new checker *right now*.
1092
 
        self.start_checker()
 
1103
            int((self.expires - now).total_seconds() * 1000),
 
1104
            self.disable)
1093
1105
 
1094
1106
    def checker_callback(self, source, condition, connection,
1095
1107
                         command):
1138
1150
    def need_approval(self):
1139
1151
        self.last_approval_request = datetime.datetime.utcnow()
1140
1152
 
1141
 
    def start_checker(self):
 
1153
    def start_checker(self, start_was_randomized=False):
1142
1154
        """Start a new checker subprocess if one is not running.
1143
1155
 
1144
1156
        If a checker already exists, leave it running and do
1194
1206
                GLib.IOChannel.unix_new(pipe[0].fileno()),
1195
1207
                GLib.PRIORITY_DEFAULT, GLib.IO_IN,
1196
1208
                self.checker_callback, pipe[0], command)
 
1209
        if start_was_randomized:
 
1210
            # We were started after a random delay; Schedule a new
 
1211
            # checker to be started an 'interval' from now, and every
 
1212
            # interval from then on.
 
1213
            now = datetime.datetime.utcnow()
 
1214
            self.checker_initiator_tag = GLib.timeout_add(
 
1215
                int(self.interval.total_seconds() * 1000),
 
1216
                self.start_checker)
 
1217
            self.expires = max(self.expires, now + self.interval)
 
1218
            # Don't start a new checker again after same random delay
 
1219
            return False
1197
1220
        # Re-run this periodically if run by GLib.timeout_add
1198
1221
        return True
1199
1222
 
3609
3632
            mandos_dbus_service.client_added_signal(client)
3610
3633
        # Need to initiate checking of clients
3611
3634
        if client.enabled:
3612
 
            client.init_checker()
 
3635
            client.init_checker(randomize_start=True)
3613
3636
 
3614
3637
    tcp_server.enable()
3615
3638
    tcp_server.server_activate()
3658
3681
    cleanup()
3659
3682
 
3660
3683
 
3661
 
def should_only_run_tests():
 
3684
def parse_test_args():
 
3685
    # type: () -> argparse.Namespace
3662
3686
    parser = argparse.ArgumentParser(add_help=False)
3663
3687
    parser.add_argument("--check", action="store_true")
 
3688
    parser.add_argument("--prefix", )
3664
3689
    args, unknown_args = parser.parse_known_args()
3665
 
    run_tests = args.check
3666
 
    if run_tests:
3667
 
        # Remove --check argument from sys.argv
 
3690
    if args.check:
 
3691
        # Remove test options from sys.argv
3668
3692
        sys.argv[1:] = unknown_args
3669
 
    return run_tests
 
3693
    return args
3670
3694
 
3671
3695
# Add all tests from doctest strings
3672
3696
def load_tests(loader, tests, none):
3675
3699
    return tests
3676
3700
 
3677
3701
if __name__ == "__main__":
 
3702
    options = parse_test_args()
3678
3703
    try:
3679
 
        if should_only_run_tests():
3680
 
            # Call using ./mandos --check [--verbose]
3681
 
            unittest.main()
 
3704
        if options.check:
 
3705
            extra_test_prefix = options.prefix
 
3706
            if extra_test_prefix is not None:
 
3707
                if not (unittest.main(argv=[""], exit=False)
 
3708
                        .result.wasSuccessful()):
 
3709
                    sys.exit(1)
 
3710
                class ExtraTestLoader(unittest.TestLoader):
 
3711
                    testMethodPrefix = extra_test_prefix
 
3712
                # Call using ./scriptname --test [--verbose]
 
3713
                unittest.main(argv=[""], testLoader=ExtraTestLoader())
 
3714
            else:
 
3715
                unittest.main(argv=[""])
3682
3716
        else:
3683
3717
            main()
3684
3718
    finally:
3685
3719
        logging.shutdown()
 
3720
 
 
3721
# Local Variables:
 
3722
# run-tests:
 
3723
# (lambda (&optional extra)
 
3724
#   (if (not (funcall run-tests-in-test-buffer default-directory
 
3725
#             extra))
 
3726
#       (funcall show-test-buffer-in-test-window)
 
3727
#     (funcall remove-test-window)
 
3728
#     (if extra (message "Extra tests run successfully!"))))
 
3729
# run-tests-in-test-buffer:
 
3730
# (lambda (dir &optional extra)
 
3731
#   (with-current-buffer (get-buffer-create "*Test*")
 
3732
#     (setq buffer-read-only nil
 
3733
#           default-directory dir)
 
3734
#     (erase-buffer)
 
3735
#     (compilation-mode))
 
3736
#   (let ((process-result
 
3737
#          (let ((inhibit-read-only t))
 
3738
#            (process-file-shell-command
 
3739
#             (funcall get-command-line extra) nil "*Test*"))))
 
3740
#     (and (numberp process-result)
 
3741
#          (= process-result 0))))
 
3742
# get-command-line:
 
3743
# (lambda (&optional extra)
 
3744
#   (let ((quoted-script
 
3745
#          (shell-quote-argument (funcall get-script-name))))
 
3746
#     (format
 
3747
#      (concat "%s --check" (if extra " --prefix=atest" ""))
 
3748
#      quoted-script)))
 
3749
# get-script-name:
 
3750
# (lambda ()
 
3751
#   (if (fboundp 'file-local-name)
 
3752
#       (file-local-name (buffer-file-name))
 
3753
#     (or (file-remote-p (buffer-file-name) 'localname)
 
3754
#         (buffer-file-name))))
 
3755
# remove-test-window:
 
3756
# (lambda ()
 
3757
#   (let ((test-window (get-buffer-window "*Test*")))
 
3758
#     (if test-window (delete-window test-window))))
 
3759
# show-test-buffer-in-test-window:
 
3760
# (lambda ()
 
3761
#   (when (not (get-buffer-window-list "*Test*"))
 
3762
#     (setq next-error-last-buffer (get-buffer "*Test*"))
 
3763
#     (let* ((side (if (>= (window-width) 146) 'right 'bottom))
 
3764
#            (display-buffer-overriding-action
 
3765
#             `((display-buffer-in-side-window) (side . ,side)
 
3766
#               (window-height . fit-window-to-buffer)
 
3767
#               (window-width . fit-window-to-buffer))))
 
3768
#       (display-buffer "*Test*"))))
 
3769
# eval:
 
3770
# (progn
 
3771
#   (let* ((run-extra-tests (lambda () (interactive)
 
3772
#                             (funcall run-tests t)))
 
3773
#          (inner-keymap `(keymap (116 . ,run-extra-tests))) ; t
 
3774
#          (outer-keymap `(keymap (3 . ,inner-keymap))))     ; C-c
 
3775
#     (setq minor-mode-overriding-map-alist
 
3776
#           (cons `(run-tests . ,outer-keymap)
 
3777
#                 minor-mode-overriding-map-alist)))
 
3778
#   (add-hook 'after-save-hook run-tests 90 t))
 
3779
# End: