File: fp-registrar.cgi

package info (click to toggle)
flashproxy 1.7-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 936 kB
  • ctags: 876
  • sloc: python: 3,708; sh: 823; makefile: 246; lisp: 15
file content (122 lines) | stat: -rwxr-xr-x 3,395 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env python

import cgi
import os
import socket
import sys
import urllib

from flashproxy import fac

FACILITATOR_ADDR = ("127.0.0.1", 9002)

def output_status(status):
    print """\
Status: %d\r
\r""" % status

def exit_error(status):
    output_status(status)
    sys.exit()

# Send a base64-encoded client address to the registration daemon.
def send_url_reg(reg):
    # Translate from url-safe base64 alphabet to the standard alphabet.
    reg = reg.replace('-', '+').replace('_', '/')
    return fac.put_reg_proc(["fp-reg-decrypt"], reg)

method = os.environ.get("REQUEST_METHOD")
remote_addr = (os.environ.get("REMOTE_ADDR"), None)
path_info = os.environ.get("PATH_INFO") or "/"

if not method or not remote_addr[0]:
    exit_error(400)

# Print the HEAD part of a URL-based registration response, or exit with an
# error if appropriate.
def url_reg(reg):
    try:
        if send_url_reg(reg):
            output_status(204)
        else:
            exit_error(400)
    except Exception:
        exit_error(500)

def do_head():
    path_parts = [x for x in path_info.split("/") if x]
    if len(path_parts) == 2 and path_parts[0] == "reg":
        url_reg(path_parts[1])
    else:
        exit_error(400)

def do_get():
    """Parses flashproxy polls.
       Example: GET /?r=1&client=7.1.43.21&client=1.2.3.4&transport=webrtc&transport=websocket
    """
    fs = cgi.FieldStorage()

    path_parts = [x for x in path_info.split("/") if x]
    if len(path_parts) == 2 and path_parts[0] == "reg":
        url_reg(path_parts[1])
    elif len(path_parts) == 0:
        # Check for recent enough flash proxy protocol.
        r = fs.getlist("r")
        if len(r) != 1 or r[0] != "1":
            exit_error(400)

        # 'transports' (optional) can be repeated and carries
        # transport names.
        transport_list = fs.getlist("transport")
        if not transport_list:
            transport_list = ["websocket"]

        try:
            reg = fac.get_reg(FACILITATOR_ADDR, remote_addr, transport_list) or ""
        except Exception:
            exit_error(500)
        # Allow XMLHttpRequest from any domain. http://www.w3.org/TR/cors/.
        print """\
Status: 200\r
Content-Type: application/x-www-form-urlencoded\r
Cache-Control: no-cache\r
Access-Control-Allow-Origin: *\r
\r"""
        sys.stdout.write(urllib.urlencode(reg))
    else:
        exit_error(400)

def do_post():
    """Parse client registration."""

    if path_info != "/":
        exit_error(400)

    # We treat sys.stdin as being a bunch of newline-separated query strings. I
    # think that this is technically a violation of the
    # application/x-www-form-urlencoded content-type the client likely used, but
    # it at least matches the standard multiline registration format used by
    # fp-reg-decryptd.
    try:
        regs = list(fac.read_client_registrations(sys.stdin.read(), defhost=remote_addr[0]))
    except ValueError:
        exit_error(400)

    for reg in regs:
        # XXX need to link these registrations together, so that
        # when one is answerered (or errors) the rest are invalidated.
        if not fac.put_reg(FACILITATOR_ADDR, reg.addr, reg.transport):
            exit_error(500)

    print """\
Status: 200\r
\r"""

if method == "HEAD":
    do_head()
elif method == "GET":
    do_get()
elif method == "POST":
    do_post()
else:
    exit_error(405)