32
35
import logging.handlers
34
# logghandler.setFormatter(logging.Formatter('%(levelname)s %(message)s')
36
37
logger = logging.Logger('mandos')
37
logger.addHandler(logging.handlers.SysLogHandler(facility = logging.handlers.SysLogHandler.LOG_DAEMON))
38
syslogger = logging.handlers.SysLogHandler\
39
(facility = logging.handlers.SysLogHandler.LOG_DAEMON)
40
syslogger.setFormatter(logging.Formatter\
41
('%(levelname)s: %(message)s'))
42
logger.addHandler(syslogger)
39
45
# This variable is used to optionally bind to a specified interface.
40
46
# It is a global variable to fit in with the other variables from the
108
114
del _set_interval
109
115
def __init__(self, name=None, options=None, stop_hook=None,
110
fingerprint=None, secret=None, secfile=None, fqdn=None,
111
timeout=None, interval=-1, checker=None):
116
fingerprint=None, secret=None, secfile=None,
117
fqdn=None, timeout=None, interval=-1, checker=None):
113
119
# Uppercase and remove spaces from fingerprint
114
120
# for later comparison purposes with return value of
127
133
self.created = datetime.datetime.now()
128
134
self.last_seen = None
129
135
if timeout is None:
130
timeout = options.timeout
131
self.timeout = timeout
136
self.timeout = options.timeout
138
self.timeout = string_to_delta(timeout)
132
139
if interval == -1:
133
interval = options.interval
140
self.interval = options.interval
135
interval = string_to_delta(interval)
136
self.interval = interval
142
self.interval = string_to_delta(interval)
137
143
self.stop_hook = stop_hook
138
144
self.checker = None
139
145
self.checker_initiator_tag = None
193
199
self.stop_initiator_tag = gobject.timeout_add\
194
200
(self._timeout_milliseconds,
196
if not os.WIFEXITED(condition):
202
elif not os.WIFEXITED(condition):
197
203
logger.warning(u"Checker for %(name)s crashed?",
218
222
command = self.check_command % escaped_attrs
219
223
except TypeError, error:
220
logger.critical(u'Could not format string "%s": %s',
221
self.check_command, error)
224
logger.critical(u'Could not format string "%s":'
225
u' %s', self.check_command, error)
222
226
return True # Try again later
228
logger.debug(u"Starting checker %r for %s",
224
230
self.checker = subprocess.\
226
stdout=subprocess.PIPE,
227
232
close_fds=True, shell=True,
229
self.checker_callback_tag = gobject.\
230
child_watch_add(self.checker.pid,
234
self.checker_callback_tag = gobject.child_watch_add\
236
self.checker_callback)
233
237
except subprocess.OSError, error:
234
238
logger.error(u"Failed to start subprocess: %s",
274
279
def fingerprint(openpgp):
280
"Convert an OpenPGP data string to a hexdigit fingerprint string"
275
281
# New empty GnuTLS certificate
276
282
crt = gnutls.library.types.gnutls_openpgp_crt_t()
277
283
gnutls.library.functions.gnutls_openpgp_crt_init\
506
logger.error(u"No suitable service name found "
507
u"after %i retries, exiting.",
512
logger.error(u"No suitable service name found after %i"
513
u" retries, exiting.", n_rename)
510
515
elif state == avahi.ENTRY_GROUP_FAILURE:
511
516
logger.error(u"Error in group state changed %s",
517
521
def if_nametoindex(interface):
533
537
return interface_index
540
def daemon(nochdir, noclose):
541
"""See daemon(3). Standard BSD Unix function.
542
This should really exist as os.daemon, but it doesn't (yet)."""
549
# Close all standard open file descriptors
550
null = os.open("/dev/null", os.O_NOCTTY | os.O_RDWR)
551
if not stat.S_ISCHR(os.fstat(null).st_mode):
552
raise OSError(errno.ENODEV,
553
"/dev/null not a character device")
554
os.dup2(null, sys.stdin.fileno())
555
os.dup2(null, sys.stdout.fileno())
556
os.dup2(null, sys.stderr.fileno())
561
def killme(status = 0):
562
logger.debug("Stopping server with exit status %d", status)
564
if main_loop_started:
536
570
if __name__ == '__main__':
572
main_loop_started = False
537
573
parser = OptionParser()
538
574
parser.add_option("-i", "--interface", type="string",
539
575
default=None, metavar="IF",
540
576
help="Bind to interface IF")
541
parser.add_option("--cert", type="string", default="cert.pem",
543
help="Public key certificate PEM file to use")
544
parser.add_option("--key", type="string", default="key.pem",
546
help="Private key PEM file to use")
547
parser.add_option("--ca", type="string", default="ca.pem",
549
help="Certificate Authority certificate PEM file to use")
550
parser.add_option("--crl", type="string", default="crl.pem",
552
help="Certificate Revokation List PEM file to use")
553
577
parser.add_option("-p", "--port", type="int", default=None,
554
578
help="Port number to receive requests on")
555
579
parser.add_option("--timeout", type="string", # Parsed later
580
604
parser.error("option --interval: Unparseable time")
582
606
# Parse config file
583
defaults = { "checker": "sleep 1; fping -q -- %%(fqdn)s" }
607
defaults = { "checker": "fping -q -- %%(fqdn)s" }
584
608
client_config = ConfigParser.SafeConfigParser(defaults)
585
609
#client_config.readfp(open("secrets.conf"), "secrets.conf")
586
610
client_config.read("mandos-clients.conf")
597
621
debug = options.debug
624
console = logging.StreamHandler()
625
# console.setLevel(logging.DEBUG)
626
console.setFormatter(logging.Formatter\
627
('%(levelname)s: %(message)s'))
628
logger.addHandler(console)
600
632
def remove_from_clients(client):
601
633
clients.remove(client)
603
635
logger.debug(u"No clients left, exiting")
606
638
clients.update(Set(Client(name=section, options=options,
607
639
stop_hook = remove_from_clients,
608
640
**(dict(client_config\
609
641
.items(section))))
610
642
for section in client_config.sections()))
648
"Cleanup function; run on exit"
650
# From the Avahi server example code
651
if not group is None:
654
# End of Avahi example code
656
for client in clients:
657
client.stop_hook = None
660
atexit.register(cleanup)
663
signal.signal(signal.SIGINT, signal.SIG_IGN)
664
signal.signal(signal.SIGHUP, lambda signum, frame: killme())
665
signal.signal(signal.SIGTERM, lambda signum, frame: killme())
611
667
for client in clients:
625
681
# From the Avahi server example code
626
682
server.connect_to_signal("StateChanged", server_state_changed)
627
server_state_changed(server.GetState())
684
server_state_changed(server.GetState())
685
except dbus.exceptions.DBusException, error:
686
logger.critical(u"DBusException: %s", error)
628
688
# End of Avahi example code
630
690
gobject.io_add_watch(tcp_server.fileno(), gobject.IO_IN,