2020-06-11 00:54:34 +02:00
|
|
|
import base64
|
|
|
|
import logging
|
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
import ujson
|
2016-08-19 03:26:49 +02:00
|
|
|
from django.conf import settings
|
2020-06-11 00:54:34 +02:00
|
|
|
from django.http import HttpRequest, HttpResponse
|
2016-08-19 03:26:49 +02:00
|
|
|
from django.utils.translation import ugettext as _
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2016-08-19 03:26:49 +02:00
|
|
|
from zerver.decorator import authenticated_json_view
|
|
|
|
from zerver.lib.ccache import make_ccache
|
2019-12-20 00:00:45 +01:00
|
|
|
from zerver.lib.pysa import mark_sanitized
|
2020-06-11 00:54:34 +02:00
|
|
|
from zerver.lib.request import REQ, has_request_variables
|
|
|
|
from zerver.lib.response import json_error, json_success
|
2018-08-01 10:53:40 +02:00
|
|
|
from zerver.lib.users import get_api_key
|
2016-08-19 03:26:49 +02:00
|
|
|
from zerver.models import UserProfile
|
|
|
|
|
2017-02-27 05:18:58 +01:00
|
|
|
# Hack for mit.edu users whose Kerberos usernames don't match what they zephyr
|
|
|
|
# as. The key is for Kerberos and the value is for zephyr.
|
|
|
|
kerberos_alter_egos = {
|
|
|
|
'golem': 'ctl',
|
|
|
|
}
|
|
|
|
|
2016-08-19 03:26:49 +02:00
|
|
|
@authenticated_json_view
|
|
|
|
@has_request_variables
|
2017-12-29 14:34:49 +01:00
|
|
|
def webathena_kerberos_login(request: HttpRequest, user_profile: UserProfile,
|
2019-07-28 22:45:04 +02:00
|
|
|
cred: Optional[str]=REQ(default=None)) -> HttpResponse:
|
2017-02-27 05:18:58 +01:00
|
|
|
global kerberos_alter_egos
|
2016-08-19 03:26:49 +02:00
|
|
|
if cred is None:
|
|
|
|
return json_error(_("Could not find Kerberos credential"))
|
|
|
|
if not user_profile.realm.webathena_enabled:
|
|
|
|
return json_error(_("Webathena login not enabled"))
|
|
|
|
|
|
|
|
try:
|
|
|
|
parsed_cred = ujson.loads(cred)
|
|
|
|
user = parsed_cred["cname"]["nameString"][0]
|
2017-02-27 05:18:58 +01:00
|
|
|
if user in kerberos_alter_egos:
|
|
|
|
user = kerberos_alter_egos[user]
|
2016-08-19 03:26:49 +02:00
|
|
|
assert(user == user_profile.email.split("@")[0])
|
2020-03-17 13:31:14 +01:00
|
|
|
# Limit characters in usernames to valid MIT usernames
|
|
|
|
# This is important for security since DNS is not secure.
|
|
|
|
assert(re.match(r'^[a-z0-9_.-]+$', user) is not None)
|
2016-08-19 03:26:49 +02:00
|
|
|
ccache = make_ccache(parsed_cred)
|
2019-12-20 00:00:45 +01:00
|
|
|
|
|
|
|
# 'user' has been verified to contain only benign characters that won't
|
|
|
|
# help with shell injection.
|
|
|
|
user = mark_sanitized(user)
|
|
|
|
|
|
|
|
# 'ccache' is only written to disk by the script and used as a kerberos
|
|
|
|
# credential cache file.
|
|
|
|
ccache = mark_sanitized(ccache)
|
2016-08-19 03:26:49 +02:00
|
|
|
except Exception:
|
|
|
|
return json_error(_("Invalid Kerberos cache"))
|
|
|
|
|
|
|
|
# TODO: Send these data via (say) rabbitmq
|
|
|
|
try:
|
2018-08-01 10:53:40 +02:00
|
|
|
api_key = get_api_key(user_profile)
|
2016-08-19 03:26:49 +02:00
|
|
|
subprocess.check_call(["ssh", settings.PERSONAL_ZMIRROR_SERVER, "--",
|
2017-10-05 21:26:54 +02:00
|
|
|
"/home/zulip/python-zulip-api/zulip/integrations/zephyr/process_ccache",
|
2018-11-27 20:24:23 +01:00
|
|
|
user,
|
|
|
|
api_key,
|
|
|
|
base64.b64encode(ccache).decode("utf-8")])
|
2016-08-19 03:26:49 +02:00
|
|
|
except Exception:
|
|
|
|
logging.exception("Error updating the user's ccache")
|
|
|
|
return json_error(_("We were unable to setup mirroring for you"))
|
|
|
|
|
|
|
|
return json_success()
|