]> snippets.scripts.mit.edu Git - Scripts/git/.git/blame_incremental - django/mit/__init__.py
kdo: Upstream krb5 now supports kswitch
[Scripts/git/.git] / django / mit / __init__.py
... / ...
CommitLineData
1import os
2import subprocess
3import tempfile
4import ldap
5import ldap.filter
6
7from django.contrib.auth.backends import RemoteUserBackend
8from django.contrib.auth.middleware import RemoteUserMiddleware
9from django.contrib.auth.views import login
10from django.contrib.auth import REDIRECT_FIELD_NAME
11from django.http import HttpResponseRedirect
12from django.contrib import auth
13from django.core.exceptions import ObjectDoesNotExist
14from django.core.validators import URLValidator, ValidationError
15
16from django.conf import settings
17
18def zephyr(msg, clas='message', instance='log', rcpt='nobody',):
19 proc = subprocess.Popen(
20 ['zwrite', '-d', '-n', '-c', clas, '-i', instance, rcpt, ],
21 stdin=subprocess.PIPE, stdout=subprocess.PIPE
22 )
23 proc.communicate(msg)
24
25def UrlOrAfsValidator(value):
26 if value.startswith('/mit/') or value.startswith('/afs/'):
27 return
28 else:
29 try:
30 URLValidator()(value)
31 except ValidationError:
32 raise ValidationError('Provide a valid URL or AFS path')
33
34def pag_check_helper(fn, args, aklog=False, ccname=None, **kwargs):
35 if 'executable' in kwargs:
36 raise ValueError('"executable" not supported with pag_check_*')
37
38 env = None
39 if 'env' in kwargs:
40 env = kwargs['env']
41 del kwargs['env']
42 if ccname:
43 if env is not None:
44 env = dict(env)
45 else:
46 env = dict(os.environ)
47 env['KRB5CCNAME'] = ccname
48
49 pagsh_cmd = 'exec "$@"'
50 if aklog: pagsh_cmd = "aklog && " + pagsh_cmd
51 args = ['pagsh', '-c', pagsh_cmd, 'exec', ] + args
52
53 return fn(args, env=env, **kwargs)
54
55def pag_check_call(args, **kwargs):
56 return pag_check_helper(subprocess.check_call, args, **kwargs)
57def pag_check_output(args, **kwargs):
58 return pag_check_helper(subprocess.check_output, args, **kwargs)
59
60def kinit(keytab=None, principal=None, autodelete=True, ):
61 if not keytab:
62 keytab = settings.KRB_KEYTAB
63 if not principal:
64 principal = settings.KRB_PRINCIPAL
65 assert keytab and principal
66 fd = tempfile.NamedTemporaryFile(mode='rb', prefix="krb5cc_djmit_", delete=autodelete, )
67 env = dict(KRB5CCNAME=fd.name)
68 kinit_cmd = ['kinit', '-k', '-t', keytab, principal, ]
69 subprocess.check_call(kinit_cmd, env=env)
70 return fd
71
72class ScriptsRemoteUserMiddleware(RemoteUserMiddleware):
73 header = 'SSL_CLIENT_S_DN_Email'
74
75class ScriptsRemoteUserBackend(RemoteUserBackend):
76 def clean_username(self, username, ):
77 if '@' in username:
78 name, domain = username.split('@')
79 assert domain.upper() == 'MIT.EDU'
80 return name
81 else:
82 return username
83 def configure_user(self, user, ):
84 username = user.username
85 user.set_unusable_password()
86 con = ldap.open('ldap-too.mit.edu')
87 con.simple_bind_s("", "")
88 dn = "dc=mit,dc=edu"
89 fields = ['cn', 'sn', 'givenName', 'mail', ]
90 userfilter = ldap.filter.filter_format('uid=%s', [username])
91 result = con.search_s('dc=mit,dc=edu', ldap.SCOPE_SUBTREE, userfilter, fields)
92 if len(result) == 1:
93 user.first_name = result[0][1]['givenName'][0]
94 user.last_name = result[0][1]['sn'][0]
95 try:
96 user.email = result[0][1]['mail'][0]
97 except KeyError:
98 user.email = username + '@mit.edu'
99 try:
100 user.groups.add(auth.models.Group.objects.get(name='mit'))
101 except ObjectDoesNotExist:
102 print "Failed to retrieve mit group"
103 else:
104 raise ValueError, ("Could not find user with username '%s' (filter '%s')"%(username, userfilter))
105 try:
106 user.groups.add(auth.models.Group.objects.get(name='autocreated'))
107 except ObjectDoesNotExist:
108 print "Failed to retrieve autocreated group"
109 user.save()
110 return user
111
112def get_or_create_mit_user(username, ):
113 """
114 Given an MIT username, return a Django user object for them.
115 If necessary, create (and save) the Django user for them.
116 If the MIT user doesn't exist, raises ValueError.
117 """
118 user, created = auth.models.User.objects.get_or_create(username=username, )
119 if created:
120 backend = ScriptsRemoteUserBackend()
121 # Raises ValueError if the user doesn't exist
122 try:
123 return backend.configure_user(user), created
124 except ValueError:
125 user.delete()
126 raise
127 else:
128 return user, created
129
130def scripts_login(request, **kwargs):
131 host = request.META['HTTP_HOST'].split(':')[0]
132 if host in ('localhost', '127.0.0.1'):
133 return login(request, **kwargs)
134 elif request.META['SERVER_PORT'] == '444':
135 if request.user.is_authenticated():
136 # They're already authenticated --- go ahead and redirect
137 if 'redirect_field_name' in kwargs:
138 redirect_field_name = kwargs['redirect_field_names']
139 else:
140 from django.contrib.auth import REDIRECT_FIELD_NAME
141 redirect_field_name = REDIRECT_FIELD_NAME
142 redirect_to = request.REQUEST.get(redirect_field_name, '')
143 if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
144 redirect_to = settings.LOGIN_REDIRECT_URL
145 return HttpResponseRedirect(redirect_to)
146 else:
147 return login(request, **kwargs)
148 else:
149 # Move to port 444
150 redirect_to = "https://%s:444%s" % (host, request.META['REQUEST_URI'], )
151 return HttpResponseRedirect(redirect_to)