28
from dbus.mainloop.glib import DBusGMainLoop
28
from dbus.mainloop.glib import DBusGMainLoop
29
import ctypes
29
import ctypes
32
import logging.handlers
34
# logghandler.setFormatter(logging.Formatter('%(levelname)s %(message)s')
36
logger = logging.Logger('mandos')
37
logger.addHandler(logging.handlers.SysLogHandler(facility = logging.handlers.SysLogHandler.LOG_DAEMON))
31
# This variable is used to optionally bind to a specified interface.
39
# This variable is used to optionally bind to a specified interface.
32
# It is a global variable to fit in with the other variables from the
40
# It is a global variable to fit in with the other variables from the
33
# Avahi server example code.
41
# Avahi server example code.
149
"""Stop this client.
157
"""Stop this client.
150
The possibility that this client might be restarted is left
158
The possibility that this client might be restarted is left
151
open, but not currently used."""
159
open, but not currently used."""
152
if debug:
160
logger.debug(u"Stopping client %s", self.name)
153
sys.stderr.write(u"Stopping client %s\n" % self.name)
154
self.secret = None
161
self.secret = None
155
if self.stop_initiator_tag:
162
if self.stop_initiator_tag:
156
gobject.source_remove(self.stop_initiator_tag)
163
gobject.source_remove(self.stop_initiator_tag)
179
now = datetime.datetime.now()
186
now = datetime.datetime.now()
180
if os.WIFEXITED(condition) \
187
if os.WIFEXITED(condition) \
181
and (os.WEXITSTATUS(condition) == 0):
188
and (os.WEXITSTATUS(condition) == 0):
182
if debug:
189
logger.debug(u"Checker for %(name)s succeeded",
183
sys.stderr.write(u"Checker for %(name)s succeeded\n"
190
vars(self))
185
self.last_seen = now
191
self.last_seen = now
186
gobject.source_remove(self.stop_initiator_tag)
192
gobject.source_remove(self.stop_initiator_tag)
187
self.stop_initiator_tag = gobject.timeout_add\
193
self.stop_initiator_tag = gobject.timeout_add\
188
(self._timeout_milliseconds,
194
(self._timeout_milliseconds,
189
self.stop)
195
self.stop)
190
elif debug:
196
if not os.WIFEXITED(condition):
191
if not os.WIFEXITED(condition):
197
logger.warning(u"Checker for %(name)s crashed?",
192
sys.stderr.write(u"Checker for %(name)s crashed?\n"
198
vars(self))
193
% vars(self))
199
else:
194
else:
200
logger.debug(u"Checker for %(name)s failed",
195
sys.stderr.write(u"Checker for %(name)s failed\n"
201
vars(self))
196
% vars(self))
202
self.checker = None
198
self.checker_callback_tag = None
203
self.checker_callback_tag = None
199
def start_checker(self):
204
def start_checker(self):
200
"""Start a new checker subprocess if one is not running.
205
"""Start a new checker subprocess if one is not running.
201
If a checker already exists, leave it running and do
206
If a checker already exists, leave it running and do
202
nothing."""
207
nothing."""
203
if self.checker is None:
208
if self.checker is None:
204
if debug:
209
logger.debug(u"Starting checker for %s",
205
sys.stderr.write(u"Starting checker for %s\n"
210
self.name)
208
command = self.check_command % self.fqdn
212
command = self.check_command % self.fqdn
209
except TypeError:
213
except TypeError:
210
escaped_attrs = dict((key, re.escape(str(val)))
214
escaped_attrs = dict((key, re.escape(str(val)))
211
for key, val in
215
for key, val in
212
vars(self).iteritems())
216
vars(self).iteritems())
213
command = self.check_command % escaped_attrs
217
try:
218
command = self.check_command % escaped_attrs
219
except TypeError, error:
220
logger.critical(u'Could not format string "%s": %s',
221
self.check_command, error)
222
return True # Try again later
215
self.checker = subprocess.\
224
self.checker = subprocess.\
216
Popen(command,
225
Popen(command,
223
checker_callback)
232
checker_callback)
224
except subprocess.OSError, error:
233
except subprocess.OSError, error:
225
sys.stderr.write(u"Failed to start subprocess: %s\n"
234
logger.error(u"Failed to start subprocess: %s",
227
# Re-run this periodically if run by gobject.timeout_add
236
# Re-run this periodically if run by gobject.timeout_add
228
return True
237
return True
229
def stop_checker(self):
238
def stop_checker(self):
298
Note: This will run in its own forked process."""
307
Note: This will run in its own forked process."""
300
def handle(self):
309
def handle(self):
301
if debug:
310
logger.debug(u"TCP connection from: %s",
302
sys.stderr.write(u"TCP request came\n")
311
unicode(self.client_address))
303
sys.stderr.write(u"Request: %s\n" % self.request)
304
sys.stderr.write(u"Client Address: %s\n"
305
% unicode(self.client_address))
306
sys.stderr.write(u"Server: %s\n" % self.server)
307
session = gnutls.connection.ClientSession(self.request,
312
session = gnutls.connection.ClientSession(self.request,
308
gnutls.connection.\
313
gnutls.connection.\
309
X509Credentials())
314
X509Credentials())
320
session.handshake()
325
session.handshake()
321
except gnutls.errors.GNUTLSError, error:
326
except gnutls.errors.GNUTLSError, error:
322
if debug:
327
logger.debug(u"Handshake failed: %s", error)
323
sys.stderr.write(u"Handshake failed: %s\n" % error)
324
# Do not run session.bye() here: the session is not
328
# Do not run session.bye() here: the session is not
325
# established. Just abandon the request.
329
# established. Just abandon the request.
328
fpr = fingerprint(peer_certificate(session))
332
fpr = fingerprint(peer_certificate(session))
329
except (TypeError, gnutls.errors.GNUTLSError), error:
333
except (TypeError, gnutls.errors.GNUTLSError), error:
330
if debug:
334
logger.debug(u"Bad certificate: %s", error)
331
sys.stderr.write(u"Bad certificate: %s\n" % error)
332
session.bye()
335
session.bye()
334
if debug:
337
logger.debug(u"Fingerprint: %s", fpr)
335
sys.stderr.write(u"Fingerprint: %s\n" % fpr)
336
client = None
338
client = None
337
for c in clients:
339
for c in clients:
338
if c.fingerprint == fpr:
340
if c.fingerprint == fpr:
342
# that the client timed out while establishing the GnuTLS
344
# that the client timed out while establishing the GnuTLS
343
# session.
345
# session.
344
if (not client) or (not client.still_valid()):
346
if (not client) or (not client.still_valid()):
345
if debug:
347
if client:
346
if client:
348
logger.debug(u"Client %(name)s is invalid",
347
sys.stderr.write(u"Client %(name)s is invalid\n"
349
vars(client))
348
% vars(client))
350
else:
349
else:
351
logger.debug(u"Client not found for fingerprint: %s",
350
sys.stderr.write(u"Client not found for "
352
fpr)
351
u"fingerprint: %s\n" % fpr)
352
session.bye()
353
session.bye()
354
sent_size = 0
355
sent_size = 0
355
while sent_size < len(client.secret):
356
while sent_size < len(client.secret):
356
sent = session.send(client.secret[sent_size:])
357
sent = session.send(client.secret[sent_size:])
357
if debug:
358
logger.debug(u"Sent: %d, remaining: %d",
358
sys.stderr.write(u"Sent: %d, remaining: %d\n"
359
sent, len(client.secret)
359
% (sent, len(client.secret)
360
- (sent_size + sent))
360
- (sent_size + sent)))
361
sent_size += sent
361
sent_size += sent
362
session.bye()
362
session.bye()
391
self.options.interface)
391
self.options.interface)
392
except socket.error, error:
392
except socket.error, error:
393
if error[0] == errno.EPERM:
393
if error[0] == errno.EPERM:
394
sys.stderr.write(u"Warning: No permission to" \
394
logger.warning(u"No permission to"
395
u" bind to interface %s\n"
395
u" bind to interface %s",
396
% self.options.interface)
396
self.options.interface)
398
raise error
398
raise error
399
# Only bind(2) the socket if we really need to.
399
# Only bind(2) the socket if we really need to.
453
avahi.DBUS_INTERFACE_ENTRY_GROUP)
453
avahi.DBUS_INTERFACE_ENTRY_GROUP)
454
group.connect_to_signal('StateChanged',
454
group.connect_to_signal('StateChanged',
455
entry_group_state_changed)
455
entry_group_state_changed)
456
if debug:
456
logger.debug(u"Adding service '%s' of type '%s' ...",
457
sys.stderr.write(u"Adding service '%s' of type '%s' ...\n"
457
serviceName, serviceType)
458
% (serviceName, serviceType))
460
group.AddService(
459
group.AddService(
461
serviceInterface, # interface
460
serviceInterface, # interface
479
def server_state_changed(state):
478
def server_state_changed(state):
480
"""From the Avahi server example code"""
479
"""From the Avahi server example code"""
481
if state == avahi.SERVER_COLLISION:
480
if state == avahi.SERVER_COLLISION:
482
sys.stderr.write(u"WARNING: Server name collision\n")
481
logger.warning(u"Server name collision")
483
remove_service()
482
remove_service()
484
elif state == avahi.SERVER_RUNNING:
483
elif state == avahi.SERVER_RUNNING:
485
add_service()
484
add_service()
489
"""From the Avahi server example code"""
488
"""From the Avahi server example code"""
490
global serviceName, server, rename_count
489
global serviceName, server, rename_count
492
if debug:
491
logger.debug(u"state change: %i", state)
493
sys.stderr.write(u"state change: %i\n" % state)
495
if state == avahi.ENTRY_GROUP_ESTABLISHED:
493
if state == avahi.ENTRY_GROUP_ESTABLISHED:
496
if debug:
494
logger.debug(u"Service established.")
497
sys.stderr.write(u"Service established.\n")
498
elif state == avahi.ENTRY_GROUP_COLLISION:
495
elif state == avahi.ENTRY_GROUP_COLLISION:
500
rename_count = rename_count - 1
497
rename_count = rename_count - 1
501
if rename_count > 0:
498
if rename_count > 0:
502
name = server.GetAlternativeServiceName(name)
499
name = server.GetAlternativeServiceName(name)
503
sys.stderr.write(u"WARNING: Service name collision, "
500
logger.warning(u"Service name collision, "
504
u"changing name to '%s' ...\n" % name)
501
u"changing name to '%s' ...", name)
505
remove_service()
502
remove_service()
506
add_service()
503
add_service()
509
sys.stderr.write(u"ERROR: No suitable service name found "
506
logger.error(u"No suitable service name found "
510
u"after %i retries, exiting.\n"
507
u"after %i retries, exiting.",
511
% n_rename)
508
n_rename)
512
main_loop.quit()
509
main_loop.quit()
513
elif state == avahi.ENTRY_GROUP_FAILURE:
510
elif state == avahi.ENTRY_GROUP_FAILURE:
514
sys.stderr.write(u"Error in group state changed %s\n"
511
logger.error(u"Error in group state changed %s",
515
% unicode(error))
512
unicode(error))
516
main_loop.quit()
513
main_loop.quit()
603
def remove_from_clients(client):
600
def remove_from_clients(client):
604
clients.remove(client)
601
clients.remove(client)
605
if not clients:
602
if not clients:
606
if debug:
603
logger.debug(u"No clients left, exiting")
607
sys.stderr.write(u"No clients left, exiting\n")
608
main_loop.quit()
604
main_loop.quit()
610
clients.update(Set(Client(name=section, options=options,
606
clients.update(Set(Client(name=section, options=options,
621
clients=clients)
617
clients=clients)
622
# Find out what random port we got
618
# Find out what random port we got
623
servicePort = tcp_server.socket.getsockname()[1]
619
servicePort = tcp_server.socket.getsockname()[1]
624
if debug:
620
logger.debug(u"Now listening on port %d", servicePort)
625
sys.stderr.write(u"Now listening on port %d\n" % servicePort)
627
if options.interface is not None:
622
if options.interface is not None:
628
serviceInterface = if_nametoindex(options.interface)
623
serviceInterface = if_nametoindex(options.interface)