289
230
if config is None:
291
232
logger.debug(u"Creating client %r", self.name)
233
self.use_dbus = False # During __init__
292
234
# Uppercase and remove spaces from fingerprint for later
293
235
# comparison purposes with return value from the fingerprint()
295
self.fingerprint = (config[u"fingerprint"].upper()
237
self.fingerprint = (config["fingerprint"].upper()
296
238
.replace(u" ", u""))
297
239
logger.debug(u" Fingerprint: %s", self.fingerprint)
298
if u"secret" in config:
299
self.secret = config[u"secret"].decode(u"base64")
300
elif u"secfile" in config:
301
with open(os.path.expanduser(os.path.expandvars
302
(config[u"secfile"])),
240
if "secret" in config:
241
self.secret = config["secret"].decode(u"base64")
242
elif "secfile" in config:
243
with closing(open(os.path.expanduser
245
(config["secfile"])))) as secfile:
304
246
self.secret = secfile.read()
306
#XXX Need to allow secret on demand!
307
248
raise TypeError(u"No secret or secfile for client %s"
309
self.host = config.get(u"host", u"")
250
self.host = config.get("host", "")
310
251
self.created = datetime.datetime.utcnow()
311
252
self.enabled = False
312
253
self.last_enabled = None
313
254
self.last_checked_ok = None
314
self.timeout = string_to_delta(config[u"timeout"])
315
self.interval = string_to_delta(config[u"interval"])
255
self.timeout = string_to_delta(config["timeout"])
256
self.interval = string_to_delta(config["interval"])
316
257
self.disable_hook = disable_hook
317
258
self.checker = None
318
259
self.checker_initiator_tag = None
319
260
self.disable_initiator_tag = None
320
261
self.checker_callback_tag = None
321
self.checker_command = config[u"checker"]
262
self.checker_command = config["checker"]
322
263
self.current_checker_command = None
323
264
self.last_connect = None
324
self.approvals_pending = 0
325
self._approved = None
326
self.approved_by_default = config.get(u"approved_by_default",
328
self.approved_delay = string_to_delta(
329
config[u"approved_delay"])
330
self.approved_duration = string_to_delta(
331
config[u"approved_duration"])
332
self.changedstate = multiprocessing_manager.Condition(multiprocessing_manager.Lock())
334
def send_changedstate(self):
335
self.changedstate.acquire()
336
self.changedstate.notify_all()
337
self.changedstate.release()
265
# Only now, when this client is initialized, can it show up on
267
self.use_dbus = use_dbus
269
self.dbus_object_path = (dbus.ObjectPath
271
+ self.name.replace(".", "_")))
272
dbus.service.Object.__init__(self, bus,
273
self.dbus_object_path)
339
275
def enable(self):
340
276
"""Start this client's checker and timeout hooks"""
341
if getattr(self, u"enabled", False):
344
self.send_changedstate()
345
277
self.last_enabled = datetime.datetime.utcnow()
346
278
# Schedule a new checker to be started an 'interval' from now,
347
279
# and every interval from then on.
348
280
self.checker_initiator_tag = (gobject.timeout_add
349
281
(self.interval_milliseconds(),
350
282
self.start_checker))
283
# Also start a new checker *right now*.
351
285
# Schedule a disable() when 'timeout' has passed
352
286
self.disable_initiator_tag = (gobject.timeout_add
353
287
(self.timeout_milliseconds(),
355
289
self.enabled = True
356
# Also start a new checker *right now*.
292
self.PropertyChanged(dbus.String(u"enabled"),
293
dbus.Boolean(True, variant_level=1))
294
self.PropertyChanged(dbus.String(u"last_enabled"),
295
(_datetime_to_dbus(self.last_enabled,
359
def disable(self, quiet=True):
360
299
"""Disable this client."""
361
300
if not getattr(self, "enabled", False):
364
self.send_changedstate()
366
logger.info(u"Disabling client %s", self.name)
367
if getattr(self, u"disable_initiator_tag", False):
302
logger.info(u"Disabling client %s", self.name)
303
if getattr(self, "disable_initiator_tag", False):
368
304
gobject.source_remove(self.disable_initiator_tag)
369
305
self.disable_initiator_tag = None
370
if getattr(self, u"checker_initiator_tag", False):
306
if getattr(self, "checker_initiator_tag", False):
371
307
gobject.source_remove(self.checker_initiator_tag)
372
308
self.checker_initiator_tag = None
373
309
self.stop_checker()
374
310
if self.disable_hook:
375
311
self.disable_hook(self)
376
312
self.enabled = False
315
self.PropertyChanged(dbus.String(u"enabled"),
316
dbus.Boolean(False, variant_level=1))
377
317
# Do not run this again if called by a gobject.timeout_add
488
444
if self.checker_callback_tag:
489
445
gobject.source_remove(self.checker_callback_tag)
490
446
self.checker_callback_tag = None
491
if getattr(self, u"checker", None) is None:
447
if getattr(self, "checker", None) is None:
493
449
logger.debug(u"Stopping checker for %(name)s", vars(self))
495
451
os.kill(self.checker.pid, signal.SIGTERM)
497
453
#if self.checker.poll() is None:
498
454
# os.kill(self.checker.pid, signal.SIGKILL)
499
455
except OSError, error:
500
456
if error.errno != errno.ESRCH: # No such process
502
458
self.checker = None
504
def dbus_service_property(dbus_interface, signature=u"v",
505
access=u"readwrite", byte_arrays=False):
506
"""Decorators for marking methods of a DBusObjectWithProperties to
507
become properties on the D-Bus.
509
The decorated method will be called with no arguments by "Get"
510
and with one argument by "Set".
512
The parameters, where they are supported, are the same as
513
dbus.service.method, except there is only "signature", since the
514
type from Get() and the type sent to Set() is the same.
516
# Encoding deeply encoded byte arrays is not supported yet by the
517
# "Set" method, so we fail early here:
518
if byte_arrays and signature != u"ay":
519
raise ValueError(u"Byte arrays not supported for non-'ay'"
520
u" signature %r" % signature)
522
func._dbus_is_property = True
523
func._dbus_interface = dbus_interface
524
func._dbus_signature = signature
525
func._dbus_access = access
526
func._dbus_name = func.__name__
527
if func._dbus_name.endswith(u"_dbus_property"):
528
func._dbus_name = func._dbus_name[:-14]
529
func._dbus_get_args_options = {u'byte_arrays': byte_arrays }
534
class DBusPropertyException(dbus.exceptions.DBusException):
535
"""A base class for D-Bus property-related exceptions
537
def __unicode__(self):
538
return unicode(str(self))
541
class DBusPropertyAccessException(DBusPropertyException):
542
"""A property's access permissions disallows an operation.
547
class DBusPropertyNotFound(DBusPropertyException):
548
"""An attempt was made to access a non-existing property.
553
class DBusObjectWithProperties(dbus.service.Object):
554
"""A D-Bus object with properties.
556
Classes inheriting from this can use the dbus_service_property
557
decorator to expose methods as D-Bus properties. It exposes the
558
standard Get(), Set(), and GetAll() methods on the D-Bus.
562
def _is_dbus_property(obj):
563
return getattr(obj, u"_dbus_is_property", False)
565
def _get_all_dbus_properties(self):
566
"""Returns a generator of (name, attribute) pairs
568
return ((prop._dbus_name, prop)
570
inspect.getmembers(self, self._is_dbus_property))
572
def _get_dbus_property(self, interface_name, property_name):
573
"""Returns a bound method if one exists which is a D-Bus
574
property with the specified name and interface.
576
for name in (property_name,
577
property_name + u"_dbus_property"):
578
prop = getattr(self, name, None)
580
or not self._is_dbus_property(prop)
581
or prop._dbus_name != property_name
582
or (interface_name and prop._dbus_interface
583
and interface_name != prop._dbus_interface)):
587
raise DBusPropertyNotFound(self.dbus_object_path + u":"
588
+ interface_name + u"."
591
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"ss",
593
def Get(self, interface_name, property_name):
594
"""Standard D-Bus property Get() method, see D-Bus standard.
596
prop = self._get_dbus_property(interface_name, property_name)
597
if prop._dbus_access == u"write":
598
raise DBusPropertyAccessException(property_name)
600
if not hasattr(value, u"variant_level"):
602
return type(value)(value, variant_level=value.variant_level+1)
604
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"ssv")
605
def Set(self, interface_name, property_name, value):
606
"""Standard D-Bus property Set() method, see D-Bus standard.
608
prop = self._get_dbus_property(interface_name, property_name)
609
if prop._dbus_access == u"read":
610
raise DBusPropertyAccessException(property_name)
611
if prop._dbus_get_args_options[u"byte_arrays"]:
612
# The byte_arrays option is not supported yet on
613
# signatures other than "ay".
614
if prop._dbus_signature != u"ay":
616
value = dbus.ByteArray(''.join(unichr(byte)
620
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"s",
621
out_signature=u"a{sv}")
622
def GetAll(self, interface_name):
623
"""Standard D-Bus property GetAll() method, see D-Bus
626
Note: Will not include properties with access="write".
629
for name, prop in self._get_all_dbus_properties():
631
and interface_name != prop._dbus_interface):
632
# Interface non-empty but did not match
634
# Ignore write-only properties
635
if prop._dbus_access == u"write":
638
if not hasattr(value, u"variant_level"):
641
all[name] = type(value)(value, variant_level=
642
value.variant_level+1)
643
return dbus.Dictionary(all, signature=u"sv")
645
@dbus.service.method(dbus.INTROSPECTABLE_IFACE,
647
path_keyword='object_path',
648
connection_keyword='connection')
649
def Introspect(self, object_path, connection):
650
"""Standard D-Bus method, overloaded to insert property tags.
652
xmlstring = dbus.service.Object.Introspect(self, object_path,
655
document = xml.dom.minidom.parseString(xmlstring)
656
def make_tag(document, name, prop):
657
e = document.createElement(u"property")
658
e.setAttribute(u"name", name)
659
e.setAttribute(u"type", prop._dbus_signature)
660
e.setAttribute(u"access", prop._dbus_access)
662
for if_tag in document.getElementsByTagName(u"interface"):
663
for tag in (make_tag(document, name, prop)
665
in self._get_all_dbus_properties()
666
if prop._dbus_interface
667
== if_tag.getAttribute(u"name")):
668
if_tag.appendChild(tag)
669
# Add the names to the return values for the
670
# "org.freedesktop.DBus.Properties" methods
671
if (if_tag.getAttribute(u"name")
672
== u"org.freedesktop.DBus.Properties"):
673
for cn in if_tag.getElementsByTagName(u"method"):
674
if cn.getAttribute(u"name") == u"Get":
675
for arg in cn.getElementsByTagName(u"arg"):
676
if (arg.getAttribute(u"direction")
678
arg.setAttribute(u"name", u"value")
679
elif cn.getAttribute(u"name") == u"GetAll":
680
for arg in cn.getElementsByTagName(u"arg"):
681
if (arg.getAttribute(u"direction")
683
arg.setAttribute(u"name", u"props")
684
xmlstring = document.toxml(u"utf-8")
686
except (AttributeError, xml.dom.DOMException,
687
xml.parsers.expat.ExpatError), error:
688
logger.error(u"Failed to override Introspection method",
693
class ClientDBus(Client, DBusObjectWithProperties):
694
"""A Client class using D-Bus
697
dbus_object_path: dbus.ObjectPath
698
bus: dbus.SystemBus()
700
# dbus.service.Object doesn't use super(), so we can't either.
702
def __init__(self, bus = None, *args, **kwargs):
704
Client.__init__(self, *args, **kwargs)
705
# Only now, when this client is initialized, can it show up on
707
self.dbus_object_path = (dbus.ObjectPath
709
+ self.name.replace(u".", u"_")))
710
DBusObjectWithProperties.__init__(self, self.bus,
711
self.dbus_object_path)
714
def _datetime_to_dbus(dt, variant_level=0):
715
"""Convert a UTC datetime.datetime() to a D-Bus type."""
716
return dbus.String(dt.isoformat(),
717
variant_level=variant_level)
720
oldstate = getattr(self, u"enabled", False)
721
r = Client.enable(self)
722
if oldstate != self.enabled:
724
self.PropertyChanged(dbus.String(u"enabled"),
725
dbus.Boolean(True, variant_level=1))
726
self.PropertyChanged(
727
dbus.String(u"last_enabled"),
728
self._datetime_to_dbus(self.last_enabled,
732
def disable(self, quiet = False):
733
oldstate = getattr(self, u"enabled", False)
734
r = Client.disable(self, quiet=quiet)
735
if not quiet and oldstate != self.enabled:
737
self.PropertyChanged(dbus.String(u"enabled"),
738
dbus.Boolean(False, variant_level=1))
741
def __del__(self, *args, **kwargs):
743
self.remove_from_connection()
746
if hasattr(DBusObjectWithProperties, u"__del__"):
747
DBusObjectWithProperties.__del__(self, *args, **kwargs)
748
Client.__del__(self, *args, **kwargs)
750
def checker_callback(self, pid, condition, command,
752
self.checker_callback_tag = None
755
self.PropertyChanged(dbus.String(u"checker_running"),
756
dbus.Boolean(False, variant_level=1))
757
if os.WIFEXITED(condition):
758
exitstatus = os.WEXITSTATUS(condition)
760
self.CheckerCompleted(dbus.Int16(exitstatus),
761
dbus.Int64(condition),
762
dbus.String(command))
765
self.CheckerCompleted(dbus.Int16(-1),
766
dbus.Int64(condition),
767
dbus.String(command))
769
return Client.checker_callback(self, pid, condition, command,
772
def checked_ok(self, *args, **kwargs):
773
r = Client.checked_ok(self, *args, **kwargs)
775
self.PropertyChanged(
776
dbus.String(u"last_checked_ok"),
777
(self._datetime_to_dbus(self.last_checked_ok,
781
def start_checker(self, *args, **kwargs):
782
old_checker = self.checker
783
if self.checker is not None:
784
old_checker_pid = self.checker.pid
786
old_checker_pid = None
787
r = Client.start_checker(self, *args, **kwargs)
788
# Only if new checker process was started
789
if (self.checker is not None
790
and old_checker_pid != self.checker.pid):
792
self.CheckerStarted(self.current_checker_command)
793
self.PropertyChanged(
794
dbus.String(u"checker_running"),
795
dbus.Boolean(True, variant_level=1))
798
def stop_checker(self, *args, **kwargs):
799
old_checker = getattr(self, u"checker", None)
800
r = Client.stop_checker(self, *args, **kwargs)
801
if (old_checker is not None
802
and getattr(self, u"checker", None) is None):
803
460
self.PropertyChanged(dbus.String(u"checker_running"),
804
461
dbus.Boolean(False, variant_level=1))
807
def _reset_approved(self):
808
self._approved = None
811
def approve(self, value=True):
812
self._approved = value
813
gobject.timeout_add(self._timedelta_to_milliseconds(self.approved_duration, self._reset_approved))
815
def approved_pending(self):
816
return self.approvals_pending > 0
819
## D-Bus methods, signals & properties
463
def still_valid(self):
464
"""Has the timeout not yet passed for this client?"""
465
if not getattr(self, "enabled", False):
467
now = datetime.datetime.utcnow()
468
if self.last_checked_ok is None:
469
return now < (self.created + self.timeout)
471
return now < (self.last_checked_ok + self.timeout)
473
## D-Bus methods & signals
820
474
_interface = u"se.bsnet.fukt.Mandos.Client"
477
CheckedOK = dbus.service.method(_interface)(checked_ok)
478
CheckedOK.__name__ = "CheckedOK"
824
480
# CheckerCompleted - signal
825
@dbus.service.signal(_interface, signature=u"nxs")
481
@dbus.service.signal(_interface, signature="nxs")
826
482
def CheckerCompleted(self, exitcode, waitstatus, command):
830
486
# CheckerStarted - signal
831
@dbus.service.signal(_interface, signature=u"s")
487
@dbus.service.signal(_interface, signature="s")
832
488
def CheckerStarted(self, command):
492
# GetAllProperties - method
493
@dbus.service.method(_interface, out_signature="a{sv}")
494
def GetAllProperties(self):
496
return dbus.Dictionary({
498
dbus.String(self.name, variant_level=1),
499
dbus.String("fingerprint"):
500
dbus.String(self.fingerprint, variant_level=1),
502
dbus.String(self.host, variant_level=1),
503
dbus.String("created"):
504
_datetime_to_dbus(self.created, variant_level=1),
505
dbus.String("last_enabled"):
506
(_datetime_to_dbus(self.last_enabled,
508
if self.last_enabled is not None
509
else dbus.Boolean(False, variant_level=1)),
510
dbus.String("enabled"):
511
dbus.Boolean(self.enabled, variant_level=1),
512
dbus.String("last_checked_ok"):
513
(_datetime_to_dbus(self.last_checked_ok,
515
if self.last_checked_ok is not None
516
else dbus.Boolean (False, variant_level=1)),
517
dbus.String("timeout"):
518
dbus.UInt64(self.timeout_milliseconds(),
520
dbus.String("interval"):
521
dbus.UInt64(self.interval_milliseconds(),
523
dbus.String("checker"):
524
dbus.String(self.checker_command,
526
dbus.String("checker_running"):
527
dbus.Boolean(self.checker is not None,
529
dbus.String("object_path"):
530
dbus.ObjectPath(self.dbus_object_path,
534
# IsStillValid - method
535
IsStillValid = (dbus.service.method(_interface, out_signature="b")
537
IsStillValid.__name__ = "IsStillValid"
836
539
# PropertyChanged - signal
837
@dbus.service.signal(_interface, signature=u"sv")
540
@dbus.service.signal(_interface, signature="sv")
838
541
def PropertyChanged(self, property, value):
843
# Is sent after succesfull transfer of secret from mandos-server to mandos-client
844
@dbus.service.signal(_interface)
850
@dbus.service.signal(_interface, signature=u"s")
851
def Rejected(self, reason):
855
# NeedApproval - signal
856
@dbus.service.signal(_interface, signature=u"db")
857
def NeedApproval(self, timeout, default):
864
@dbus.service.method(_interface, in_signature=u"b")
865
def Approve(self, value):
869
@dbus.service.method(_interface)
871
return self.checked_ok()
545
# SetChecker - method
546
@dbus.service.method(_interface, in_signature="s")
547
def SetChecker(self, checker):
548
"D-Bus setter method"
549
self.checker_command = checker
551
self.PropertyChanged(dbus.String(u"checker"),
552
dbus.String(self.checker_command,
556
@dbus.service.method(_interface, in_signature="s")
557
def SetHost(self, host):
558
"D-Bus setter method"
561
self.PropertyChanged(dbus.String(u"host"),
562
dbus.String(self.host, variant_level=1))
564
# SetInterval - method
565
@dbus.service.method(_interface, in_signature="t")
566
def SetInterval(self, milliseconds):
567
self.interval = datetime.timedelta(0, 0, 0, milliseconds)
569
self.PropertyChanged(dbus.String(u"interval"),
570
(dbus.UInt64(self.interval_milliseconds(),
574
@dbus.service.method(_interface, in_signature="ay",
576
def SetSecret(self, secret):
577
"D-Bus setter method"
578
self.secret = str(secret)
580
# SetTimeout - method
581
@dbus.service.method(_interface, in_signature="t")
582
def SetTimeout(self, milliseconds):
583
self.timeout = datetime.timedelta(0, 0, 0, milliseconds)
585
self.PropertyChanged(dbus.String(u"timeout"),
586
(dbus.UInt64(self.timeout_milliseconds(),
873
589
# Enable - method
874
@dbus.service.method(_interface)
590
Enable = dbus.service.method(_interface)(enable)
591
Enable.__name__ = "Enable"
879
593
# StartChecker - method
880
594
@dbus.service.method(_interface)
891
605
# StopChecker - method
892
@dbus.service.method(_interface)
893
def StopChecker(self):
898
# approved_pending - property
899
@dbus_service_property(_interface, signature=u"b", access=u"read")
900
def approved_pending_dbus_property(self):
901
return dbus.Boolean(self.approved_pending())
903
# approved_by_default - property
904
@dbus_service_property(_interface, signature=u"b",
906
def approved_by_default_dbus_property(self):
907
return dbus.Boolean(self.approved_by_default)
909
# approved_delay - property
910
@dbus_service_property(_interface, signature=u"t",
912
def approved_delay_dbus_property(self):
913
return dbus.UInt64(self.approved_delay_milliseconds())
915
# approved_duration - property
916
@dbus_service_property(_interface, signature=u"t",
918
def approved_duration_dbus_property(self):
919
return dbus.UInt64(self._timedelta_to_milliseconds(
920
self.approved_duration))
923
@dbus_service_property(_interface, signature=u"s", access=u"read")
924
def name_dbus_property(self):
925
return dbus.String(self.name)
927
# fingerprint - property
928
@dbus_service_property(_interface, signature=u"s", access=u"read")
929
def fingerprint_dbus_property(self):
930
return dbus.String(self.fingerprint)
933
@dbus_service_property(_interface, signature=u"s",
935
def host_dbus_property(self, value=None):
936
if value is None: # get
937
return dbus.String(self.host)
940
self.PropertyChanged(dbus.String(u"host"),
941
dbus.String(value, variant_level=1))
944
@dbus_service_property(_interface, signature=u"s", access=u"read")
945
def created_dbus_property(self):
946
return dbus.String(self._datetime_to_dbus(self.created))
948
# last_enabled - property
949
@dbus_service_property(_interface, signature=u"s", access=u"read")
950
def last_enabled_dbus_property(self):
951
if self.last_enabled is None:
952
return dbus.String(u"")
953
return dbus.String(self._datetime_to_dbus(self.last_enabled))
956
@dbus_service_property(_interface, signature=u"b",
958
def enabled_dbus_property(self, value=None):
959
if value is None: # get
960
return dbus.Boolean(self.enabled)
966
# last_checked_ok - property
967
@dbus_service_property(_interface, signature=u"s",
969
def last_checked_ok_dbus_property(self, value=None):
970
if value is not None:
973
if self.last_checked_ok is None:
974
return dbus.String(u"")
975
return dbus.String(self._datetime_to_dbus(self
979
@dbus_service_property(_interface, signature=u"t",
981
def timeout_dbus_property(self, value=None):
982
if value is None: # get
983
return dbus.UInt64(self.timeout_milliseconds())
984
self.timeout = datetime.timedelta(0, 0, 0, value)
986
self.PropertyChanged(dbus.String(u"timeout"),
987
dbus.UInt64(value, variant_level=1))
988
if getattr(self, u"disable_initiator_tag", None) is None:
991
gobject.source_remove(self.disable_initiator_tag)
992
self.disable_initiator_tag = None
994
_timedelta_to_milliseconds((self
1000
# The timeout has passed
1003
self.disable_initiator_tag = (gobject.timeout_add
1004
(time_to_die, self.disable))
1006
# interval - property
1007
@dbus_service_property(_interface, signature=u"t",
1008
access=u"readwrite")
1009
def interval_dbus_property(self, value=None):
1010
if value is None: # get
1011
return dbus.UInt64(self.interval_milliseconds())
1012
self.interval = datetime.timedelta(0, 0, 0, value)
1014
self.PropertyChanged(dbus.String(u"interval"),
1015
dbus.UInt64(value, variant_level=1))
1016
if getattr(self, u"checker_initiator_tag", None) is None:
1018
# Reschedule checker run
1019
gobject.source_remove(self.checker_initiator_tag)
1020
self.checker_initiator_tag = (gobject.timeout_add
1021
(value, self.start_checker))
1022
self.start_checker() # Start one now, too
1024
# checker - property
1025
@dbus_service_property(_interface, signature=u"s",
1026
access=u"readwrite")
1027
def checker_dbus_property(self, value=None):
1028
if value is None: # get
1029
return dbus.String(self.checker_command)
1030
self.checker_command = value
1032
self.PropertyChanged(dbus.String(u"checker"),
1033
dbus.String(self.checker_command,
1036
# checker_running - property
1037
@dbus_service_property(_interface, signature=u"b",
1038
access=u"readwrite")
1039
def checker_running_dbus_property(self, value=None):
1040
if value is None: # get
1041
return dbus.Boolean(self.checker is not None)
1043
self.start_checker()
1047
# object_path - property
1048
@dbus_service_property(_interface, signature=u"o", access=u"read")
1049
def object_path_dbus_property(self):
1050
return self.dbus_object_path # is already a dbus.ObjectPath
1053
@dbus_service_property(_interface, signature=u"ay",
1054
access=u"write", byte_arrays=True)
1055
def secret_dbus_property(self, value):
1056
self.secret = str(value)
606
StopChecker = dbus.service.method(_interface)(stop_checker)
607
StopChecker.__name__ = "StopChecker"
1061
class ProxyClient(object):
1062
def __init__(self, child_pipe, fpr, address):
1063
self._pipe = child_pipe
1064
self._pipe.send(('init', fpr, address))
1065
if not self._pipe.recv():
1068
def __getattribute__(self, name):
1069
if(name == '_pipe'):
1070
return super(ProxyClient, self).__getattribute__(name)
1071
self._pipe.send(('getattr', name))
1072
data = self._pipe.recv()
1073
if data[0] == 'data':
1075
if data[0] == 'function':
1076
def func(*args, **kwargs):
1077
self._pipe.send(('funcall', name, args, kwargs))
1078
return self._pipe.recv()[1]
1081
def __setattr__(self, name, value):
1082
if(name == '_pipe'):
1083
return super(ProxyClient, self).__setattr__(name, value)
1084
self._pipe.send(('setattr', name, value))
1087
class ClientHandler(socketserver.BaseRequestHandler, object):
1088
"""A class to handle client connections.
1090
Instantiated once for each connection to handle it.
612
def peer_certificate(session):
613
"Return the peer's OpenPGP certificate as a bytestring"
614
# If not an OpenPGP certificate...
615
if (gnutls.library.functions
616
.gnutls_certificate_type_get(session._c_object)
617
!= gnutls.library.constants.GNUTLS_CRT_OPENPGP):
618
# ...do the normal thing
619
return session.peer_certificate
620
list_size = ctypes.c_uint(1)
621
cert_list = (gnutls.library.functions
622
.gnutls_certificate_get_peers
623
(session._c_object, ctypes.byref(list_size)))
624
if not bool(cert_list) and list_size.value != 0:
625
raise gnutls.errors.GNUTLSError("error getting peer"
627
if list_size.value == 0:
630
return ctypes.string_at(cert.data, cert.size)
633
def fingerprint(openpgp):
634
"Convert an OpenPGP bytestring to a hexdigit fingerprint string"
635
# New GnuTLS "datum" with the OpenPGP public key
636
datum = (gnutls.library.types
637
.gnutls_datum_t(ctypes.cast(ctypes.c_char_p(openpgp),
640
ctypes.c_uint(len(openpgp))))
641
# New empty GnuTLS certificate
642
crt = gnutls.library.types.gnutls_openpgp_crt_t()
643
(gnutls.library.functions
644
.gnutls_openpgp_crt_init(ctypes.byref(crt)))
645
# Import the OpenPGP public key into the certificate
646
(gnutls.library.functions
647
.gnutls_openpgp_crt_import(crt, ctypes.byref(datum),
648
gnutls.library.constants
649
.GNUTLS_OPENPGP_FMT_RAW))
650
# Verify the self signature in the key
651
crtverify = ctypes.c_uint()
652
(gnutls.library.functions
653
.gnutls_openpgp_crt_verify_self(crt, 0, ctypes.byref(crtverify)))
654
if crtverify.value != 0:
655
gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
656
raise gnutls.errors.CertificateSecurityError("Verify failed")
657
# New buffer for the fingerprint
658
buf = ctypes.create_string_buffer(20)
659
buf_len = ctypes.c_size_t()
660
# Get the fingerprint from the certificate into the buffer
661
(gnutls.library.functions
662
.gnutls_openpgp_crt_get_fingerprint(crt, ctypes.byref(buf),
663
ctypes.byref(buf_len)))
664
# Deinit the certificate
665
gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
666
# Convert the buffer to a Python bytestring
667
fpr = ctypes.string_at(buf, buf_len.value)
668
# Convert the bytestring to hexadecimal notation
669
hex_fpr = u''.join(u"%02X" % ord(char) for char in fpr)
673
class TCP_handler(SocketServer.BaseRequestHandler, object):
674
"""A TCP request handler class.
675
Instantiated by IPv6_TCPServer for each request to handle it.
1091
676
Note: This will run in its own forked process."""
1093
678
def handle(self):
1094
with contextlib.closing(self.server.child_pipe) as child_pipe:
1095
logger.info(u"TCP connection from: %s",
1096
unicode(self.client_address))
1097
logger.debug(u"Pipe FD: %d",
1098
self.server.child_pipe.fileno())
1100
session = (gnutls.connection
1101
.ClientSession(self.request,
1103
.X509Credentials()))
1105
# Note: gnutls.connection.X509Credentials is really a
1106
# generic GnuTLS certificate credentials object so long as
1107
# no X.509 keys are added to it. Therefore, we can use it
1108
# here despite using OpenPGP certificates.
1110
#priority = u':'.join((u"NONE", u"+VERS-TLS1.1",
1111
# u"+AES-256-CBC", u"+SHA1",
1112
# u"+COMP-NULL", u"+CTYPE-OPENPGP",
1114
# Use a fallback default, since this MUST be set.
1115
priority = self.server.gnutls_priority
1116
if priority is None:
1117
priority = u"NORMAL"
1118
(gnutls.library.functions
1119
.gnutls_priority_set_direct(session._c_object,
1122
# Start communication using the Mandos protocol
1123
# Get protocol number
1124
line = self.request.makefile().readline()
1125
logger.debug(u"Protocol version: %r", line)
1127
if int(line.strip().split()[0]) > 1:
1129
except (ValueError, IndexError, RuntimeError), error:
1130
logger.error(u"Unknown protocol version: %s", error)
1133
# Start GnuTLS connection
1136
except gnutls.errors.GNUTLSError, error:
1137
logger.warning(u"Handshake failed: %s", error)
1138
# Do not run session.bye() here: the session is not
1139
# established. Just abandon the request.
1141
logger.debug(u"Handshake succeeded")
1143
approval_required = False
1146
fpr = self.fingerprint(self.peer_certificate
1148
except (TypeError, gnutls.errors.GNUTLSError), error:
1149
logger.warning(u"Bad certificate: %s", error)
1151
logger.debug(u"Fingerprint: %s", fpr)
1154
client = ProxyClient(child_pipe, fpr,
1155
self.client_address)
1159
if client.approved_delay:
1160
delay = client.approved_delay
1161
client.approvals_pending += 1
1162
approval_required = True
1165
if not client.enabled:
1166
logger.warning(u"Client %s is disabled",
1168
if self.server.use_dbus:
1170
client.Rejected("Disabled")
1173
if client._approved or not client.approved_delay:
1174
#We are approved or approval is disabled
1176
elif client._approved is None:
1177
logger.info(u"Client %s need approval",
1179
if self.server.use_dbus:
1181
client.NeedApproval(
1182
client.approved_delay_milliseconds(),
1183
client.approved_by_default)
1185
logger.warning(u"Client %s was not approved",
1187
if self.server.use_dbus:
1189
client.Rejected("Disapproved")
1192
#wait until timeout or approved
1193
#x = float(client._timedelta_to_milliseconds(delay))
1194
time = datetime.datetime.now()
1195
client.changedstate.acquire()
1196
client.changedstate.wait(float(client._timedelta_to_milliseconds(delay) / 1000))
1197
client.changedstate.release()
1198
time2 = datetime.datetime.now()
1199
if (time2 - time) >= delay:
1200
if not client.approved_by_default:
1201
logger.warning("Client %s timed out while"
1202
" waiting for approval",
1204
if self.server.use_dbus:
1206
client.Rejected("Time out")
1211
delay -= time2 - time
1214
while sent_size < len(client.secret):
1215
# XXX handle session exception
1216
sent = session.send(client.secret[sent_size:])
1217
logger.debug(u"Sent: %d, remaining: %d",
1218
sent, len(client.secret)
1219
- (sent_size + sent))
1222
logger.info(u"Sending secret to %s", client.name)
1223
# bump the timeout as if seen
1225
if self.server.use_dbus:
1230
if approval_required:
1231
client.approvals_pending -= 1
1235
def peer_certificate(session):
1236
"Return the peer's OpenPGP certificate as a bytestring"
1237
# If not an OpenPGP certificate...
1238
if (gnutls.library.functions
1239
.gnutls_certificate_type_get(session._c_object)
1240
!= gnutls.library.constants.GNUTLS_CRT_OPENPGP):
1241
# ...do the normal thing
1242
return session.peer_certificate
1243
list_size = ctypes.c_uint(1)
1244
cert_list = (gnutls.library.functions
1245
.gnutls_certificate_get_peers
1246
(session._c_object, ctypes.byref(list_size)))
1247
if not bool(cert_list) and list_size.value != 0:
1248
raise gnutls.errors.GNUTLSError(u"error getting peer"
1250
if list_size.value == 0:
1253
return ctypes.string_at(cert.data, cert.size)
1256
def fingerprint(openpgp):
1257
"Convert an OpenPGP bytestring to a hexdigit fingerprint"
1258
# New GnuTLS "datum" with the OpenPGP public key
1259
datum = (gnutls.library.types
1260
.gnutls_datum_t(ctypes.cast(ctypes.c_char_p(openpgp),
1263
ctypes.c_uint(len(openpgp))))
1264
# New empty GnuTLS certificate
1265
crt = gnutls.library.types.gnutls_openpgp_crt_t()
1266
(gnutls.library.functions
1267
.gnutls_openpgp_crt_init(ctypes.byref(crt)))
1268
# Import the OpenPGP public key into the certificate
1269
(gnutls.library.functions
1270
.gnutls_openpgp_crt_import(crt, ctypes.byref(datum),
1271
gnutls.library.constants
1272
.GNUTLS_OPENPGP_FMT_RAW))
1273
# Verify the self signature in the key
1274
crtverify = ctypes.c_uint()
1275
(gnutls.library.functions
1276
.gnutls_openpgp_crt_verify_self(crt, 0,
1277
ctypes.byref(crtverify)))
1278
if crtverify.value != 0:
1279
gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
1280
raise (gnutls.errors.CertificateSecurityError
1282
# New buffer for the fingerprint
1283
buf = ctypes.create_string_buffer(20)
1284
buf_len = ctypes.c_size_t()
1285
# Get the fingerprint from the certificate into the buffer
1286
(gnutls.library.functions
1287
.gnutls_openpgp_crt_get_fingerprint(crt, ctypes.byref(buf),
1288
ctypes.byref(buf_len)))
1289
# Deinit the certificate
1290
gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
1291
# Convert the buffer to a Python bytestring
1292
fpr = ctypes.string_at(buf, buf_len.value)
1293
# Convert the bytestring to hexadecimal notation
1294
hex_fpr = u''.join(u"%02X" % ord(char) for char in fpr)
1298
class MultiprocessingMixIn(object):
1299
"""Like socketserver.ThreadingMixIn, but with multiprocessing"""
1300
def sub_process_main(self, request, address):
1302
self.finish_request(request, address)
1304
self.handle_error(request, address)
1305
self.close_request(request)
1307
def process_request(self, request, address):
1308
"""Start a new process to process the request."""
1309
multiprocessing.Process(target = self.sub_process_main,
1310
args = (request, address)).start()
1312
class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object):
1313
""" adds a pipe to the MixIn """
1314
def process_request(self, request, client_address):
1315
"""Overrides and wraps the original process_request().
1317
This function creates a new pipe in self.pipe
1319
parent_pipe, self.child_pipe = multiprocessing.Pipe()
1321
super(MultiprocessingMixInWithPipe,
1322
self).process_request(request, client_address)
1323
self.child_pipe.close()
1324
self.add_pipe(parent_pipe)
1326
def add_pipe(self, parent_pipe):
1327
"""Dummy function; override as necessary"""
1330
class IPv6_TCPServer(MultiprocessingMixInWithPipe,
1331
socketserver.TCPServer, object):
679
logger.info(u"TCP connection from: %s",
680
unicode(self.client_address))
681
session = (gnutls.connection
682
.ClientSession(self.request,
686
line = self.request.makefile().readline()
687
logger.debug(u"Protocol version: %r", line)
689
if int(line.strip().split()[0]) > 1:
691
except (ValueError, IndexError, RuntimeError), error:
692
logger.error(u"Unknown protocol version: %s", error)
695
# Note: gnutls.connection.X509Credentials is really a generic
696
# GnuTLS certificate credentials object so long as no X.509
697
# keys are added to it. Therefore, we can use it here despite
698
# using OpenPGP certificates.
700
#priority = ':'.join(("NONE", "+VERS-TLS1.1", "+AES-256-CBC",
701
# "+SHA1", "+COMP-NULL", "+CTYPE-OPENPGP",
703
# Use a fallback default, since this MUST be set.
704
priority = self.server.settings.get("priority", "NORMAL")
705
(gnutls.library.functions
706
.gnutls_priority_set_direct(session._c_object,
711
except gnutls.errors.GNUTLSError, error:
712
logger.warning(u"Handshake failed: %s", error)
713
# Do not run session.bye() here: the session is not
714
# established. Just abandon the request.
716
logger.debug(u"Handshake succeeded")
718
fpr = fingerprint(peer_certificate(session))
719
except (TypeError, gnutls.errors.GNUTLSError), error:
720
logger.warning(u"Bad certificate: %s", error)
723
logger.debug(u"Fingerprint: %s", fpr)
725
for c in self.server.clients:
726
if c.fingerprint == fpr:
730
logger.warning(u"Client not found for fingerprint: %s",
734
# Have to check if client.still_valid(), since it is possible
735
# that the client timed out while establishing the GnuTLS
737
if not client.still_valid():
738
logger.warning(u"Client %(name)s is invalid",
742
## This won't work here, since we're in a fork.
743
# client.checked_ok()
745
while sent_size < len(client.secret):
746
sent = session.send(client.secret[sent_size:])
747
logger.debug(u"Sent: %d, remaining: %d",
748
sent, len(client.secret)
749
- (sent_size + sent))
754
class IPv6_TCPServer(SocketServer.ForkingMixIn,
755
SocketServer.TCPServer, object):
1332
756
"""IPv6-capable TCP server. Accepts 'None' as address and/or port
758
settings: Server settings
759
clients: Set() of Client objects
1335
760
enabled: Boolean; whether this server is activated yet
1336
interface: None or a network interface name (string)
1337
use_ipv6: Boolean; to use IPv6 or not
1339
def __init__(self, server_address, RequestHandlerClass,
1340
interface=None, use_ipv6=True):
1341
self.interface = interface
1343
self.address_family = socket.AF_INET6
1344
socketserver.TCPServer.__init__(self, server_address,
1345
RequestHandlerClass)
762
address_family = socket.AF_INET6
763
def __init__(self, *args, **kwargs):
764
if "settings" in kwargs:
765
self.settings = kwargs["settings"]
766
del kwargs["settings"]
767
if "clients" in kwargs:
768
self.clients = kwargs["clients"]
769
del kwargs["clients"]
770
if "use_ipv6" in kwargs:
771
if not kwargs["use_ipv6"]:
772
self.address_family = socket.AF_INET
773
del kwargs["use_ipv6"]
775
super(IPv6_TCPServer, self).__init__(*args, **kwargs)
1346
776
def server_bind(self):
1347
777
"""This overrides the normal server_bind() function
1348
778
to bind to an interface if one was specified, and also NOT to
1349
779
bind to an address or port if they were not specified."""
1350
if self.interface is not None:
1351
if SO_BINDTODEVICE is None:
1352
logger.error(u"SO_BINDTODEVICE does not exist;"
1353
u" cannot bind to interface %s",
1357
self.socket.setsockopt(socket.SOL_SOCKET,
1361
except socket.error, error:
1362
if error[0] == errno.EPERM:
1363
logger.error(u"No permission to"
1364
u" bind to interface %s",
1366
elif error[0] == errno.ENOPROTOOPT:
1367
logger.error(u"SO_BINDTODEVICE not available;"
1368
u" cannot bind to interface %s",
780
if self.settings["interface"]:
781
# 25 is from /usr/include/asm-i486/socket.h
782
SO_BINDTODEVICE = getattr(socket, "SO_BINDTODEVICE", 25)
784
self.socket.setsockopt(socket.SOL_SOCKET,
786
self.settings["interface"])
787
except socket.error, error:
788
if error[0] == errno.EPERM:
789
logger.error(u"No permission to"
790
u" bind to interface %s",
791
self.settings["interface"])
1372
794
# Only bind(2) the socket if we really need to.
1373
795
if self.server_address[0] or self.server_address[1]:
1374
796
if not self.server_address[0]:
1375
797
if self.address_family == socket.AF_INET6:
1376
any_address = u"::" # in6addr_any
798
any_address = "::" # in6addr_any
1378
800
any_address = socket.INADDR_ANY
1379
801
self.server_address = (any_address,
1381
803
elif not self.server_address[1]:
1382
804
self.server_address = (self.server_address[0],
1384
# if self.interface:
806
# if self.settings["interface"]:
1385
807
# self.server_address = (self.server_address[0],
1388
810
# if_nametoindex
1390
return socketserver.TCPServer.server_bind(self)
1393
class MandosServer(IPv6_TCPServer):
1397
clients: set of Client objects
1398
gnutls_priority GnuTLS priority string
1399
use_dbus: Boolean; to emit D-Bus signals or not
1401
Assumes a gobject.MainLoop event loop.
1403
def __init__(self, server_address, RequestHandlerClass,
1404
interface=None, use_ipv6=True, clients=None,
1405
gnutls_priority=None, use_dbus=True):
1406
self.enabled = False
1407
self.clients = clients
1408
if self.clients is None:
1409
self.clients = set()
1410
self.use_dbus = use_dbus
1411
self.gnutls_priority = gnutls_priority
1412
IPv6_TCPServer.__init__(self, server_address,
1413
RequestHandlerClass,
1414
interface = interface,
1415
use_ipv6 = use_ipv6)
813
return super(IPv6_TCPServer, self).server_bind()
1416
814
def server_activate(self):
1417
815
if self.enabled:
1418
return socketserver.TCPServer.server_activate(self)
816
return super(IPv6_TCPServer, self).server_activate()
1419
817
def enable(self):
1420
818
self.enabled = True
1421
def add_pipe(self, parent_pipe):
1422
# Call "handle_ipc" for both data and EOF events
1423
gobject.io_add_watch(parent_pipe.fileno(),
1424
gobject.IO_IN | gobject.IO_HUP,
1425
functools.partial(self.handle_ipc,
1426
parent_pipe = parent_pipe))
1428
def handle_ipc(self, source, condition, parent_pipe=None,
1429
client_object=None):
1431
gobject.IO_IN: u"IN", # There is data to read.
1432
gobject.IO_OUT: u"OUT", # Data can be written (without
1434
gobject.IO_PRI: u"PRI", # There is urgent data to read.
1435
gobject.IO_ERR: u"ERR", # Error condition.
1436
gobject.IO_HUP: u"HUP" # Hung up (the connection has been
1437
# broken, usually for pipes and
1440
conditions_string = ' | '.join(name
1442
condition_names.iteritems()
1443
if cond & condition)
1444
logger.debug(u"Handling IPC: FD = %d, condition = %s", source,
1447
# error or the other end of multiprocessing.Pipe has closed
1448
if condition & gobject.IO_HUP or condition & gobject.IO_ERR:
1451
# Read a request from the child
1452
request = parent_pipe.recv()
1453
logger.debug(u"IPC request: %s", repr(request))
1454
command = request[0]
1456
if command == 'init':
1458
address = request[2]
1460
for c in self.clients:
1461
if c.fingerprint == fpr:
1465
logger.warning(u"Client not found for fingerprint: %s, ad"
1466
u"dress: %s", fpr, address)
1469
mandos_dbus_service.ClientNotFound(fpr, address)
1470
parent_pipe.send(False)
1473
gobject.io_add_watch(parent_pipe.fileno(),
1474
gobject.IO_IN | gobject.IO_HUP,
1475
functools.partial(self.handle_ipc,
1476
parent_pipe = parent_pipe,
1477
client_object = client))
1478
parent_pipe.send(True)
1479
# remove the old hook in favor of the new above hook on same fileno
1481
if command == 'funcall':
1482
funcname = request[1]
1486
parent_pipe.send(('data', getattr(client_object, funcname)(*args, **kwargs)))
1488
if command == 'getattr':
1489
attrname = request[1]
1490
if callable(client_object.__getattribute__(attrname)):
1491
parent_pipe.send(('function',))
1493
parent_pipe.send(('data', client_object.__getattribute__(attrname)))
1495
if command == 'setattr':
1496
attrname = request[1]
1498
setattr(client_object, attrname, value)
1503
821
def string_to_delta(interval):
1504
822
"""Parse a string and return a datetime.timedelta
1506
>>> string_to_delta(u'7d')
824
>>> string_to_delta('7d')
1507
825
datetime.timedelta(7)
1508
>>> string_to_delta(u'60s')
826
>>> string_to_delta('60s')
1509
827
datetime.timedelta(0, 60)
1510
>>> string_to_delta(u'60m')
828
>>> string_to_delta('60m')
1511
829
datetime.timedelta(0, 3600)
1512
>>> string_to_delta(u'24h')
830
>>> string_to_delta('24h')
1513
831
datetime.timedelta(1)
1514
832
>>> string_to_delta(u'1w')
1515
833
datetime.timedelta(7)
1516
>>> string_to_delta(u'5m 30s')
834
>>> string_to_delta('5m 30s')
1517
835
datetime.timedelta(0, 330)
1519
837
timevalue = datetime.timedelta(0)
1628
962
# Default values for config file for server-global settings
1629
server_defaults = { u"interface": u"",
1634
u"SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP",
1635
u"servicename": u"Mandos",
1636
u"use_dbus": u"True",
1637
u"use_ipv6": u"True",
963
server_defaults = { "interface": "",
968
"SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP",
969
"servicename": "Mandos",
1640
974
# Parse config file for server-global settings
1641
server_config = configparser.SafeConfigParser(server_defaults)
975
server_config = ConfigParser.SafeConfigParser(server_defaults)
1642
976
del server_defaults
1643
server_config.read(os.path.join(options.configdir,
977
server_config.read(os.path.join(options.configdir, "mandos.conf"))
1645
978
# Convert the SafeConfigParser object to a dict
1646
979
server_settings = server_config.defaults()
1647
980
# Use the appropriate methods on the non-string config options
1648
for option in (u"debug", u"use_dbus", u"use_ipv6"):
1649
server_settings[option] = server_config.getboolean(u"DEFAULT",
981
server_settings["debug"] = server_config.getboolean("DEFAULT",
983
server_settings["use_dbus"] = server_config.getboolean("DEFAULT",
985
server_settings["use_ipv6"] = server_config.getboolean("DEFAULT",
1651
987
if server_settings["port"]:
1652
server_settings["port"] = server_config.getint(u"DEFAULT",
988
server_settings["port"] = server_config.getint("DEFAULT",
1654
990
del server_config
1656
992
# Override the settings from the config file with command line
1657
993
# options, if set.
1658
for option in (u"interface", u"address", u"port", u"debug",
1659
u"priority", u"servicename", u"configdir",
1660
u"use_dbus", u"use_ipv6"):
994
for option in ("interface", "address", "port", "debug",
995
"priority", "servicename", "configdir",
996
"use_dbus", "use_ipv6"):
1661
997
value = getattr(options, option)
1662
998
if value is not None:
1663
999
server_settings[option] = value
1665
# Force all strings to be unicode
1666
for option in server_settings.keys():
1667
if type(server_settings[option]) is str:
1668
server_settings[option] = unicode(server_settings[option])
1669
1001
# Now we have our good server settings in "server_settings"
1671
##################################################################
1673
1003
# For convenience
1674
debug = server_settings[u"debug"]
1675
use_dbus = server_settings[u"use_dbus"]
1676
use_ipv6 = server_settings[u"use_ipv6"]
1004
debug = server_settings["debug"]
1005
use_dbus = server_settings["use_dbus"]
1006
use_dbus = False # XXX: Not done yet
1007
use_ipv6 = server_settings["use_ipv6"]
1679
1010
syslogger.setLevel(logging.WARNING)
1680
1011
console.setLevel(logging.WARNING)
1682
if server_settings[u"servicename"] != u"Mandos":
1013
if server_settings["servicename"] != "Mandos":
1683
1014
syslogger.setFormatter(logging.Formatter
1684
(u'Mandos (%s) [%%(process)d]:'
1685
u' %%(levelname)s: %%(message)s'
1686
% server_settings[u"servicename"]))
1015
('Mandos (%s): %%(levelname)s:'
1017
% server_settings["servicename"]))
1688
1019
# Parse config file with clients
1689
client_defaults = { u"timeout": u"1h",
1691
u"checker": u"fping -q -- %%(host)s",
1693
u"approved_delay": u"5m",
1694
u"approved_duration": u"1s",
1020
client_defaults = { "timeout": "1h",
1022
"checker": "fping -q -- %%(host)s",
1696
client_config = configparser.SafeConfigParser(client_defaults)
1697
client_config.read(os.path.join(server_settings[u"configdir"],
1700
global mandos_dbus_service
1701
mandos_dbus_service = None
1703
tcp_server = MandosServer((server_settings[u"address"],
1704
server_settings[u"port"]),
1706
interface=server_settings[u"interface"],
1709
server_settings[u"priority"],
1711
pidfilename = u"/var/run/mandos.pid"
1025
client_config = ConfigParser.SafeConfigParser(client_defaults)
1026
client_config.read(os.path.join(server_settings["configdir"],
1030
tcp_server = IPv6_TCPServer((server_settings["address"],
1031
server_settings["port"]),
1033
settings=server_settings,
1034
clients=clients, use_ipv6=use_ipv6)
1035
pidfilename = "/var/run/mandos.pid"
1713
pidfile = open(pidfilename, u"w")
1037
pidfile = open(pidfilename, "w")
1714
1038
except IOError:
1715
logger.error(u"Could not open file %r", pidfilename)
1039
logger.error("Could not open file %r", pidfilename)
1718
uid = pwd.getpwnam(u"_mandos").pw_uid
1719
gid = pwd.getpwnam(u"_mandos").pw_gid
1042
uid = pwd.getpwnam("_mandos").pw_uid
1043
gid = pwd.getpwnam("_mandos").pw_gid
1720
1044
except KeyError:
1722
uid = pwd.getpwnam(u"mandos").pw_uid
1723
gid = pwd.getpwnam(u"mandos").pw_gid
1046
uid = pwd.getpwnam("mandos").pw_uid
1047
gid = pwd.getpwnam("mandos").pw_gid
1724
1048
except KeyError:
1726
uid = pwd.getpwnam(u"nobody").pw_uid
1727
gid = pwd.getpwnam(u"nobody").pw_gid
1050
uid = pwd.getpwnam("nobody").pw_uid
1051
gid = pwd.getpwnam("nogroup").pw_gid
1728
1052
except KeyError: