source: mod_gnutls/test/data/ocsp.py

asyncio
Last change on this file was 90d750d, checked in by Fiona Klute <fiona.klute@…>, 10 months ago

Fix flake8 warnings in the test OCSP responder script

  • Property mode set to 100755
File size: 3.9 KB
Line 
1#!/usr/bin/python3
2# Python 3 wrapper to use "openssl ocsp" as a simple OCSP responder
3#
4# Copyright 2020 Krista Karppinen, Fiona Klute
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you
7# may not use this file except in compliance with the License.  You
8# may obtain a copy of the License at
9#
10#      http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15# implied.  See the License for the specific language governing
16# permissions and limitations under the License.
17
18# This is a CGI script to run the OpenSSL OCSP responder from a web
19# server. The CGI environment must provide the following four
20# variables to configure the OCSP responder:
21#
22# CA_CERT: CA certificate of the CA that issued the certificates this
23# OCSP reponder should provide status information for
24#
25# OCSP_INDEX: CA index file in the format used by OpenSSL
26#
27# OCSP_CERT: Certificate that should be used to sign OCSP reponses
28# (either CA_CERT or a dedicated OCSP signer certificate, see RFC
29# 6960, Section 4.2.2.2)
30#
31# OCSP_KEY: Private key for OCSP_CERT
32#
33# Additionally, the OpenSSL binary to use can be configured through
34# the OPENSSL environment variable. If it is not set, the PATH will be
35# searched.
36
37from http import HTTPStatus
38import base64
39import os
40import shutil
41import subprocess
42import sys
43
44
45REQUEST_TYPE = 'application/ocsp-request'
46RESPONSE_TYPE = 'application/ocsp-response'
47
48
49def stdout(data):
50    sys.stdout.buffer.write(data)
51
52
53def stdout_line(line):
54    stdout(line.encode('utf-8'))
55    stdout(b'\n')
56
57
58def stdout_status(status, content_type='text/plain'):
59    stdout_line(f'Status: {status.value} {status.phrase}')
60    stdout_line(f'Content-Type: {content_type}\n')
61
62
63def stdout_response(status, response):
64    stdout_status(status, content_type=RESPONSE_TYPE)
65    stdout(response)
66
67
68def handle_get():
69    # GET OCSP requests are allowed by RFC 6960, Appendix A.1, but
70    # not implemented here. It should be possible to extract a GET
71    # request from the PATH_INFO CGI variable.
72    stdout_status(HTTPStatus.METHOD_NOT_ALLOWED)
73    stdout_line('OCSP GET request not implemented.')
74
75
76def handle_post():
77    content_type = os.getenv('CONTENT_TYPE')
78    content_length = os.getenv('CONTENT_LENGTH')
79    if content_type != REQUEST_TYPE or not content_length:
80        stdout_status(HTTPStatus.UNSUPPORTED_MEDIA_TYPE)
81        stdout_line(f'POST request must contain {REQUEST_TYPE} data.')
82        return
83
84    try:
85        req = sys.stdin.buffer.read(int(content_length))
86        print(f'Received OCSP request: \'{base64.b64encode(req).decode()}\'',
87              file=sys.stderr, flush=True)
88        openssl = os.getenv('OPENSSL') or shutil.which('openssl')
89        openssl_run = subprocess.run(
90            [openssl, 'ocsp',
91             '-index', os.getenv('OCSP_INDEX'),
92             '-CA', os.getenv('CA_CERT'),
93             '-rsigner', os.getenv('OCSP_CERT'),
94             '-rkey', os.getenv('OCSP_KEY'),
95             '-nmin', os.getenv('OCSP_VALID_MIN', '5'),
96             '-reqin', '-', '-respout', '-'],
97            input=req, capture_output=True)
98
99        if openssl_run.returncode == 0:
100            stdout_response(HTTPStatus.OK, openssl_run.stdout)
101            sys.stderr.buffer.write(openssl_run.stderr)
102        else:
103            raise Exception('openssl process exited with return code '
104                            f'{openssl_run.returncode}, stdout: '
105                            f'{openssl_run.stdout}, stderr: '
106                            f'{openssl_run.stderr}')
107    except:
108        stdout_status(HTTPStatus.INTERNAL_SERVER_ERROR)
109        raise
110
111
112if __name__ == '__main__':
113    method = os.getenv('REQUEST_METHOD')
114    if method == 'GET':
115        handle_get()
116    elif method == 'POST':
117        handle_post()
118    else:
119        stdout_status(HTTPStatus.METHOD_NOT_ALLOWED)
Note: See TracBrowser for help on using the repository browser.