1 | from django.contrib.auth.models import User |
---|
2 | import socket |
---|
3 | import settings |
---|
4 | |
---|
5 | class SocketAuthBackend(): |
---|
6 | """ |
---|
7 | SocketAuthBackend provides a simple way to authenticate with another process. |
---|
8 | |
---|
9 | The protocol is simple: |
---|
10 | * Open a connection to a socket. |
---|
11 | * On the first line, pass the name of the operation |
---|
12 | * Then, on successive lines, pass additional arguments, one per line |
---|
13 | * Close the write half of the socket |
---|
14 | * The authentication server sends back a reply, one tuple element |
---|
15 | per line |
---|
16 | |
---|
17 | Queries include: |
---|
18 | * AUTHENTICATE(username, password) => boolean |
---|
19 | * FINGER(username) => (first name, last name, email, ) |
---|
20 | """ |
---|
21 | def authenticate(self, username, password, ): |
---|
22 | (result,) = query("AUTHENTICATE", username, password, ) |
---|
23 | print result |
---|
24 | if result == 'true': |
---|
25 | try: |
---|
26 | user = User.objects.get(username=username) |
---|
27 | if len(user.groups.filter(name='local-auth-only')) > 0: |
---|
28 | if user.check_password(password): |
---|
29 | return user |
---|
30 | else: |
---|
31 | return None |
---|
32 | else: |
---|
33 | return user |
---|
34 | except User.DoesNotExist: |
---|
35 | user = User(username=username, password='SocketAuth') |
---|
36 | user.is_staff = False |
---|
37 | user.is_superuser = False |
---|
38 | # Is there a race condition here? Yes. |
---|
39 | # Should I do more error-checking? Yes. |
---|
40 | # Do I care? No. |
---|
41 | (first, last, email,) = query('FINGER', username) |
---|
42 | user.first_name = first |
---|
43 | user.last_name = last |
---|
44 | user.email = email |
---|
45 | user.save() |
---|
46 | return user |
---|
47 | return None |
---|
48 | |
---|
49 | def get_user(self, user_id): |
---|
50 | try: |
---|
51 | return User.objects.get(pk=user_id) |
---|
52 | except User.DoesNotExist: |
---|
53 | return None |
---|
54 | |
---|
55 | |
---|
56 | def query(*args): |
---|
57 | conn = socket.socket(socket.AF_UNIX) |
---|
58 | conn.connect(settings.AUTH_SOCK) |
---|
59 | conn.send('\n'.join(args)) |
---|
60 | conn.shutdown(socket.SHUT_WR) |
---|
61 | result = conn.makefile().read().strip().split('\n') |
---|
62 | conn.close() |
---|
63 | return result |
---|