2020-06-11 00:54:34 +02:00
|
|
|
import base64
|
|
|
|
import logging
|
|
|
|
import re
|
2020-10-09 03:22:31 +02:00
|
|
|
import shlex
|
2020-06-11 00:54:34 +02:00
|
|
|
import subprocess
|
|
|
|
from typing import Optional
|
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
import orjson
|
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 = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"golem": "ctl",
|
2017-02-27 05:18:58 +01:00
|
|
|
}
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2016-08-19 03:26:49 +02:00
|
|
|
@authenticated_json_view
|
|
|
|
@has_request_variables
|
2021-02-12 08:19:30 +01:00
|
|
|
def webathena_kerberos_login(
|
|
|
|
request: HttpRequest, user_profile: UserProfile, 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:
|
2020-08-07 01:09:47 +02:00
|
|
|
parsed_cred = orjson.loads(cred)
|
2016-08-19 03:26:49 +02:00
|
|
|
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]
|
2021-02-12 08:19:30 +01: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.
|
2021-02-12 08:20:45 +01:00
|
|
|
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"))
|
|
|
|
|
2020-10-23 02:43:28 +02:00
|
|
|
# TODO: Send these data via (say) RabbitMQ
|
2016-08-19 03:26:49 +02:00
|
|
|
try:
|
2018-08-01 10:53:40 +02:00
|
|
|
api_key = get_api_key(user_profile)
|
2020-10-09 03:22:31 +02:00
|
|
|
command = [
|
|
|
|
"/home/zulip/python-zulip-api/zulip/integrations/zephyr/process_ccache",
|
|
|
|
user,
|
|
|
|
api_key,
|
|
|
|
base64.b64encode(ccache).decode("utf-8"),
|
|
|
|
]
|
2021-02-12 08:19:30 +01:00
|
|
|
subprocess.check_call(
|
|
|
|
["ssh", settings.PERSONAL_ZMIRROR_SERVER, "--", " ".join(map(shlex.quote, command))]
|
|
|
|
)
|
2020-10-09 03:32:00 +02:00
|
|
|
except subprocess.CalledProcessError:
|
2020-08-11 03:19:00 +02:00
|
|
|
logging.exception("Error updating the user's ccache", stack_info=True)
|
2016-08-19 03:26:49 +02:00
|
|
|
return json_error(_("We were unable to setup mirroring for you"))
|
|
|
|
|
|
|
|
return json_success()
|