-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdaemon.py
133 lines (114 loc) · 4.02 KB
/
daemon.py
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
127
128
129
130
131
132
133
import paho.mqtt.client as mqtt
import ldap
import traceback
from peewee import *
from db_models import *
import config
class AuthStatus:
SUCCESS = 0
LDAP_ERR = -1
NO_LDAP_ENTRY = -2
NO_SUCH_USER = -3
ACCESS_DEINED = -4
USER_DISABLED = -5
EXCEPTION = -1000
ADS_UF_ACCOUNTDISABLE=2 #https://docs.microsoft.com/en-us/windows/desktop/adschema/a-useraccountcontrol
client=mqtt.Client()
def verify_with_ldap(studnum):
passed = False
status = AuthStatus.LDAP_ERR
conn = ldap.initialize(config.LDAP_URI)
conn.protocol_version = 3
conn.set_option(ldap.OPT_REFERRALS, 0)
conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
try:
bind_result = conn.simple_bind_s(config.LDAP_USER, config.LDAP_PASS)
# print("LDAP: Succesfully authenticated")
search_results = conn.search_s(
'DC=ad,DC=thu-skyworks,DC=org',
ldap.SCOPE_SUBTREE,
"(&(objectClass=person)(employeeNumber={}))".format(studnum),
)
search_results = filter(lambda s: s[0] is not None, search_results)
cnt = 0;
for dn,details in search_results:
# print(details)
if 'userAccountControl' in details: # MS AD
print("userAccountControl =",int(details['userAccountControl'][0]))
if int(details['userAccountControl'][0]) & ADS_UF_ACCOUNTDISABLE:
status = AuthStatus.USER_DISABLED
break
cnt += 1
else:
if cnt>1:
print("Warning: more than one user matched {}".format(studnum))
if cnt>0:
passed = True
status = AuthStatus.SUCCESS
else:
status = AuthStatus.NO_SUCH_USER
except ldap.INVALID_CREDENTIALS:
print("LDAP: Invalid credentials")
except ldap.SERVER_DOWN:
print("LDAP: Server down")
except ldap.LDAPError as e:
print("LDAP: Other LDAP error: ", e)
finally:
conn.unbind_s()
return passed, status
def log_handle(msg):
print("[client]" + str(msg.payload))
def verify_card(msg):
DB_connection_check()
card_number = '{:010d}'.format(int(msg.payload))
status = AuthStatus.EXCEPTION
try:
one = AccountInfo.select().where(AccountInfo.cardnum == card_number).get()
print("Access Request by", one.studnum, one.realname)
assert len(one.studnum) > 0 and int(one.studnum) > 0
success, status = verify_with_ldap(one.studnum)
if success:
client.publish("/command", "open")
print("Valid card, opening the door")
else:
print("Invalid card:", card_number)
AccessRecords.create(
realname = one.realname,
studnum = one.studnum,
cardnum = one.cardnum,
status = status,
).save()
except AccountInfo.DoesNotExist:
print("No Records Found for {}".format(msg.payload))
AccessRecords.create(
cardnum = card_number,
status = AuthStatus.NO_SUCH_USER,
).save()
except Exception as e:
AccessRecords.create(
cardnum = card_number,
status = AuthStatus.EXCEPTION,
).save()
raise e
topics = {
"/log": log_handle,
#"/rs485": log_handle,
"/cardverify": verify_card}
def on_connect(client, userdata, flags, rc):
print("Connected to MQTT broker with result code " + str(rc))
client.subscribe("/cardverify")
client.subscribe("/rs485")
client.subscribe("/log")
def on_message(client, userdata, msg):
# print("Received message " + str(msg.payload) + " from topic " + msg.topic)
try:
if msg.topic in topics:
topics.get(msg.topic)(msg)
except Exception as e:
traceback.print_exc()
DB_Init()
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(config.MQTT_USER, config.MQTT_PASSWORD)
client.connect(config.MQTT_BROKER, 1883)
client.loop_forever()