/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: 2019-08-02 22:16:53 UTC
  • Revision ID: teddy@recompile.se-20190802221653-ic1iko9hbefzwsk7
Fix bug in server Debian package: Fails to start on first install

There has been a very long-standing bug where installation of the
server (the "mandos" Debian package) would fail to start the server
properly right after installation.  It would work on manual (re)start
after installation, or after reboot, and even after package purge and
reinstall, it would then work the first time.  The problem, it turns
out, is when the new "_mandos" user (and corresponding group) is
created, the D-Bus server is not reloaded, and is therefore not aware
of that user, and does not recognize the user and group name in the
/etc/dbus-1/system.d/mandos.conf file.  The Mandos server, when it
tries to start and access the D-Bus, is then not permitted to connect
to its D-Bus bus name, and disables D-Bus use as a fallback measure;
i.e. the server works, but it is not controllable via D-Bus commands
(via mandos-ctl or mandos-monitor).  The next time the D-Bus daemon is
reloaded for any reason, the new user & group would become visible to
the D-Bus daemon and after that, any restart of the Mandos server
would succeed and it would bind to its D-Bus name properly, and
thereby be visible and controllable by mandos-ctl & mandos-monitor.
This was mostly invisible when using sysvinit, but systemd makes the
problem visible since the systemd service file for the Mandos server
is configured to not consider the Mandos server "started" until the
D-Bus name has been bound; this makes the starting of the service wait
for 90 seconds and then fail with a timeout error.

Fixing this should also make the Debian CI autopkgtest tests work.

* debian/mandos.postinst (configure): After creating (or renaming)
                                      user & group, reload D-Bus
                                      daemon (if present).

Show diffs side-by-side

added added

removed removed

Lines of Context:
115
115
if sys.version_info.major == 2:
116
116
    str = unicode
117
117
 
118
 
version = "1.8.4"
 
118
version = "1.8.5"
119
119
stored_state_file = "clients.pickle"
120
120
 
121
121
logger = logging.getLogger()
586
586
        def __init__(self, socket, credentials=None):
587
587
            self._c_object = gnutls.session_t()
588
588
            gnutls_flags = gnutls.CLIENT
589
 
            if gnutls.check_version("3.5.6"):
 
589
            if gnutls.check_version(b"3.5.6"):
590
590
                gnutls_flags |= gnutls.NO_TICKETS
591
591
            if gnutls.has_rawpk:
592
592
                gnutls_flags |= gnutls.ENABLE_RAWPK
794
794
                                                    ctypes.c_size_t)]
795
795
        openpgp_crt_get_fingerprint.restype = _error_code
796
796
 
797
 
    if check_version("3.6.4"):
 
797
    if check_version(b"3.6.4"):
798
798
        certificate_type_get2 = _library.gnutls_certificate_type_get2
799
799
        certificate_type_get2.argtypes = [session_t, ctypes.c_int]
800
800
        certificate_type_get2.restype = _error_code
821
821
    approved:   bool(); 'None' if not yet approved/disapproved
822
822
    approval_delay: datetime.timedelta(); Time to wait for approval
823
823
    approval_duration: datetime.timedelta(); Duration of one approval
824
 
    checker:    subprocess.Popen(); a running checker process used
825
 
                                    to see if the client lives.
826
 
                                    'None' if no process is running.
 
824
    checker: multiprocessing.Process(); a running checker process used
 
825
             to see if the client lives. 'None' if no process is
 
826
             running.
827
827
    checker_callback_tag: a GLib event source tag, or None
828
828
    checker_command: string; External command which is run to check
829
829
                     if client lives.  %() expansions are done at
1036
1036
    def checker_callback(self, source, condition, connection,
1037
1037
                         command):
1038
1038
        """The checker has completed, so take appropriate actions."""
1039
 
        self.checker_callback_tag = None
1040
 
        self.checker = None
1041
1039
        # Read return code from connection (see call_pipe)
1042
1040
        returncode = connection.recv()
1043
1041
        connection.close()
 
1042
        self.checker.join()
 
1043
        self.checker_callback_tag = None
 
1044
        self.checker = None
1044
1045
 
1045
1046
        if returncode >= 0:
1046
1047
            self.last_checker_status = returncode
2287
2288
            approval_required = False
2288
2289
            try:
2289
2290
                if gnutls.has_rawpk:
2290
 
                    fpr = ""
 
2291
                    fpr = b""
2291
2292
                    try:
2292
2293
                        key_id = self.key_id(
2293
2294
                            self.peer_certificate(session))
2297
2298
                    logger.debug("Key ID: %s", key_id)
2298
2299
 
2299
2300
                else:
2300
 
                    key_id = ""
 
2301
                    key_id = b""
2301
2302
                    try:
2302
2303
                        fpr = self.fingerprint(
2303
2304
                            self.peer_certificate(session))
3244
3245
                        for k in ("name", "host"):
3245
3246
                            if isinstance(value[k], bytes):
3246
3247
                                value[k] = value[k].decode("utf-8")
3247
 
                        if not value.has_key("key_id"):
 
3248
                        if "key_id" not in value:
3248
3249
                            value["key_id"] = ""
3249
 
                        elif not value.has_key("fingerprint"):
 
3250
                        elif "fingerprint" not in value:
3250
3251
                            value["fingerprint"] = ""
3251
3252
                    #  old_client_settings
3252
3253
                    # .keys()