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