[dbb39a2] | 1 | from django.contrib.auth.models import User |
---|
[fe43b8a] | 2 | from django.core.exceptions import ObjectDoesNotExist |
---|
| 3 | from django.contrib import auth |
---|
[dbb39a2] | 4 | import socket |
---|
| 5 | import settings |
---|
| 6 | |
---|
| 7 | class SocketAuthBackend(): |
---|
[734ef4f] | 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 | """ |
---|
[dbb39a2] | 23 | def authenticate(self, username, password, ): |
---|
[e1ae8b3] | 24 | (result,) = query(1, "AUTHENTICATE", username, password, ) |
---|
[dbb39a2] | 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: |
---|
[39bd19e] | 37 | user = User(username=username) |
---|
| 38 | user.set_unusable_password() |
---|
[dbb39a2] | 39 | user.is_staff = False |
---|
| 40 | user.is_superuser = False |
---|
| 41 | # Is there a race condition here? Yes. |
---|
| 42 | # Should I do more error-checking? Yes. |
---|
| 43 | # Do I care? No. |
---|
[e1ae8b3] | 44 | (first, last, email,) = query(3, 'FINGER', username) |
---|
[dbb39a2] | 45 | user.first_name = first |
---|
| 46 | user.last_name = last |
---|
| 47 | user.email = email |
---|
| 48 | user.save() |
---|
[fe43b8a] | 49 | try: |
---|
| 50 | user.groups.add(auth.models.Group.objects.get(name='autocreated')) |
---|
| 51 | except ObjectDoesNotExist: |
---|
| 52 | print "Failed to retrieve autocreated group" |
---|
[dbb39a2] | 53 | return user |
---|
| 54 | return None |
---|
| 55 | |
---|
| 56 | def get_user(self, user_id): |
---|
| 57 | try: |
---|
| 58 | return User.objects.get(pk=user_id) |
---|
| 59 | except User.DoesNotExist: |
---|
| 60 | return None |
---|
| 61 | |
---|
[e1ae8b3] | 62 | def query(length, *args): |
---|
[dbb39a2] | 63 | conn = socket.socket(socket.AF_UNIX) |
---|
| 64 | conn.connect(settings.AUTH_SOCK) |
---|
| 65 | conn.send('\n'.join(args)) |
---|
| 66 | conn.shutdown(socket.SHUT_WR) |
---|
[e1ae8b3] | 67 | result = conn.makefile().read().split('\n') |
---|
| 68 | if(len(result)==length+1 and result[-1] == ''): |
---|
| 69 | result = result[:-1] |
---|
| 70 | if len(result) != length: |
---|
| 71 | raise ValueError("Got return value of length %d to query '%s'; needed length %d" % (len(result), args[0], length, )) |
---|
[dbb39a2] | 72 | conn.close() |
---|
| 73 | return result |
---|