~glatzor/dahoam/trunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
dahoam - Pam extension which checks if there's a connection with a known network
"""
# Copyright (C) 2011 Sebastian Heinlein <devel@glatzor.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

__author__  = "Sebastian Heinlein <devel@glatzor.de>"

import ConfigParser
import logging
import logging.handlers
import time

import dbus


NM_IFACE = "org.freedesktop.NetworkManager"
NM_SERVICE = "org.freedesktop.NetworkManager"
NM_PATH = "/org/freedesktop/NetworkManager"
NM_WIRELESS_DEVICE_IFACE = "org.freedesktop.NetworkManager.Device.Wireless"
NM_ACCESS_POINT_IFACE = "org.freedesktop.NetworkManager.AccessPoint"
NM_ACTIVE_CONNECTION_IFACE = "org.freedesktop.NetworkManager.Connection.Active"

# Setup logging
logging.basicConfig(level=logging.DEBUG)
try:
    facility = logging.handlers.SysLogHandler.LOG_AUTH
    _syslog_handler = logging.handlers.SysLogHandler("/dev/log", facility)
except:
    pass
else:
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    log.addHandler(_syslog_handler)


class Dahoam(object):

    def __init__(self, user):
        self.bus = dbus.SystemBus()
        self.user = user
        self.config = ConfigParser.ConfigParser()
        self.config.read("/etc/security/dahoam.conf")

    @property
    def is_connected(self):
        """Return True if there is a connection to a known Wifi network."""
        proxy = self.bus.get_object(NM_SERVICE, NM_PATH)
        prop = dbus.Interface(proxy, dbus.PROPERTIES_IFACE)
        if not prop.Get(NM_IFACE, "WirelessEnabled") or \
           not prop.Get(NM_IFACE, "WirelessHardwareEnabled"):
            log.info("Wifi is disabled")
            return False
        for conn_path in prop.Get(NM_IFACE, "ActiveConnections"):
            conn_proxy = self.bus.get_object(NM_SERVICE, conn_path)
            conn_prop = dbus.Interface(conn_proxy, dbus.PROPERTIES_IFACE)
            for dev_path in conn_prop.Get(NM_ACTIVE_CONNECTION_IFACE,
                                          "Devices"):
                dev_proxy = self.bus.get_object(NM_SERVICE, dev_path)
                dev_prop = dbus.Interface(dev_proxy, dbus.PROPERTIES_IFACE)
                try:
                    access_point = dev_prop.Get(NM_WIRELESS_DEVICE_IFACE,
                                                "ActiveAccessPoint")
                except dbus.exceptions.DBusException:
                    log.debug("Device %s doesn't support wireless", dev_path)
                    continue
                if access_point and self._check_access_point(access_point):
                    return True
        return False

    def _check_access_point(self, access_point):
        """Return True if the access points is known to be safe."""
        ap_proxy = self.bus.get_object(NM_SERVICE, access_point)
        ap_prop = dbus.Interface(ap_proxy, dbus.PROPERTIES_IFACE)
        hw_addr = ap_prop.Get(NM_ACCESS_POINT_IFACE, "HwAddress")
        ssid_bytes = ap_prop.Get(NM_ACCESS_POINT_IFACE, "Ssid")
        ssid = "".join([str(byte) for byte in ssid_bytes])
        log.debug("Checking wifi network %s", ssid)
        if not self.config.has_section(ssid):
            log.debug("Network %s isn't known", ssid)
        elif not self.config.has_option(ssid, "hwaddr"):
            log.debug("There isn't any hardware address sepcified")
        elif not self.config.has_option(ssid, "users"):
            log.debug("There aren't any users specified")
        elif hw_addr != self.config.get(ssid, "hwaddr"):
            log.debug("Hardware addresses don't match")
        elif not self.user in self.config.get(ssid, "users").split(","):
            log.debug("User isn't allowed")
        else:
            log.debug("Network %s is known to be safe", ssid)
            return True
        return False


def pam_sm_authenticate(pamh, flags, argv):
    try:
        user = pamh.get_user(None)
    except pamh.exception, e:
        return e.pam_result
    dahoam = Dahoam(user)
    if dahoam.is_connected:
        return pamh.PAM_SUCCESS
    else:
        return pamh.PAM_AUTH_ERR

def pam_sm_setcred(pamh, flags, argv):
    return pamh.PAM_IGNORE

if __name__ == "__main__":
    dahoam = Dahoam("renate")
    print dahoam.is_connected