]> snippets.scripts.mit.edu Git - Scripts/git/.git/blame - django/mit/__init__.py
kdo: Upstream krb5 now supports kswitch
[Scripts/git/.git] / django / mit / __init__.py
CommitLineData
20e2c5bc 1import os
aec307d9 2import subprocess
be3f03e7 3import tempfile
aec307d9
AD
4import ldap
5import ldap.filter
6
e2ce65b9 7from django.contrib.auth.backends import RemoteUserBackend
c6b6a6b9 8from django.contrib.auth.middleware import RemoteUserMiddleware
2e0bd8fa
AD
9from django.contrib.auth.views import login
10from django.contrib.auth import REDIRECT_FIELD_NAME
11from django.http import HttpResponseRedirect
e2ce65b9
AD
12from django.contrib import auth
13from django.core.exceptions import ObjectDoesNotExist
6650ee78
AD
14from django.core.validators import URLValidator, ValidationError
15
be3f03e7 16from django.conf import settings
e2ce65b9 17
aec307d9
AD
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)
e2ce65b9 24
6650ee78
AD
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
20e2c5bc
AD
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
be3f03e7
AD
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
e2ce65b9
AD
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
fb128813 85 user.set_unusable_password()
abab96a3 86 con = ldap.open('ldap-too.mit.edu')
e2ce65b9
AD
87 con.simple_bind_s("", "")
88 dn = "dc=mit,dc=edu"
89 fields = ['cn', 'sn', 'givenName', 'mail', ]
aec307d9
AD
90 userfilter = ldap.filter.filter_format('uid=%s', [username])
91 result = con.search_s('dc=mit,dc=edu', ldap.SCOPE_SUBTREE, userfilter, fields)
e2ce65b9
AD
92 if len(result) == 1:
93 user.first_name = result[0][1]['givenName'][0]
94 user.last_name = result[0][1]['sn'][0]
23bea0e4
GT
95 try:
96 user.email = result[0][1]['mail'][0]
97 except KeyError:
98 user.email = username + '@mit.edu'
e2ce65b9
AD
99 try:
100 user.groups.add(auth.models.Group.objects.get(name='mit'))
101 except ObjectDoesNotExist:
102 print "Failed to retrieve mit group"
aec307d9
AD
103 else:
104 raise ValueError, ("Could not find user with username '%s' (filter '%s')"%(username, userfilter))
e2ce65b9
AD
105 try:
106 user.groups.add(auth.models.Group.objects.get(name='autocreated'))
107 except ObjectDoesNotExist:
108 print "Failed to retrieve autocreated group"
aec307d9 109 user.save()
e2ce65b9 110 return user
2e0bd8fa 111
d4bd5af8
AD
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
2e0bd8fa 130def scripts_login(request, **kwargs):
4df1aef4 131 host = request.META['HTTP_HOST'].split(':')[0]
5ba5fe8d 132 if host in ('localhost', '127.0.0.1'):
2e0bd8fa
AD
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
2e0bd8fa
AD
150 redirect_to = "https://%s:444%s" % (host, request.META['REQUEST_URI'], )
151 return HttpResponseRedirect(redirect_to)