From 19a394b1877d094560f9f5ea0a7ab93e1311def5 Mon Sep 17 00:00:00 2001 From: Apex Liu Date: Fri, 14 Sep 2018 06:00:33 +0800 Subject: [PATCH] update python-packages like mako/tornado/etc. to last version. --- .../packages-common/cryptography/__about__.py | 23 + .../packages-common/cryptography/__init__.py | 16 + .../cryptography/exceptions.py | 57 + .../packages-common/cryptography/fernet.py | 173 ++ .../cryptography/hazmat/__init__.py | 11 + .../cryptography/hazmat/backends/__init__.py | 18 + .../hazmat/backends/interfaces.py | 395 ++++ .../hazmat/backends/openssl/__init__.py | 10 + .../hazmat/backends/openssl/aead.py | 159 ++ .../hazmat/backends/openssl/backend.py | 1974 +++++++++++++++++ .../hazmat/backends/openssl/ciphers.py | 222 ++ .../hazmat/backends/openssl/cmac.py | 81 + .../hazmat/backends/openssl/decode_asn1.py | 826 +++++++ .../hazmat/backends/openssl/dh.py | 280 +++ .../hazmat/backends/openssl/dsa.py | 269 +++ .../hazmat/backends/openssl/ec.py | 298 +++ .../hazmat/backends/openssl/encode_asn1.py | 611 +++++ .../hazmat/backends/openssl/hashes.py | 61 + .../hazmat/backends/openssl/hmac.py | 73 + .../hazmat/backends/openssl/rsa.py | 475 ++++ .../hazmat/backends/openssl/utils.py | 45 + .../hazmat/backends/openssl/x25519.py | 79 + .../hazmat/backends/openssl/x509.py | 518 +++++ .../cryptography/hazmat/bindings/__init__.py | 5 + .../bindings/_constant_time.cp37-win32.pyd | Bin 0 -> 9728 bytes .../hazmat/bindings/_openssl.cp37-win32.pyd | Bin 0 -> 2017792 bytes .../hazmat/bindings/_padding.cp37-win32.pyd | Bin 0 -> 9728 bytes .../hazmat/bindings/openssl/__init__.py | 5 + .../hazmat/bindings/openssl/_conditional.py | 302 +++ .../hazmat/bindings/openssl/binding.py | 157 ++ .../hazmat/primitives/__init__.py | 5 + .../hazmat/primitives/asymmetric/__init__.py | 40 + .../hazmat/primitives/asymmetric/dh.py | 212 ++ .../hazmat/primitives/asymmetric/dsa.py | 254 +++ .../hazmat/primitives/asymmetric/ec.py | 411 ++++ .../hazmat/primitives/asymmetric/padding.py | 79 + .../hazmat/primitives/asymmetric/rsa.py | 368 +++ .../hazmat/primitives/asymmetric/utils.py | 60 + .../hazmat/primitives/asymmetric/x25519.py | 54 + .../hazmat/primitives/ciphers/__init__.py | 21 + .../hazmat/primitives/ciphers/aead.py | 188 ++ .../hazmat/primitives/ciphers/algorithms.py | 168 ++ .../hazmat/primitives/ciphers/base.py | 235 ++ .../hazmat/primitives/ciphers/modes.py | 231 ++ .../cryptography/hazmat/primitives/cmac.py | 66 + .../hazmat/primitives/constant_time.py | 35 + .../cryptography/hazmat/primitives/hashes.py | 185 ++ .../cryptography/hazmat/primitives/hmac.py | 69 + .../hazmat/primitives/kdf/__init__.py | 26 + .../hazmat/primitives/kdf/concatkdf.py | 125 ++ .../hazmat/primitives/kdf/hkdf.py | 116 + .../hazmat/primitives/kdf/kbkdf.py | 148 ++ .../hazmat/primitives/kdf/pbkdf2.py | 58 + .../hazmat/primitives/kdf/scrypt.py | 66 + .../hazmat/primitives/kdf/x963kdf.py | 70 + .../cryptography/hazmat/primitives/keywrap.py | 154 ++ .../cryptography/hazmat/primitives/mac.py | 37 + .../cryptography/hazmat/primitives/padding.py | 202 ++ .../hazmat/primitives/serialization.py | 209 ++ .../hazmat/primitives/twofactor/__init__.py | 9 + .../hazmat/primitives/twofactor/hotp.py | 68 + .../hazmat/primitives/twofactor/totp.py | 40 + .../hazmat/primitives/twofactor/utils.py | 30 + .../packages-common/cryptography/utils.py | 165 ++ .../cryptography/x509/__init__.py | 185 ++ .../packages-common/cryptography/x509/base.py | 743 +++++++ .../x509/certificate_transparency.py | 46 + .../cryptography/x509/extensions.py | 1429 ++++++++++++ .../cryptography/x509/general_name.py | 345 +++ .../packages-common/cryptography/x509/name.py | 190 ++ .../packages-common/cryptography/x509/oid.py | 271 +++ .../packages/packages-common/mako/__init__.py | 2 +- .../packages-common/mako/_ast_util.py | 2 +- .../packages/packages-common/mako/cache.py | 14 +- .../www/packages/packages-common/mako/cmd.py | 2 +- .../packages-common/mako/ext/extract.py | 2 +- .../packages-common/mako/parsetree.py | 2 +- .../packages/packages-common/mako/template.py | 2 +- .../packages-common/pymysql/__init__.py | 15 +- .../packages-common/pymysql/connections.py | 798 +++---- .../pymysql/constants/CLIENT.py | 6 +- .../packages-common/pymysql/constants/ER.py | 3 + .../packages-common/pymysql/converters.py | 25 +- .../packages-common/pymysql/cursors.py | 35 +- .../packages/packages-common/pymysql/err.py | 6 +- .../packages-common/pymysql/optionfile.py | 3 + .../packages-common/pymysql/protocol.py | 341 +++ .../packages/packages-common/qrcode/LUT.py | 50 + .../packages/packages-common/qrcode/base.py | 13 +- .../packages-common/qrcode/console_scripts.py | 8 +- .../packages-common/qrcode/image/pil.py | 7 +- .../packages/packages-common/qrcode/main.py | 23 +- .../packages/packages-common/qrcode/mecard.py | 33 - .../packages-common/qrcode/release.py | 42 + .../packages/packages-common/qrcode/speedy.py | 8 - .../packages/packages-common/qrcode/util.py | 200 +- server/www/packages/packages-common/six.py | 55 +- .../packages-common/tornado/__init__.py | 5 +- .../packages-common/tornado/_locale_data.py | 3 +- .../packages/packages-common/tornado/auth.py | 312 ++- .../packages-common/tornado/autoreload.py | 76 +- .../packages-common/tornado/concurrent.py | 231 +- .../tornado/curl_httpclient.py | 49 +- .../packages-common/tornado/escape.py | 31 +- .../packages/packages-common/tornado/gen.py | 336 +-- .../tornado/http1connection.py | 61 +- .../packages-common/tornado/httpclient.py | 166 +- .../packages-common/tornado/httpserver.py | 15 +- .../packages-common/tornado/httputil.py | 114 +- .../packages-common/tornado/ioloop.py | 460 +++- .../packages-common/tornado/iostream.py | 595 +++-- .../packages-common/tornado/locale.py | 2 +- .../packages/packages-common/tornado/locks.py | 152 +- .../packages/packages-common/tornado/log.py | 10 +- .../packages-common/tornado/netutil.py | 233 +- .../packages-common/tornado/options.py | 130 +- .../tornado/platform/asyncio.py | 199 +- .../packages-common/tornado/platform/auto.py | 1 - .../tornado/platform/caresresolver.py | 18 +- .../tornado/platform/common.py | 4 + .../packages-common/tornado/platform/epoll.py | 1 - .../tornado/platform/interface.py | 1 - .../tornado/platform/kqueue.py | 1 - .../packages-common/tornado/platform/posix.py | 1 - .../tornado/platform/select.py | 1 - .../tornado/platform/twisted.py | 66 +- .../tornado/platform/windows.py | 2 +- .../packages-common/tornado/process.py | 38 +- .../packages-common/tornado/queues.py | 68 +- .../packages-common/tornado/routing.py | 22 +- .../tornado/simple_httpclient.py | 331 ++- .../tornado/speedups.cp37-win32.pyd | Bin 0 -> 9216 bytes .../packages-common/tornado/stack_context.py | 27 +- .../packages-common/tornado/tcpclient.py | 104 +- .../packages-common/tornado/tcpserver.py | 35 +- .../packages-common/tornado/template.py | 6 +- .../packages-common/tornado/testing.py | 264 +-- .../packages/packages-common/tornado/util.py | 24 +- .../packages/packages-common/tornado/web.py | 191 +- .../packages-common/tornado/websocket.py | 424 ++-- .../packages/packages-common/tornado/wsgi.py | 29 +- .../www/teleport/webroot/app/base/webapp.py | 4 + 142 files changed, 18666 insertions(+), 2430 deletions(-) create mode 100644 server/www/packages/packages-common/cryptography/__about__.py create mode 100644 server/www/packages/packages-common/cryptography/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/exceptions.py create mode 100644 server/www/packages/packages-common/cryptography/fernet.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/interfaces.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/aead.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/backend.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ciphers.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/cmac.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/decode_asn1.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dh.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dsa.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ec.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/encode_asn1.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hashes.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hmac.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/rsa.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/utils.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x25519.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x509.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/bindings/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/bindings/_constant_time.cp37-win32.pyd create mode 100644 server/www/packages/packages-common/cryptography/hazmat/bindings/_openssl.cp37-win32.pyd create mode 100644 server/www/packages/packages-common/cryptography/hazmat/bindings/_padding.cp37-win32.pyd create mode 100644 server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/_conditional.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/binding.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dh.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dsa.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/ec.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/padding.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/rsa.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/utils.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/x25519.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/aead.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/algorithms.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/base.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/modes.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/cmac.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/constant_time.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/hashes.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/hmac.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/concatkdf.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/hkdf.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/kbkdf.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/pbkdf2.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/scrypt.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/x963kdf.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/keywrap.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/mac.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/padding.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/serialization.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/hotp.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/totp.py create mode 100644 server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/utils.py create mode 100644 server/www/packages/packages-common/cryptography/utils.py create mode 100644 server/www/packages/packages-common/cryptography/x509/__init__.py create mode 100644 server/www/packages/packages-common/cryptography/x509/base.py create mode 100644 server/www/packages/packages-common/cryptography/x509/certificate_transparency.py create mode 100644 server/www/packages/packages-common/cryptography/x509/extensions.py create mode 100644 server/www/packages/packages-common/cryptography/x509/general_name.py create mode 100644 server/www/packages/packages-common/cryptography/x509/name.py create mode 100644 server/www/packages/packages-common/cryptography/x509/oid.py create mode 100644 server/www/packages/packages-common/pymysql/protocol.py create mode 100644 server/www/packages/packages-common/qrcode/LUT.py delete mode 100644 server/www/packages/packages-common/qrcode/mecard.py create mode 100644 server/www/packages/packages-common/qrcode/release.py delete mode 100644 server/www/packages/packages-common/qrcode/speedy.py create mode 100644 server/www/packages/packages-common/tornado/speedups.cp37-win32.pyd diff --git a/server/www/packages/packages-common/cryptography/__about__.py b/server/www/packages/packages-common/cryptography/__about__.py new file mode 100644 index 0000000..a99f58f --- /dev/null +++ b/server/www/packages/packages-common/cryptography/__about__.py @@ -0,0 +1,23 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "cryptography" +__summary__ = ("cryptography is a package which provides cryptographic recipes" + " and primitives to Python developers.") +__uri__ = "https://github.com/pyca/cryptography" + +__version__ = "2.3.1" + +__author__ = "The cryptography developers" +__email__ = "cryptography-dev@python.org" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2013-2017 {0}".format(__author__) diff --git a/server/www/packages/packages-common/cryptography/__init__.py b/server/www/packages/packages-common/cryptography/__init__.py new file mode 100644 index 0000000..6da0b38 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/__init__.py @@ -0,0 +1,16 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography.__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/server/www/packages/packages-common/cryptography/exceptions.py b/server/www/packages/packages-common/cryptography/exceptions.py new file mode 100644 index 0000000..648cf9d --- /dev/null +++ b/server/www/packages/packages-common/cryptography/exceptions.py @@ -0,0 +1,57 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from enum import Enum + + +class _Reasons(Enum): + BACKEND_MISSING_INTERFACE = 0 + UNSUPPORTED_HASH = 1 + UNSUPPORTED_CIPHER = 2 + UNSUPPORTED_PADDING = 3 + UNSUPPORTED_MGF = 4 + UNSUPPORTED_PUBLIC_KEY_ALGORITHM = 5 + UNSUPPORTED_ELLIPTIC_CURVE = 6 + UNSUPPORTED_SERIALIZATION = 7 + UNSUPPORTED_X509 = 8 + UNSUPPORTED_EXCHANGE_ALGORITHM = 9 + UNSUPPORTED_DIFFIE_HELLMAN = 10 + + +class UnsupportedAlgorithm(Exception): + def __init__(self, message, reason=None): + super(UnsupportedAlgorithm, self).__init__(message) + self._reason = reason + + +class AlreadyFinalized(Exception): + pass + + +class AlreadyUpdated(Exception): + pass + + +class NotYetFinalized(Exception): + pass + + +class InvalidTag(Exception): + pass + + +class InvalidSignature(Exception): + pass + + +class InternalError(Exception): + def __init__(self, msg, err_code): + super(InternalError, self).__init__(msg) + self.err_code = err_code + + +class InvalidKey(Exception): + pass diff --git a/server/www/packages/packages-common/cryptography/fernet.py b/server/www/packages/packages-common/cryptography/fernet.py new file mode 100644 index 0000000..ac2dd0b --- /dev/null +++ b/server/www/packages/packages-common/cryptography/fernet.py @@ -0,0 +1,173 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import base64 +import binascii +import os +import struct +import time + +import six + +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes, padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.hmac import HMAC + + +class InvalidToken(Exception): + pass + + +_MAX_CLOCK_SKEW = 60 + + +class Fernet(object): + def __init__(self, key, backend=None): + if backend is None: + backend = default_backend() + + key = base64.urlsafe_b64decode(key) + if len(key) != 32: + raise ValueError( + "Fernet key must be 32 url-safe base64-encoded bytes." + ) + + self._signing_key = key[:16] + self._encryption_key = key[16:] + self._backend = backend + + @classmethod + def generate_key(cls): + return base64.urlsafe_b64encode(os.urandom(32)) + + def encrypt(self, data): + current_time = int(time.time()) + iv = os.urandom(16) + return self._encrypt_from_parts(data, current_time, iv) + + def _encrypt_from_parts(self, data, current_time, iv): + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") + + padder = padding.PKCS7(algorithms.AES.block_size).padder() + padded_data = padder.update(data) + padder.finalize() + encryptor = Cipher( + algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend + ).encryptor() + ciphertext = encryptor.update(padded_data) + encryptor.finalize() + + basic_parts = ( + b"\x80" + struct.pack(">Q", current_time) + iv + ciphertext + ) + + h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) + h.update(basic_parts) + hmac = h.finalize() + return base64.urlsafe_b64encode(basic_parts + hmac) + + def decrypt(self, token, ttl=None): + timestamp, data = Fernet._get_unverified_token_data(token) + return self._decrypt_data(data, timestamp, ttl) + + def extract_timestamp(self, token): + timestamp, data = Fernet._get_unverified_token_data(token) + # Verify the token was not tampered with. + self._verify_signature(data) + return timestamp + + @staticmethod + def _get_unverified_token_data(token): + if not isinstance(token, bytes): + raise TypeError("token must be bytes.") + + try: + data = base64.urlsafe_b64decode(token) + except (TypeError, binascii.Error): + raise InvalidToken + + if not data or six.indexbytes(data, 0) != 0x80: + raise InvalidToken + + try: + timestamp, = struct.unpack(">Q", data[1:9]) + except struct.error: + raise InvalidToken + return timestamp, data + + def _verify_signature(self, data): + h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) + h.update(data[:-32]) + try: + h.verify(data[-32:]) + except InvalidSignature: + raise InvalidToken + + def _decrypt_data(self, data, timestamp, ttl): + current_time = int(time.time()) + if ttl is not None: + if timestamp + ttl < current_time: + raise InvalidToken + + if current_time + _MAX_CLOCK_SKEW < timestamp: + raise InvalidToken + + self._verify_signature(data) + + iv = data[9:25] + ciphertext = data[25:-32] + decryptor = Cipher( + algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend + ).decryptor() + plaintext_padded = decryptor.update(ciphertext) + try: + plaintext_padded += decryptor.finalize() + except ValueError: + raise InvalidToken + unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() + + unpadded = unpadder.update(plaintext_padded) + try: + unpadded += unpadder.finalize() + except ValueError: + raise InvalidToken + return unpadded + + +class MultiFernet(object): + def __init__(self, fernets): + fernets = list(fernets) + if not fernets: + raise ValueError( + "MultiFernet requires at least one Fernet instance" + ) + self._fernets = fernets + + def encrypt(self, msg): + return self._fernets[0].encrypt(msg) + + def rotate(self, msg): + timestamp, data = Fernet._get_unverified_token_data(msg) + for f in self._fernets: + try: + p = f._decrypt_data(data, timestamp, None) + break + except InvalidToken: + pass + else: + raise InvalidToken + + iv = os.urandom(16) + return self._fernets[0]._encrypt_from_parts(p, timestamp, iv) + + def decrypt(self, msg, ttl=None): + for f in self._fernets: + try: + return f.decrypt(msg, ttl) + except InvalidToken: + pass + raise InvalidToken diff --git a/server/www/packages/packages-common/cryptography/hazmat/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/__init__.py new file mode 100644 index 0000000..9f06a99 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/__init__.py @@ -0,0 +1,11 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +Hazardous Materials + +This is a "Hazardous Materials" module. You should ONLY use it if you're +100% absolutely sure that you know what you're doing because this module +is full of land mines, dragons, and dinosaurs with laser guns. +""" +from __future__ import absolute_import, division, print_function diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/backends/__init__.py new file mode 100644 index 0000000..565bde7 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/__init__.py @@ -0,0 +1,18 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + + +_default_backend = None + + +def default_backend(): + global _default_backend + + if _default_backend is None: + from cryptography.hazmat.backends.openssl.backend import backend + _default_backend = backend + + return _default_backend diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/interfaces.py b/server/www/packages/packages-common/cryptography/hazmat/backends/interfaces.py new file mode 100644 index 0000000..0a476b9 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/interfaces.py @@ -0,0 +1,395 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + + +@six.add_metaclass(abc.ABCMeta) +class CipherBackend(object): + @abc.abstractmethod + def cipher_supported(self, cipher, mode): + """ + Return True if the given cipher and mode are supported. + """ + + @abc.abstractmethod + def create_symmetric_encryption_ctx(self, cipher, mode): + """ + Get a CipherContext that can be used for encryption. + """ + + @abc.abstractmethod + def create_symmetric_decryption_ctx(self, cipher, mode): + """ + Get a CipherContext that can be used for decryption. + """ + + +@six.add_metaclass(abc.ABCMeta) +class HashBackend(object): + @abc.abstractmethod + def hash_supported(self, algorithm): + """ + Return True if the hash algorithm is supported by this backend. + """ + + @abc.abstractmethod + def create_hash_ctx(self, algorithm): + """ + Create a HashContext for calculating a message digest. + """ + + +@six.add_metaclass(abc.ABCMeta) +class HMACBackend(object): + @abc.abstractmethod + def hmac_supported(self, algorithm): + """ + Return True if the hash algorithm is supported for HMAC by this + backend. + """ + + @abc.abstractmethod + def create_hmac_ctx(self, key, algorithm): + """ + Create a MACContext for calculating a message authentication code. + """ + + +@six.add_metaclass(abc.ABCMeta) +class CMACBackend(object): + @abc.abstractmethod + def cmac_algorithm_supported(self, algorithm): + """ + Returns True if the block cipher is supported for CMAC by this backend + """ + + @abc.abstractmethod + def create_cmac_ctx(self, algorithm): + """ + Create a MACContext for calculating a message authentication code. + """ + + +@six.add_metaclass(abc.ABCMeta) +class PBKDF2HMACBackend(object): + @abc.abstractmethod + def pbkdf2_hmac_supported(self, algorithm): + """ + Return True if the hash algorithm is supported for PBKDF2 by this + backend. + """ + + @abc.abstractmethod + def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, + key_material): + """ + Return length bytes derived from provided PBKDF2 parameters. + """ + + +@six.add_metaclass(abc.ABCMeta) +class RSABackend(object): + @abc.abstractmethod + def generate_rsa_private_key(self, public_exponent, key_size): + """ + Generate an RSAPrivateKey instance with public_exponent and a modulus + of key_size bits. + """ + + @abc.abstractmethod + def rsa_padding_supported(self, padding): + """ + Returns True if the backend supports the given padding options. + """ + + @abc.abstractmethod + def generate_rsa_parameters_supported(self, public_exponent, key_size): + """ + Returns True if the backend supports the given parameters for key + generation. + """ + + @abc.abstractmethod + def load_rsa_private_numbers(self, numbers): + """ + Returns an RSAPrivateKey provider. + """ + + @abc.abstractmethod + def load_rsa_public_numbers(self, numbers): + """ + Returns an RSAPublicKey provider. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DSABackend(object): + @abc.abstractmethod + def generate_dsa_parameters(self, key_size): + """ + Generate a DSAParameters instance with a modulus of key_size bits. + """ + + @abc.abstractmethod + def generate_dsa_private_key(self, parameters): + """ + Generate a DSAPrivateKey instance with parameters as a DSAParameters + object. + """ + + @abc.abstractmethod + def generate_dsa_private_key_and_parameters(self, key_size): + """ + Generate a DSAPrivateKey instance using key size only. + """ + + @abc.abstractmethod + def dsa_hash_supported(self, algorithm): + """ + Return True if the hash algorithm is supported by the backend for DSA. + """ + + @abc.abstractmethod + def dsa_parameters_supported(self, p, q, g): + """ + Return True if the parameters are supported by the backend for DSA. + """ + + @abc.abstractmethod + def load_dsa_private_numbers(self, numbers): + """ + Returns a DSAPrivateKey provider. + """ + + @abc.abstractmethod + def load_dsa_public_numbers(self, numbers): + """ + Returns a DSAPublicKey provider. + """ + + @abc.abstractmethod + def load_dsa_parameter_numbers(self, numbers): + """ + Returns a DSAParameters provider. + """ + + +@six.add_metaclass(abc.ABCMeta) +class EllipticCurveBackend(object): + @abc.abstractmethod + def elliptic_curve_signature_algorithm_supported( + self, signature_algorithm, curve + ): + """ + Returns True if the backend supports the named elliptic curve with the + specified signature algorithm. + """ + + @abc.abstractmethod + def elliptic_curve_supported(self, curve): + """ + Returns True if the backend supports the named elliptic curve. + """ + + @abc.abstractmethod + def generate_elliptic_curve_private_key(self, curve): + """ + Return an object conforming to the EllipticCurvePrivateKey interface. + """ + + @abc.abstractmethod + def load_elliptic_curve_public_numbers(self, numbers): + """ + Return an EllipticCurvePublicKey provider using the given numbers. + """ + + @abc.abstractmethod + def load_elliptic_curve_private_numbers(self, numbers): + """ + Return an EllipticCurvePrivateKey provider using the given numbers. + """ + + @abc.abstractmethod + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + """ + Returns whether the exchange algorithm is supported by this backend. + """ + + @abc.abstractmethod + def derive_elliptic_curve_private_key(self, private_value, curve): + """ + Compute the private key given the private value and curve. + """ + + +@six.add_metaclass(abc.ABCMeta) +class PEMSerializationBackend(object): + @abc.abstractmethod + def load_pem_private_key(self, data, password): + """ + Loads a private key from PEM encoded data, using the provided password + if the data is encrypted. + """ + + @abc.abstractmethod + def load_pem_public_key(self, data): + """ + Loads a public key from PEM encoded data. + """ + + @abc.abstractmethod + def load_pem_parameters(self, data): + """ + Load encryption parameters from PEM encoded data. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DERSerializationBackend(object): + @abc.abstractmethod + def load_der_private_key(self, data, password): + """ + Loads a private key from DER encoded data. Uses the provided password + if the data is encrypted. + """ + + @abc.abstractmethod + def load_der_public_key(self, data): + """ + Loads a public key from DER encoded data. + """ + + @abc.abstractmethod + def load_der_parameters(self, data): + """ + Load encryption parameters from DER encoded data. + """ + + +@six.add_metaclass(abc.ABCMeta) +class X509Backend(object): + @abc.abstractmethod + def load_pem_x509_certificate(self, data): + """ + Load an X.509 certificate from PEM encoded data. + """ + + @abc.abstractmethod + def load_der_x509_certificate(self, data): + """ + Load an X.509 certificate from DER encoded data. + """ + + @abc.abstractmethod + def load_der_x509_csr(self, data): + """ + Load an X.509 CSR from DER encoded data. + """ + + @abc.abstractmethod + def load_pem_x509_csr(self, data): + """ + Load an X.509 CSR from PEM encoded data. + """ + + @abc.abstractmethod + def create_x509_csr(self, builder, private_key, algorithm): + """ + Create and sign an X.509 CSR from a CSR builder object. + """ + + @abc.abstractmethod + def create_x509_certificate(self, builder, private_key, algorithm): + """ + Create and sign an X.509 certificate from a CertificateBuilder object. + """ + + @abc.abstractmethod + def create_x509_crl(self, builder, private_key, algorithm): + """ + Create and sign an X.509 CertificateRevocationList from a + CertificateRevocationListBuilder object. + """ + + @abc.abstractmethod + def create_x509_revoked_certificate(self, builder): + """ + Create a RevokedCertificate object from a RevokedCertificateBuilder + object. + """ + + @abc.abstractmethod + def x509_name_bytes(self, name): + """ + Compute the DER encoded bytes of an X509 Name object. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DHBackend(object): + @abc.abstractmethod + def generate_dh_parameters(self, generator, key_size): + """ + Generate a DHParameters instance with a modulus of key_size bits. + Using the given generator. Often 2 or 5. + """ + + @abc.abstractmethod + def generate_dh_private_key(self, parameters): + """ + Generate a DHPrivateKey instance with parameters as a DHParameters + object. + """ + + @abc.abstractmethod + def generate_dh_private_key_and_parameters(self, generator, key_size): + """ + Generate a DHPrivateKey instance using key size only. + Using the given generator. Often 2 or 5. + """ + + @abc.abstractmethod + def load_dh_private_numbers(self, numbers): + """ + Load a DHPrivateKey from DHPrivateNumbers + """ + + @abc.abstractmethod + def load_dh_public_numbers(self, numbers): + """ + Load a DHPublicKey from DHPublicNumbers. + """ + + @abc.abstractmethod + def load_dh_parameter_numbers(self, numbers): + """ + Load DHParameters from DHParameterNumbers. + """ + + @abc.abstractmethod + def dh_parameters_supported(self, p, g, q=None): + """ + Returns whether the backend supports DH with these parameter values. + """ + + @abc.abstractmethod + def dh_x942_serialization_supported(self): + """ + Returns True if the backend supports the serialization of DH objects + with subgroup order (q). + """ + + +@six.add_metaclass(abc.ABCMeta) +class ScryptBackend(object): + @abc.abstractmethod + def derive_scrypt(self, key_material, salt, length, n, r, p): + """ + Return bytes derived from provided Scrypt parameters. + """ diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/__init__.py new file mode 100644 index 0000000..8eadeb6 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/__init__.py @@ -0,0 +1,10 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography.hazmat.backends.openssl.backend import backend + + +__all__ = ["backend"] diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/aead.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/aead.py new file mode 100644 index 0000000..9cec3e2 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/aead.py @@ -0,0 +1,159 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography.exceptions import InvalidTag + + +_ENCRYPT = 1 +_DECRYPT = 0 + + +def _aead_cipher_name(cipher): + from cryptography.hazmat.primitives.ciphers.aead import ( + AESCCM, AESGCM, ChaCha20Poly1305 + ) + if isinstance(cipher, ChaCha20Poly1305): + return b"chacha20-poly1305" + elif isinstance(cipher, AESCCM): + return "aes-{0}-ccm".format(len(cipher._key) * 8).encode("ascii") + else: + assert isinstance(cipher, AESGCM) + return "aes-{0}-gcm".format(len(cipher._key) * 8).encode("ascii") + + +def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation): + evp_cipher = backend._lib.EVP_get_cipherbyname(cipher_name) + backend.openssl_assert(evp_cipher != backend._ffi.NULL) + ctx = backend._lib.EVP_CIPHER_CTX_new() + ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free) + res = backend._lib.EVP_CipherInit_ex( + ctx, evp_cipher, + backend._ffi.NULL, + backend._ffi.NULL, + backend._ffi.NULL, + int(operation == _ENCRYPT) + ) + backend.openssl_assert(res != 0) + res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key)) + backend.openssl_assert(res != 0) + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(nonce), + backend._ffi.NULL + ) + backend.openssl_assert(res != 0) + if operation == _DECRYPT: + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag + ) + backend.openssl_assert(res != 0) + else: + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL + ) + + res = backend._lib.EVP_CipherInit_ex( + ctx, + backend._ffi.NULL, + backend._ffi.NULL, + key, + nonce, + int(operation == _ENCRYPT) + ) + backend.openssl_assert(res != 0) + return ctx + + +def _set_length(backend, ctx, data_len): + intptr = backend._ffi.new("int *") + res = backend._lib.EVP_CipherUpdate( + ctx, + backend._ffi.NULL, + intptr, + backend._ffi.NULL, + data_len + ) + backend.openssl_assert(res != 0) + + +def _process_aad(backend, ctx, associated_data): + outlen = backend._ffi.new("int *") + res = backend._lib.EVP_CipherUpdate( + ctx, backend._ffi.NULL, outlen, associated_data, len(associated_data) + ) + backend.openssl_assert(res != 0) + + +def _process_data(backend, ctx, data): + outlen = backend._ffi.new("int *") + buf = backend._ffi.new("unsigned char[]", len(data)) + res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data)) + backend.openssl_assert(res != 0) + return backend._ffi.buffer(buf, outlen[0])[:] + + +def _encrypt(backend, cipher, nonce, data, associated_data, tag_length): + from cryptography.hazmat.primitives.ciphers.aead import AESCCM + cipher_name = _aead_cipher_name(cipher) + ctx = _aead_setup( + backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT + ) + # CCM requires us to pass the length of the data before processing anything + # However calling this with any other AEAD results in an error + if isinstance(cipher, AESCCM): + _set_length(backend, ctx, len(data)) + + _process_aad(backend, ctx, associated_data) + processed_data = _process_data(backend, ctx, data) + outlen = backend._ffi.new("int *") + res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen) + backend.openssl_assert(res != 0) + backend.openssl_assert(outlen[0] == 0) + tag_buf = backend._ffi.new("unsigned char[]", tag_length) + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_GET_TAG, tag_length, tag_buf + ) + backend.openssl_assert(res != 0) + tag = backend._ffi.buffer(tag_buf)[:] + + return processed_data + tag + + +def _decrypt(backend, cipher, nonce, data, associated_data, tag_length): + from cryptography.hazmat.primitives.ciphers.aead import AESCCM + if len(data) < tag_length: + raise InvalidTag + tag = data[-tag_length:] + data = data[:-tag_length] + cipher_name = _aead_cipher_name(cipher) + ctx = _aead_setup( + backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT + ) + # CCM requires us to pass the length of the data before processing anything + # However calling this with any other AEAD results in an error + if isinstance(cipher, AESCCM): + _set_length(backend, ctx, len(data)) + + _process_aad(backend, ctx, associated_data) + # CCM has a different error path if the tag doesn't match. Errors are + # raised in Update and Final is irrelevant. + if isinstance(cipher, AESCCM): + outlen = backend._ffi.new("int *") + buf = backend._ffi.new("unsigned char[]", len(data)) + res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data)) + if res != 1: + backend._consume_errors() + raise InvalidTag + + processed_data = backend._ffi.buffer(buf, outlen[0])[:] + else: + processed_data = _process_data(backend, ctx, data) + outlen = backend._ffi.new("int *") + res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen) + if res == 0: + backend._consume_errors() + raise InvalidTag + + return processed_data diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/backend.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/backend.py new file mode 100644 index 0000000..af14bfa --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/backend.py @@ -0,0 +1,1974 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import base64 +import calendar +import collections +import contextlib +import itertools +from contextlib import contextmanager + +import six + +from cryptography import utils, x509 +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.backends.interfaces import ( + CMACBackend, CipherBackend, DERSerializationBackend, DHBackend, DSABackend, + EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, + PEMSerializationBackend, RSABackend, ScryptBackend, X509Backend +) +from cryptography.hazmat.backends.openssl import aead +from cryptography.hazmat.backends.openssl.ciphers import _CipherContext +from cryptography.hazmat.backends.openssl.cmac import _CMACContext +from cryptography.hazmat.backends.openssl.decode_asn1 import _Integers +from cryptography.hazmat.backends.openssl.dh import ( + _DHParameters, _DHPrivateKey, _DHPublicKey, _dh_params_dup +) +from cryptography.hazmat.backends.openssl.dsa import ( + _DSAParameters, _DSAPrivateKey, _DSAPublicKey +) +from cryptography.hazmat.backends.openssl.ec import ( + _EllipticCurvePrivateKey, _EllipticCurvePublicKey +) +from cryptography.hazmat.backends.openssl.encode_asn1 import ( + _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS, + _CRL_EXTENSION_ENCODE_HANDLERS, _EXTENSION_ENCODE_HANDLERS, + _encode_asn1_int_gc, _encode_asn1_str_gc, _encode_name_gc, _txt2obj_gc, +) +from cryptography.hazmat.backends.openssl.hashes import _HashContext +from cryptography.hazmat.backends.openssl.hmac import _HMACContext +from cryptography.hazmat.backends.openssl.rsa import ( + _RSAPrivateKey, _RSAPublicKey +) +from cryptography.hazmat.backends.openssl.x25519 import ( + _X25519PrivateKey, _X25519PublicKey +) +from cryptography.hazmat.backends.openssl.x509 import ( + _Certificate, _CertificateRevocationList, + _CertificateSigningRequest, _RevokedCertificate +) +from cryptography.hazmat.bindings.openssl import binding +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa +from cryptography.hazmat.primitives.asymmetric.padding import ( + MGF1, OAEP, PKCS1v15, PSS +) +from cryptography.hazmat.primitives.ciphers.algorithms import ( + AES, ARC4, Blowfish, CAST5, Camellia, ChaCha20, IDEA, SEED, TripleDES +) +from cryptography.hazmat.primitives.ciphers.modes import ( + CBC, CFB, CFB8, CTR, ECB, GCM, OFB, XTS +) +from cryptography.hazmat.primitives.kdf import scrypt + + +_MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) + + +@utils.register_interface(CipherBackend) +@utils.register_interface(CMACBackend) +@utils.register_interface(DERSerializationBackend) +@utils.register_interface(DHBackend) +@utils.register_interface(DSABackend) +@utils.register_interface(EllipticCurveBackend) +@utils.register_interface(HashBackend) +@utils.register_interface(HMACBackend) +@utils.register_interface(PBKDF2HMACBackend) +@utils.register_interface(RSABackend) +@utils.register_interface(PEMSerializationBackend) +@utils.register_interface(X509Backend) +@utils.register_interface_if( + binding.Binding().lib.Cryptography_HAS_SCRYPT, ScryptBackend +) +class Backend(object): + """ + OpenSSL API binding interfaces. + """ + name = "openssl" + + def __init__(self): + self._binding = binding.Binding() + self._ffi = self._binding.ffi + self._lib = self._binding.lib + + self._cipher_registry = {} + self._register_default_ciphers() + self.activate_osrandom_engine() + self._dh_types = [self._lib.EVP_PKEY_DH] + if self._lib.Cryptography_HAS_EVP_PKEY_DHX: + self._dh_types.append(self._lib.EVP_PKEY_DHX) + + def openssl_assert(self, ok): + return binding._openssl_assert(self._lib, ok) + + def activate_builtin_random(self): + # Obtain a new structural reference. + e = self._lib.ENGINE_get_default_RAND() + if e != self._ffi.NULL: + self._lib.ENGINE_unregister_RAND(e) + # Reset the RNG to use the new engine. + self._lib.RAND_cleanup() + # decrement the structural reference from get_default_RAND + res = self._lib.ENGINE_finish(e) + self.openssl_assert(res == 1) + + @contextlib.contextmanager + def _get_osurandom_engine(self): + # Fetches an engine by id and returns it. This creates a structural + # reference. + e = self._lib.ENGINE_by_id(self._binding._osrandom_engine_id) + self.openssl_assert(e != self._ffi.NULL) + # Initialize the engine for use. This adds a functional reference. + res = self._lib.ENGINE_init(e) + self.openssl_assert(res == 1) + + try: + yield e + finally: + # Decrement the structural ref incremented by ENGINE_by_id. + res = self._lib.ENGINE_free(e) + self.openssl_assert(res == 1) + # Decrement the functional ref incremented by ENGINE_init. + res = self._lib.ENGINE_finish(e) + self.openssl_assert(res == 1) + + def activate_osrandom_engine(self): + # Unregister and free the current engine. + self.activate_builtin_random() + with self._get_osurandom_engine() as e: + # Set the engine as the default RAND provider. + res = self._lib.ENGINE_set_default_RAND(e) + self.openssl_assert(res == 1) + # Reset the RNG to use the new engine. + self._lib.RAND_cleanup() + + def osrandom_engine_implementation(self): + buf = self._ffi.new("char[]", 64) + with self._get_osurandom_engine() as e: + res = self._lib.ENGINE_ctrl_cmd(e, b"get_implementation", + len(buf), buf, + self._ffi.NULL, 0) + self.openssl_assert(res > 0) + return self._ffi.string(buf).decode('ascii') + + def openssl_version_text(self): + """ + Friendly string name of the loaded OpenSSL library. This is not + necessarily the same version as it was compiled against. + + Example: OpenSSL 1.0.1e 11 Feb 2013 + """ + return self._ffi.string( + self._lib.OpenSSL_version(self._lib.OPENSSL_VERSION) + ).decode("ascii") + + def openssl_version_number(self): + return self._lib.OpenSSL_version_num() + + def create_hmac_ctx(self, key, algorithm): + return _HMACContext(self, key, algorithm) + + def _build_openssl_digest_name(self, algorithm): + if algorithm.name == "blake2b" or algorithm.name == "blake2s": + alg = "{0}{1}".format( + algorithm.name, algorithm.digest_size * 8 + ).encode("ascii") + else: + alg = algorithm.name.encode("ascii") + + return alg + + def hash_supported(self, algorithm): + name = self._build_openssl_digest_name(algorithm) + digest = self._lib.EVP_get_digestbyname(name) + return digest != self._ffi.NULL + + def hmac_supported(self, algorithm): + return self.hash_supported(algorithm) + + def create_hash_ctx(self, algorithm): + return _HashContext(self, algorithm) + + def cipher_supported(self, cipher, mode): + try: + adapter = self._cipher_registry[type(cipher), type(mode)] + except KeyError: + return False + evp_cipher = adapter(self, cipher, mode) + return self._ffi.NULL != evp_cipher + + def register_cipher_adapter(self, cipher_cls, mode_cls, adapter): + if (cipher_cls, mode_cls) in self._cipher_registry: + raise ValueError("Duplicate registration for: {0} {1}.".format( + cipher_cls, mode_cls) + ) + self._cipher_registry[cipher_cls, mode_cls] = adapter + + def _register_default_ciphers(self): + for mode_cls in [CBC, CTR, ECB, OFB, CFB, CFB8, GCM]: + self.register_cipher_adapter( + AES, + mode_cls, + GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}") + ) + for mode_cls in [CBC, CTR, ECB, OFB, CFB]: + self.register_cipher_adapter( + Camellia, + mode_cls, + GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}") + ) + for mode_cls in [CBC, CFB, CFB8, OFB]: + self.register_cipher_adapter( + TripleDES, + mode_cls, + GetCipherByName("des-ede3-{mode.name}") + ) + self.register_cipher_adapter( + TripleDES, + ECB, + GetCipherByName("des-ede3") + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + Blowfish, + mode_cls, + GetCipherByName("bf-{mode.name}") + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + SEED, + mode_cls, + GetCipherByName("seed-{mode.name}") + ) + for cipher_cls, mode_cls in itertools.product( + [CAST5, IDEA], + [CBC, OFB, CFB, ECB], + ): + self.register_cipher_adapter( + cipher_cls, + mode_cls, + GetCipherByName("{cipher.name}-{mode.name}") + ) + self.register_cipher_adapter( + ARC4, + type(None), + GetCipherByName("rc4") + ) + self.register_cipher_adapter( + ChaCha20, + type(None), + GetCipherByName("chacha20") + ) + self.register_cipher_adapter(AES, XTS, _get_xts_cipher) + + def create_symmetric_encryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) + + def create_symmetric_decryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) + + def pbkdf2_hmac_supported(self, algorithm): + return self.hmac_supported(algorithm) + + def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, + key_material): + buf = self._ffi.new("unsigned char[]", length) + evp_md = self._lib.EVP_get_digestbyname( + algorithm.name.encode("ascii")) + self.openssl_assert(evp_md != self._ffi.NULL) + res = self._lib.PKCS5_PBKDF2_HMAC( + key_material, + len(key_material), + salt, + len(salt), + iterations, + evp_md, + length, + buf + ) + self.openssl_assert(res == 1) + return self._ffi.buffer(buf)[:] + + def _consume_errors(self): + return binding._consume_errors(self._lib) + + def _bn_to_int(self, bn): + assert bn != self._ffi.NULL + + if not six.PY2: + # Python 3 has constant time from_bytes, so use that. + bn_num_bytes = self._lib.BN_num_bytes(bn) + bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes) + bin_len = self._lib.BN_bn2bin(bn, bin_ptr) + # A zero length means the BN has value 0 + self.openssl_assert(bin_len >= 0) + return int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big") + else: + # Under Python 2 the best we can do is hex() + hex_cdata = self._lib.BN_bn2hex(bn) + self.openssl_assert(hex_cdata != self._ffi.NULL) + hex_str = self._ffi.string(hex_cdata) + self._lib.OPENSSL_free(hex_cdata) + return int(hex_str, 16) + + def _int_to_bn(self, num, bn=None): + """ + Converts a python integer to a BIGNUM. The returned BIGNUM will not + be garbage collected (to support adding them to structs that take + ownership of the object). Be sure to register it for GC if it will + be discarded after use. + """ + assert bn is None or bn != self._ffi.NULL + + if bn is None: + bn = self._ffi.NULL + + if not six.PY2: + # Python 3 has constant time to_bytes, so use that. + + binary = num.to_bytes(int(num.bit_length() / 8.0 + 1), "big") + bn_ptr = self._lib.BN_bin2bn(binary, len(binary), bn) + self.openssl_assert(bn_ptr != self._ffi.NULL) + return bn_ptr + + else: + # Under Python 2 the best we can do is hex(), [2:] removes the 0x + # prefix. + hex_num = hex(num).rstrip("L")[2:].encode("ascii") + bn_ptr = self._ffi.new("BIGNUM **") + bn_ptr[0] = bn + res = self._lib.BN_hex2bn(bn_ptr, hex_num) + self.openssl_assert(res != 0) + self.openssl_assert(bn_ptr[0] != self._ffi.NULL) + return bn_ptr[0] + + def generate_rsa_private_key(self, public_exponent, key_size): + rsa._verify_rsa_parameters(public_exponent, key_size) + + rsa_cdata = self._lib.RSA_new() + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + + bn = self._int_to_bn(public_exponent) + bn = self._ffi.gc(bn, self._lib.BN_free) + + res = self._lib.RSA_generate_key_ex( + rsa_cdata, key_size, bn, self._ffi.NULL + ) + self.openssl_assert(res == 1) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + + return _RSAPrivateKey(self, rsa_cdata, evp_pkey) + + def generate_rsa_parameters_supported(self, public_exponent, key_size): + return (public_exponent >= 3 and public_exponent & 1 != 0 and + key_size >= 512) + + def load_rsa_private_numbers(self, numbers): + rsa._check_private_key_components( + numbers.p, + numbers.q, + numbers.d, + numbers.dmp1, + numbers.dmq1, + numbers.iqmp, + numbers.public_numbers.e, + numbers.public_numbers.n + ) + rsa_cdata = self._lib.RSA_new() + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + p = self._int_to_bn(numbers.p) + q = self._int_to_bn(numbers.q) + d = self._int_to_bn(numbers.d) + dmp1 = self._int_to_bn(numbers.dmp1) + dmq1 = self._int_to_bn(numbers.dmq1) + iqmp = self._int_to_bn(numbers.iqmp) + e = self._int_to_bn(numbers.public_numbers.e) + n = self._int_to_bn(numbers.public_numbers.n) + res = self._lib.RSA_set0_factors(rsa_cdata, p, q) + self.openssl_assert(res == 1) + res = self._lib.RSA_set0_key(rsa_cdata, n, e, d) + self.openssl_assert(res == 1) + res = self._lib.RSA_set0_crt_params(rsa_cdata, dmp1, dmq1, iqmp) + self.openssl_assert(res == 1) + res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL) + self.openssl_assert(res == 1) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + + return _RSAPrivateKey(self, rsa_cdata, evp_pkey) + + def load_rsa_public_numbers(self, numbers): + rsa._check_public_key_components(numbers.e, numbers.n) + rsa_cdata = self._lib.RSA_new() + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + e = self._int_to_bn(numbers.e) + n = self._int_to_bn(numbers.n) + res = self._lib.RSA_set0_key(rsa_cdata, n, e, self._ffi.NULL) + self.openssl_assert(res == 1) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + + def _create_evp_pkey_gc(self): + evp_pkey = self._lib.EVP_PKEY_new() + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return evp_pkey + + def _rsa_cdata_to_evp_pkey(self, rsa_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def _bytes_to_bio(self, data): + """ + Return a _MemoryBIO namedtuple of (BIO, char*). + + The char* is the storage for the BIO and it must stay alive until the + BIO is finished with. + """ + data_char_p = self._ffi.new("char[]", data) + bio = self._lib.BIO_new_mem_buf( + data_char_p, len(data) + ) + self.openssl_assert(bio != self._ffi.NULL) + + return _MemoryBIO(self._ffi.gc(bio, self._lib.BIO_free), data_char_p) + + def _create_mem_bio_gc(self): + """ + Creates an empty memory BIO. + """ + bio_method = self._lib.BIO_s_mem() + self.openssl_assert(bio_method != self._ffi.NULL) + bio = self._lib.BIO_new(bio_method) + self.openssl_assert(bio != self._ffi.NULL) + bio = self._ffi.gc(bio, self._lib.BIO_free) + return bio + + def _read_mem_bio(self, bio): + """ + Reads a memory BIO. This only works on memory BIOs. + """ + buf = self._ffi.new("char **") + buf_len = self._lib.BIO_get_mem_data(bio, buf) + self.openssl_assert(buf_len > 0) + self.openssl_assert(buf[0] != self._ffi.NULL) + bio_data = self._ffi.buffer(buf[0], buf_len)[:] + return bio_data + + def _evp_pkey_to_private_key(self, evp_pkey): + """ + Return the appropriate type of PrivateKey given an evp_pkey cdata + pointer. + """ + + key_type = self._lib.EVP_PKEY_id(evp_pkey) + + if key_type == self._lib.EVP_PKEY_RSA: + rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey) + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + return _RSAPrivateKey(self, rsa_cdata, evp_pkey) + elif key_type == self._lib.EVP_PKEY_DSA: + dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + return _DSAPrivateKey(self, dsa_cdata, evp_pkey) + elif key_type == self._lib.EVP_PKEY_EC: + ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + elif key_type in self._dh_types: + dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey) + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHPrivateKey(self, dh_cdata, evp_pkey) + else: + raise UnsupportedAlgorithm("Unsupported key type.") + + def _evp_pkey_to_public_key(self, evp_pkey): + """ + Return the appropriate type of PublicKey given an evp_pkey cdata + pointer. + """ + + key_type = self._lib.EVP_PKEY_id(evp_pkey) + + if key_type == self._lib.EVP_PKEY_RSA: + rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey) + self.openssl_assert(rsa_cdata != self._ffi.NULL) + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + elif key_type == self._lib.EVP_PKEY_DSA: + dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + return _DSAPublicKey(self, dsa_cdata, evp_pkey) + elif key_type == self._lib.EVP_PKEY_EC: + ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + elif key_type in self._dh_types: + dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey) + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHPublicKey(self, dh_cdata, evp_pkey) + else: + raise UnsupportedAlgorithm("Unsupported key type.") + + def _oaep_hash_supported(self, algorithm): + if self._lib.Cryptography_HAS_RSA_OAEP_MD: + return isinstance( + algorithm, ( + hashes.SHA1, + hashes.SHA224, + hashes.SHA256, + hashes.SHA384, + hashes.SHA512, + ) + ) + else: + return isinstance(algorithm, hashes.SHA1) + + def rsa_padding_supported(self, padding): + if isinstance(padding, PKCS1v15): + return True + elif isinstance(padding, PSS) and isinstance(padding._mgf, MGF1): + return self.hash_supported(padding._mgf._algorithm) + elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1): + return ( + self._oaep_hash_supported(padding._mgf._algorithm) and + self._oaep_hash_supported(padding._algorithm) and + ( + (padding._label is None or len(padding._label) == 0) or + self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1 + ) + ) + else: + return False + + def generate_dsa_parameters(self, key_size): + if key_size not in (1024, 2048, 3072): + raise ValueError("Key size must be 1024 or 2048 or 3072 bits.") + + ctx = self._lib.DSA_new() + self.openssl_assert(ctx != self._ffi.NULL) + ctx = self._ffi.gc(ctx, self._lib.DSA_free) + + res = self._lib.DSA_generate_parameters_ex( + ctx, key_size, self._ffi.NULL, 0, + self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + + self.openssl_assert(res == 1) + + return _DSAParameters(self, ctx) + + def generate_dsa_private_key(self, parameters): + ctx = self._lib.DSAparams_dup(parameters._dsa_cdata) + self.openssl_assert(ctx != self._ffi.NULL) + ctx = self._ffi.gc(ctx, self._lib.DSA_free) + self._lib.DSA_generate_key(ctx) + evp_pkey = self._dsa_cdata_to_evp_pkey(ctx) + + return _DSAPrivateKey(self, ctx, evp_pkey) + + def generate_dsa_private_key_and_parameters(self, key_size): + parameters = self.generate_dsa_parameters(key_size) + return self.generate_dsa_private_key(parameters) + + def _dsa_cdata_set_values(self, dsa_cdata, p, q, g, pub_key, priv_key): + res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g) + self.openssl_assert(res == 1) + res = self._lib.DSA_set0_key(dsa_cdata, pub_key, priv_key) + self.openssl_assert(res == 1) + + def load_dsa_private_numbers(self, numbers): + dsa._check_dsa_private_numbers(numbers) + parameter_numbers = numbers.public_numbers.parameter_numbers + + dsa_cdata = self._lib.DSA_new() + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + p = self._int_to_bn(parameter_numbers.p) + q = self._int_to_bn(parameter_numbers.q) + g = self._int_to_bn(parameter_numbers.g) + pub_key = self._int_to_bn(numbers.public_numbers.y) + priv_key = self._int_to_bn(numbers.x) + self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key) + + evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata) + + return _DSAPrivateKey(self, dsa_cdata, evp_pkey) + + def load_dsa_public_numbers(self, numbers): + dsa._check_dsa_parameters(numbers.parameter_numbers) + dsa_cdata = self._lib.DSA_new() + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + p = self._int_to_bn(numbers.parameter_numbers.p) + q = self._int_to_bn(numbers.parameter_numbers.q) + g = self._int_to_bn(numbers.parameter_numbers.g) + pub_key = self._int_to_bn(numbers.y) + priv_key = self._ffi.NULL + self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key) + + evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata) + + return _DSAPublicKey(self, dsa_cdata, evp_pkey) + + def load_dsa_parameter_numbers(self, numbers): + dsa._check_dsa_parameters(numbers) + dsa_cdata = self._lib.DSA_new() + self.openssl_assert(dsa_cdata != self._ffi.NULL) + dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) + + p = self._int_to_bn(numbers.p) + q = self._int_to_bn(numbers.q) + g = self._int_to_bn(numbers.g) + res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g) + self.openssl_assert(res == 1) + + return _DSAParameters(self, dsa_cdata) + + def _dsa_cdata_to_evp_pkey(self, dsa_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_DSA(evp_pkey, dsa_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def dsa_hash_supported(self, algorithm): + return self.hash_supported(algorithm) + + def dsa_parameters_supported(self, p, q, g): + return True + + def cmac_algorithm_supported(self, algorithm): + return self.cipher_supported( + algorithm, CBC(b"\x00" * algorithm.block_size) + ) + + def create_cmac_ctx(self, algorithm): + return _CMACContext(self, algorithm) + + def create_x509_csr(self, builder, private_key, algorithm): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError('Algorithm must be a registered hash algorithm.') + + if ( + isinstance(algorithm, hashes.MD5) and not + isinstance(private_key, rsa.RSAPrivateKey) + ): + raise ValueError( + "MD5 is not a supported hash algorithm for EC/DSA CSRs" + ) + + # Resolve the signature algorithm. + evp_md = self._lib.EVP_get_digestbyname( + algorithm.name.encode('ascii') + ) + self.openssl_assert(evp_md != self._ffi.NULL) + + # Create an empty request. + x509_req = self._lib.X509_REQ_new() + self.openssl_assert(x509_req != self._ffi.NULL) + x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) + + # Set x509 version. + res = self._lib.X509_REQ_set_version(x509_req, x509.Version.v1.value) + self.openssl_assert(res == 1) + + # Set subject name. + res = self._lib.X509_REQ_set_subject_name( + x509_req, _encode_name_gc(self, builder._subject_name) + ) + self.openssl_assert(res == 1) + + # Set subject public key. + public_key = private_key.public_key() + res = self._lib.X509_REQ_set_pubkey( + x509_req, public_key._evp_pkey + ) + self.openssl_assert(res == 1) + + # Add extensions. + sk_extension = self._lib.sk_X509_EXTENSION_new_null() + self.openssl_assert(sk_extension != self._ffi.NULL) + sk_extension = self._ffi.gc( + sk_extension, self._lib.sk_X509_EXTENSION_free + ) + # gc is not necessary for CSRs, as sk_X509_EXTENSION_free + # will release all the X509_EXTENSIONs. + self._create_x509_extensions( + extensions=builder._extensions, + handlers=_EXTENSION_ENCODE_HANDLERS, + x509_obj=sk_extension, + add_func=self._lib.sk_X509_EXTENSION_insert, + gc=False + ) + res = self._lib.X509_REQ_add_extensions(x509_req, sk_extension) + self.openssl_assert(res == 1) + + # Sign the request using the requester's private key. + res = self._lib.X509_REQ_sign( + x509_req, private_key._evp_pkey, evp_md + ) + if res == 0: + errors = self._consume_errors() + self.openssl_assert( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_RSA, + self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY + ) + ) + + raise ValueError("Digest too big for RSA key") + + return _CertificateSigningRequest(self, x509_req) + + def create_x509_certificate(self, builder, private_key, algorithm): + if not isinstance(builder, x509.CertificateBuilder): + raise TypeError('Builder type mismatch.') + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError('Algorithm must be a registered hash algorithm.') + + if ( + isinstance(algorithm, hashes.MD5) and not + isinstance(private_key, rsa.RSAPrivateKey) + ): + raise ValueError( + "MD5 is not a supported hash algorithm for EC/DSA certificates" + ) + + # Resolve the signature algorithm. + evp_md = self._lib.EVP_get_digestbyname( + algorithm.name.encode('ascii') + ) + self.openssl_assert(evp_md != self._ffi.NULL) + + # Create an empty certificate. + x509_cert = self._lib.X509_new() + x509_cert = self._ffi.gc(x509_cert, backend._lib.X509_free) + + # Set the x509 version. + res = self._lib.X509_set_version(x509_cert, builder._version.value) + self.openssl_assert(res == 1) + + # Set the subject's name. + res = self._lib.X509_set_subject_name( + x509_cert, _encode_name_gc(self, builder._subject_name) + ) + self.openssl_assert(res == 1) + + # Set the subject's public key. + res = self._lib.X509_set_pubkey( + x509_cert, builder._public_key._evp_pkey + ) + self.openssl_assert(res == 1) + + # Set the certificate serial number. + serial_number = _encode_asn1_int_gc(self, builder._serial_number) + res = self._lib.X509_set_serialNumber(x509_cert, serial_number) + self.openssl_assert(res == 1) + + # Set the "not before" time. + res = self._lib.ASN1_TIME_set( + self._lib.X509_get_notBefore(x509_cert), + calendar.timegm(builder._not_valid_before.timetuple()) + ) + if res == self._ffi.NULL: + self._raise_time_set_error() + + # Set the "not after" time. + res = self._lib.ASN1_TIME_set( + self._lib.X509_get_notAfter(x509_cert), + calendar.timegm(builder._not_valid_after.timetuple()) + ) + if res == self._ffi.NULL: + self._raise_time_set_error() + + # Add extensions. + self._create_x509_extensions( + extensions=builder._extensions, + handlers=_EXTENSION_ENCODE_HANDLERS, + x509_obj=x509_cert, + add_func=self._lib.X509_add_ext, + gc=True + ) + + # Set the issuer name. + res = self._lib.X509_set_issuer_name( + x509_cert, _encode_name_gc(self, builder._issuer_name) + ) + self.openssl_assert(res == 1) + + # Sign the certificate with the issuer's private key. + res = self._lib.X509_sign( + x509_cert, private_key._evp_pkey, evp_md + ) + if res == 0: + errors = self._consume_errors() + self.openssl_assert( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_RSA, + self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY + ) + ) + raise ValueError("Digest too big for RSA key") + + return _Certificate(self, x509_cert) + + def _raise_time_set_error(self): + errors = self._consume_errors() + self.openssl_assert( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_ASN1, + self._lib.ASN1_R_ERROR_GETTING_TIME + ) + ) + raise ValueError( + "Invalid time. This error can occur if you set a time too far in " + "the future on Windows." + ) + + def create_x509_crl(self, builder, private_key, algorithm): + if not isinstance(builder, x509.CertificateRevocationListBuilder): + raise TypeError('Builder type mismatch.') + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError('Algorithm must be a registered hash algorithm.') + + if ( + isinstance(algorithm, hashes.MD5) and not + isinstance(private_key, rsa.RSAPrivateKey) + ): + raise ValueError( + "MD5 is not a supported hash algorithm for EC/DSA CRLs" + ) + + evp_md = self._lib.EVP_get_digestbyname( + algorithm.name.encode('ascii') + ) + self.openssl_assert(evp_md != self._ffi.NULL) + + # Create an empty CRL. + x509_crl = self._lib.X509_CRL_new() + x509_crl = self._ffi.gc(x509_crl, backend._lib.X509_CRL_free) + + # Set the x509 CRL version. We only support v2 (integer value 1). + res = self._lib.X509_CRL_set_version(x509_crl, 1) + self.openssl_assert(res == 1) + + # Set the issuer name. + res = self._lib.X509_CRL_set_issuer_name( + x509_crl, _encode_name_gc(self, builder._issuer_name) + ) + self.openssl_assert(res == 1) + + # Set the last update time. + last_update = self._lib.ASN1_TIME_set( + self._ffi.NULL, calendar.timegm(builder._last_update.timetuple()) + ) + self.openssl_assert(last_update != self._ffi.NULL) + last_update = self._ffi.gc(last_update, self._lib.ASN1_TIME_free) + res = self._lib.X509_CRL_set_lastUpdate(x509_crl, last_update) + self.openssl_assert(res == 1) + + # Set the next update time. + next_update = self._lib.ASN1_TIME_set( + self._ffi.NULL, calendar.timegm(builder._next_update.timetuple()) + ) + self.openssl_assert(next_update != self._ffi.NULL) + next_update = self._ffi.gc(next_update, self._lib.ASN1_TIME_free) + res = self._lib.X509_CRL_set_nextUpdate(x509_crl, next_update) + self.openssl_assert(res == 1) + + # Add extensions. + self._create_x509_extensions( + extensions=builder._extensions, + handlers=_CRL_EXTENSION_ENCODE_HANDLERS, + x509_obj=x509_crl, + add_func=self._lib.X509_CRL_add_ext, + gc=True + ) + + # add revoked certificates + for revoked_cert in builder._revoked_certificates: + # Duplicating because the X509_CRL takes ownership and will free + # this memory when X509_CRL_free is called. + revoked = self._lib.Cryptography_X509_REVOKED_dup( + revoked_cert._x509_revoked + ) + self.openssl_assert(revoked != self._ffi.NULL) + res = self._lib.X509_CRL_add0_revoked(x509_crl, revoked) + self.openssl_assert(res == 1) + + res = self._lib.X509_CRL_sign( + x509_crl, private_key._evp_pkey, evp_md + ) + if res == 0: + errors = self._consume_errors() + self.openssl_assert( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_RSA, + self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY + ) + ) + raise ValueError("Digest too big for RSA key") + + return _CertificateRevocationList(self, x509_crl) + + def _create_x509_extensions(self, extensions, handlers, x509_obj, + add_func, gc): + for i, extension in enumerate(extensions): + x509_extension = self._create_x509_extension( + handlers, extension + ) + self.openssl_assert(x509_extension != self._ffi.NULL) + + if gc: + x509_extension = self._ffi.gc( + x509_extension, self._lib.X509_EXTENSION_free + ) + res = add_func(x509_obj, x509_extension, i) + self.openssl_assert(res >= 1) + + def _create_raw_x509_extension(self, extension, value): + obj = _txt2obj_gc(self, extension.oid.dotted_string) + return self._lib.X509_EXTENSION_create_by_OBJ( + self._ffi.NULL, obj, 1 if extension.critical else 0, value + ) + + def _create_x509_extension(self, handlers, extension): + if isinstance(extension.value, x509.UnrecognizedExtension): + value = _encode_asn1_str_gc( + self, extension.value.value, len(extension.value.value) + ) + return self._create_raw_x509_extension(extension, value) + elif isinstance(extension.value, x509.TLSFeature): + asn1 = _Integers([x.value for x in extension.value]).dump() + value = _encode_asn1_str_gc(self, asn1, len(asn1)) + return self._create_raw_x509_extension(extension, value) + else: + try: + encode = handlers[extension.oid] + except KeyError: + raise NotImplementedError( + 'Extension not supported: {0}'.format(extension.oid) + ) + + ext_struct = encode(self, extension.value) + nid = self._lib.OBJ_txt2nid( + extension.oid.dotted_string.encode("ascii") + ) + backend.openssl_assert(nid != self._lib.NID_undef) + return self._lib.X509V3_EXT_i2d( + nid, 1 if extension.critical else 0, ext_struct + ) + + def create_x509_revoked_certificate(self, builder): + if not isinstance(builder, x509.RevokedCertificateBuilder): + raise TypeError('Builder type mismatch.') + + x509_revoked = self._lib.X509_REVOKED_new() + self.openssl_assert(x509_revoked != self._ffi.NULL) + x509_revoked = self._ffi.gc(x509_revoked, self._lib.X509_REVOKED_free) + serial_number = _encode_asn1_int_gc(self, builder._serial_number) + res = self._lib.X509_REVOKED_set_serialNumber( + x509_revoked, serial_number + ) + self.openssl_assert(res == 1) + rev_date = self._lib.ASN1_TIME_set( + self._ffi.NULL, + calendar.timegm(builder._revocation_date.timetuple()) + ) + self.openssl_assert(rev_date != self._ffi.NULL) + rev_date = self._ffi.gc(rev_date, self._lib.ASN1_TIME_free) + res = self._lib.X509_REVOKED_set_revocationDate(x509_revoked, rev_date) + self.openssl_assert(res == 1) + # add CRL entry extensions + self._create_x509_extensions( + extensions=builder._extensions, + handlers=_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS, + x509_obj=x509_revoked, + add_func=self._lib.X509_REVOKED_add_ext, + gc=True + ) + return _RevokedCertificate(self, None, x509_revoked) + + def load_pem_private_key(self, data, password): + return self._load_key( + self._lib.PEM_read_bio_PrivateKey, + self._evp_pkey_to_private_key, + data, + password, + ) + + def load_pem_public_key(self, data): + mem_bio = self._bytes_to_bio(data) + evp_pkey = self._lib.PEM_read_bio_PUBKEY( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if evp_pkey != self._ffi.NULL: + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return self._evp_pkey_to_public_key(evp_pkey) + else: + # It's not a (RSA/DSA/ECDSA) subjectPublicKeyInfo, but we still + # need to check to see if it is a pure PKCS1 RSA public key (not + # embedded in a subjectPublicKeyInfo) + self._consume_errors() + res = self._lib.BIO_reset(mem_bio.bio) + self.openssl_assert(res == 1) + rsa_cdata = self._lib.PEM_read_bio_RSAPublicKey( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if rsa_cdata != self._ffi.NULL: + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + else: + self._handle_key_loading_error() + + def load_pem_parameters(self, data): + mem_bio = self._bytes_to_bio(data) + # only DH is supported currently + dh_cdata = self._lib.PEM_read_bio_DHparams( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + else: + self._handle_key_loading_error() + + def load_der_private_key(self, data, password): + # OpenSSL has a function called d2i_AutoPrivateKey that in theory + # handles this automatically, however it doesn't handle encrypted + # private keys. Instead we try to load the key two different ways. + # First we'll try to load it as a traditional key. + bio_data = self._bytes_to_bio(data) + key = self._evp_pkey_from_der_traditional_key(bio_data, password) + if key: + return self._evp_pkey_to_private_key(key) + else: + # Finally we try to load it with the method that handles encrypted + # PKCS8 properly. + return self._load_key( + self._lib.d2i_PKCS8PrivateKey_bio, + self._evp_pkey_to_private_key, + data, + password, + ) + + def _evp_pkey_from_der_traditional_key(self, bio_data, password): + key = self._lib.d2i_PrivateKey_bio(bio_data.bio, self._ffi.NULL) + if key != self._ffi.NULL: + key = self._ffi.gc(key, self._lib.EVP_PKEY_free) + if password is not None: + raise TypeError( + "Password was given but private key is not encrypted." + ) + + return key + else: + self._consume_errors() + return None + + def load_der_public_key(self, data): + mem_bio = self._bytes_to_bio(data) + evp_pkey = self._lib.d2i_PUBKEY_bio(mem_bio.bio, self._ffi.NULL) + if evp_pkey != self._ffi.NULL: + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + return self._evp_pkey_to_public_key(evp_pkey) + else: + # It's not a (RSA/DSA/ECDSA) subjectPublicKeyInfo, but we still + # need to check to see if it is a pure PKCS1 RSA public key (not + # embedded in a subjectPublicKeyInfo) + self._consume_errors() + res = self._lib.BIO_reset(mem_bio.bio) + self.openssl_assert(res == 1) + rsa_cdata = self._lib.d2i_RSAPublicKey_bio( + mem_bio.bio, self._ffi.NULL + ) + if rsa_cdata != self._ffi.NULL: + rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) + evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + return _RSAPublicKey(self, rsa_cdata, evp_pkey) + else: + self._handle_key_loading_error() + + def load_der_parameters(self, data): + mem_bio = self._bytes_to_bio(data) + dh_cdata = self._lib.d2i_DHparams_bio( + mem_bio.bio, self._ffi.NULL + ) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + elif self._lib.Cryptography_HAS_EVP_PKEY_DHX: + # We check to see if the is dhx. + self._consume_errors() + res = self._lib.BIO_reset(mem_bio.bio) + self.openssl_assert(res == 1) + dh_cdata = self._lib.Cryptography_d2i_DHxparams_bio( + mem_bio.bio, self._ffi.NULL + ) + if dh_cdata != self._ffi.NULL: + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + return _DHParameters(self, dh_cdata) + + self._handle_key_loading_error() + + def load_pem_x509_certificate(self, data): + mem_bio = self._bytes_to_bio(data) + x509 = self._lib.PEM_read_bio_X509( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if x509 == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to load certificate") + + x509 = self._ffi.gc(x509, self._lib.X509_free) + return _Certificate(self, x509) + + def load_der_x509_certificate(self, data): + mem_bio = self._bytes_to_bio(data) + x509 = self._lib.d2i_X509_bio(mem_bio.bio, self._ffi.NULL) + if x509 == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to load certificate") + + x509 = self._ffi.gc(x509, self._lib.X509_free) + return _Certificate(self, x509) + + def load_pem_x509_crl(self, data): + mem_bio = self._bytes_to_bio(data) + x509_crl = self._lib.PEM_read_bio_X509_CRL( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if x509_crl == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to load CRL") + + x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) + return _CertificateRevocationList(self, x509_crl) + + def load_der_x509_crl(self, data): + mem_bio = self._bytes_to_bio(data) + x509_crl = self._lib.d2i_X509_CRL_bio(mem_bio.bio, self._ffi.NULL) + if x509_crl == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to load CRL") + + x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) + return _CertificateRevocationList(self, x509_crl) + + def load_pem_x509_csr(self, data): + mem_bio = self._bytes_to_bio(data) + x509_req = self._lib.PEM_read_bio_X509_REQ( + mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL + ) + if x509_req == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to load request") + + x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) + return _CertificateSigningRequest(self, x509_req) + + def load_der_x509_csr(self, data): + mem_bio = self._bytes_to_bio(data) + x509_req = self._lib.d2i_X509_REQ_bio(mem_bio.bio, self._ffi.NULL) + if x509_req == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to load request") + + x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) + return _CertificateSigningRequest(self, x509_req) + + def _load_key(self, openssl_read_func, convert_func, data, password): + mem_bio = self._bytes_to_bio(data) + + if password is not None and not isinstance(password, bytes): + raise TypeError("Password must be bytes") + + userdata = self._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") + if password is not None: + password_buf = self._ffi.new("char []", password) + userdata.password = password_buf + userdata.length = len(password) + + evp_pkey = openssl_read_func( + mem_bio.bio, + self._ffi.NULL, + self._ffi.addressof( + self._lib._original_lib, "Cryptography_pem_password_cb" + ), + userdata, + ) + + if evp_pkey == self._ffi.NULL: + if userdata.error != 0: + errors = self._consume_errors() + self.openssl_assert(errors) + if userdata.error == -1: + raise TypeError( + "Password was not given but private key is encrypted" + ) + else: + assert userdata.error == -2 + raise ValueError( + "Passwords longer than {0} bytes are not supported " + "by this backend.".format(userdata.maxsize - 1) + ) + else: + self._handle_key_loading_error() + + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + + if password is not None and userdata.called == 0: + raise TypeError( + "Password was given but private key is not encrypted.") + + assert ( + (password is not None and userdata.called == 1) or + password is None + ) + + return convert_func(evp_pkey) + + def _handle_key_loading_error(self): + errors = self._consume_errors() + + if not errors: + raise ValueError("Could not deserialize key data.") + + elif ( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT + ) or errors[0]._lib_reason_match( + self._lib.ERR_LIB_PKCS12, + self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR + ) + ): + raise ValueError("Bad decrypt. Incorrect password?") + + elif ( + errors[0]._lib_reason_match( + self._lib.ERR_LIB_EVP, self._lib.EVP_R_UNKNOWN_PBE_ALGORITHM + ) or errors[0]._lib_reason_match( + self._lib.ERR_LIB_PEM, self._lib.PEM_R_UNSUPPORTED_ENCRYPTION + ) + ): + raise UnsupportedAlgorithm( + "PEM data is encrypted with an unsupported cipher", + _Reasons.UNSUPPORTED_CIPHER + ) + + elif any( + error._lib_reason_match( + self._lib.ERR_LIB_EVP, + self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM + ) + for error in errors + ): + raise ValueError("Unsupported public key algorithm.") + + else: + assert errors[0].lib in ( + self._lib.ERR_LIB_EVP, + self._lib.ERR_LIB_PEM, + self._lib.ERR_LIB_ASN1, + ) + raise ValueError("Could not deserialize key data.") + + def elliptic_curve_supported(self, curve): + try: + curve_nid = self._elliptic_curve_to_nid(curve) + except UnsupportedAlgorithm: + curve_nid = self._lib.NID_undef + + group = self._lib.EC_GROUP_new_by_curve_name(curve_nid) + + if group == self._ffi.NULL: + errors = self._consume_errors() + self.openssl_assert( + curve_nid == self._lib.NID_undef or + errors[0]._lib_reason_match( + self._lib.ERR_LIB_EC, + self._lib.EC_R_UNKNOWN_GROUP + ) + ) + return False + else: + self.openssl_assert(curve_nid != self._lib.NID_undef) + self._lib.EC_GROUP_free(group) + return True + + def elliptic_curve_signature_algorithm_supported( + self, signature_algorithm, curve + ): + # We only support ECDSA right now. + if not isinstance(signature_algorithm, ec.ECDSA): + return False + + return self.elliptic_curve_supported(curve) + + def generate_elliptic_curve_private_key(self, curve): + """ + Generate a new private key on the named curve. + """ + + if self.elliptic_curve_supported(curve): + curve_nid = self._elliptic_curve_to_nid(curve) + + ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + + res = self._lib.EC_KEY_generate_key(ec_cdata) + self.openssl_assert(res == 1) + + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + else: + raise UnsupportedAlgorithm( + "Backend object does not support {0}.".format(curve.name), + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE + ) + + def load_elliptic_curve_private_numbers(self, numbers): + public = numbers.public_numbers + + curve_nid = self._elliptic_curve_to_nid(public.curve) + + ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + + private_value = self._ffi.gc( + self._int_to_bn(numbers.private_value), self._lib.BN_clear_free + ) + res = self._lib.EC_KEY_set_private_key(ec_cdata, private_value) + self.openssl_assert(res == 1) + + ec_cdata = self._ec_key_set_public_key_affine_coordinates( + ec_cdata, public.x, public.y) + + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + + def load_elliptic_curve_public_numbers(self, numbers): + curve_nid = self._elliptic_curve_to_nid(numbers.curve) + + ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + + ec_cdata = self._ec_key_set_public_key_affine_coordinates( + ec_cdata, numbers.x, numbers.y) + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + + def derive_elliptic_curve_private_key(self, private_value, curve): + curve_nid = self._elliptic_curve_to_nid(curve) + + ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid) + self.openssl_assert(ec_cdata != self._ffi.NULL) + ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) + + get_func, group = self._ec_key_determine_group_get_func(ec_cdata) + + point = self._lib.EC_POINT_new(group) + self.openssl_assert(point != self._ffi.NULL) + point = self._ffi.gc(point, self._lib.EC_POINT_free) + + value = self._int_to_bn(private_value) + value = self._ffi.gc(value, self._lib.BN_clear_free) + + with self._tmp_bn_ctx() as bn_ctx: + res = self._lib.EC_POINT_mul(group, point, value, self._ffi.NULL, + self._ffi.NULL, bn_ctx) + self.openssl_assert(res == 1) + + bn_x = self._lib.BN_CTX_get(bn_ctx) + bn_y = self._lib.BN_CTX_get(bn_ctx) + + res = get_func(group, point, bn_x, bn_y, bn_ctx) + self.openssl_assert(res == 1) + + res = self._lib.EC_KEY_set_public_key(ec_cdata, point) + self.openssl_assert(res == 1) + private = self._int_to_bn(private_value) + private = self._ffi.gc(private, self._lib.BN_clear_free) + res = self._lib.EC_KEY_set_private_key(ec_cdata, private) + self.openssl_assert(res == 1) + + evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) + + return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) + + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + return ( + self.elliptic_curve_supported(curve) and + isinstance(algorithm, ec.ECDH) + ) + + def _ec_cdata_to_evp_pkey(self, ec_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_EC_KEY(evp_pkey, ec_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def _elliptic_curve_to_nid(self, curve): + """ + Get the NID for a curve name. + """ + + curve_aliases = { + "secp192r1": "prime192v1", + "secp256r1": "prime256v1" + } + + curve_name = curve_aliases.get(curve.name, curve.name) + + curve_nid = self._lib.OBJ_sn2nid(curve_name.encode()) + if curve_nid == self._lib.NID_undef: + raise UnsupportedAlgorithm( + "{0} is not a supported elliptic curve".format(curve.name), + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE + ) + return curve_nid + + @contextmanager + def _tmp_bn_ctx(self): + bn_ctx = self._lib.BN_CTX_new() + self.openssl_assert(bn_ctx != self._ffi.NULL) + bn_ctx = self._ffi.gc(bn_ctx, self._lib.BN_CTX_free) + self._lib.BN_CTX_start(bn_ctx) + try: + yield bn_ctx + finally: + self._lib.BN_CTX_end(bn_ctx) + + def _ec_key_determine_group_get_func(self, ctx): + """ + Given an EC_KEY determine the group and what function is required to + get point coordinates. + """ + self.openssl_assert(ctx != self._ffi.NULL) + + nid_two_field = self._lib.OBJ_sn2nid(b"characteristic-two-field") + self.openssl_assert(nid_two_field != self._lib.NID_undef) + + group = self._lib.EC_KEY_get0_group(ctx) + self.openssl_assert(group != self._ffi.NULL) + + method = self._lib.EC_GROUP_method_of(group) + self.openssl_assert(method != self._ffi.NULL) + + nid = self._lib.EC_METHOD_get_field_type(method) + self.openssl_assert(nid != self._lib.NID_undef) + + if nid == nid_two_field and self._lib.Cryptography_HAS_EC2M: + get_func = self._lib.EC_POINT_get_affine_coordinates_GF2m + else: + get_func = self._lib.EC_POINT_get_affine_coordinates_GFp + + assert get_func + + return get_func, group + + def _ec_key_set_public_key_affine_coordinates(self, ctx, x, y): + """ + Sets the public key point in the EC_KEY context to the affine x and y + values. + """ + + if x < 0 or y < 0: + raise ValueError( + "Invalid EC key. Both x and y must be non-negative." + ) + + x = self._ffi.gc(self._int_to_bn(x), self._lib.BN_free) + y = self._ffi.gc(self._int_to_bn(y), self._lib.BN_free) + res = self._lib.EC_KEY_set_public_key_affine_coordinates(ctx, x, y) + if res != 1: + self._consume_errors() + raise ValueError("Invalid EC key.") + + return ctx + + def _private_key_bytes(self, encoding, format, encryption_algorithm, + evp_pkey, cdata): + if not isinstance(format, serialization.PrivateFormat): + raise TypeError( + "format must be an item from the PrivateFormat enum" + ) + + if not isinstance(encryption_algorithm, + serialization.KeySerializationEncryption): + raise TypeError( + "Encryption algorithm must be a KeySerializationEncryption " + "instance" + ) + + if isinstance(encryption_algorithm, serialization.NoEncryption): + password = b"" + passlen = 0 + evp_cipher = self._ffi.NULL + elif isinstance(encryption_algorithm, + serialization.BestAvailableEncryption): + # This is a curated value that we will update over time. + evp_cipher = self._lib.EVP_get_cipherbyname( + b"aes-256-cbc" + ) + password = encryption_algorithm.password + passlen = len(password) + if passlen > 1023: + raise ValueError( + "Passwords longer than 1023 bytes are not supported by " + "this backend" + ) + else: + raise ValueError("Unsupported encryption type") + + key_type = self._lib.EVP_PKEY_id(evp_pkey) + if encoding is serialization.Encoding.PEM: + if format is serialization.PrivateFormat.PKCS8: + write_bio = self._lib.PEM_write_bio_PKCS8PrivateKey + key = evp_pkey + else: + assert format is serialization.PrivateFormat.TraditionalOpenSSL + if key_type == self._lib.EVP_PKEY_RSA: + write_bio = self._lib.PEM_write_bio_RSAPrivateKey + elif key_type == self._lib.EVP_PKEY_DSA: + write_bio = self._lib.PEM_write_bio_DSAPrivateKey + else: + assert key_type == self._lib.EVP_PKEY_EC + write_bio = self._lib.PEM_write_bio_ECPrivateKey + + key = cdata + elif encoding is serialization.Encoding.DER: + if format is serialization.PrivateFormat.TraditionalOpenSSL: + if not isinstance( + encryption_algorithm, serialization.NoEncryption + ): + raise ValueError( + "Encryption is not supported for DER encoded " + "traditional OpenSSL keys" + ) + + return self._private_key_bytes_traditional_der(key_type, cdata) + else: + assert format is serialization.PrivateFormat.PKCS8 + write_bio = self._lib.i2d_PKCS8PrivateKey_bio + key = evp_pkey + else: + raise TypeError("encoding must be an item from the Encoding enum") + + bio = self._create_mem_bio_gc() + res = write_bio( + bio, + key, + evp_cipher, + password, + passlen, + self._ffi.NULL, + self._ffi.NULL + ) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio) + + def _private_key_bytes_traditional_der(self, key_type, cdata): + if key_type == self._lib.EVP_PKEY_RSA: + write_bio = self._lib.i2d_RSAPrivateKey_bio + elif key_type == self._lib.EVP_PKEY_EC: + write_bio = self._lib.i2d_ECPrivateKey_bio + else: + self.openssl_assert(key_type == self._lib.EVP_PKEY_DSA) + write_bio = self._lib.i2d_DSAPrivateKey_bio + + bio = self._create_mem_bio_gc() + res = write_bio(bio, cdata) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio) + + def _public_key_bytes(self, encoding, format, key, evp_pkey, cdata): + if not isinstance(encoding, serialization.Encoding): + raise TypeError("encoding must be an item from the Encoding enum") + + if ( + format is serialization.PublicFormat.OpenSSH or + encoding is serialization.Encoding.OpenSSH + ): + if ( + format is not serialization.PublicFormat.OpenSSH or + encoding is not serialization.Encoding.OpenSSH + ): + raise ValueError( + "OpenSSH format must be used with OpenSSH encoding" + ) + return self._openssh_public_key_bytes(key) + elif format is serialization.PublicFormat.SubjectPublicKeyInfo: + if encoding is serialization.Encoding.PEM: + write_bio = self._lib.PEM_write_bio_PUBKEY + else: + assert encoding is serialization.Encoding.DER + write_bio = self._lib.i2d_PUBKEY_bio + + key = evp_pkey + elif format is serialization.PublicFormat.PKCS1: + # Only RSA is supported here. + assert self._lib.EVP_PKEY_id(evp_pkey) == self._lib.EVP_PKEY_RSA + if encoding is serialization.Encoding.PEM: + write_bio = self._lib.PEM_write_bio_RSAPublicKey + else: + assert encoding is serialization.Encoding.DER + write_bio = self._lib.i2d_RSAPublicKey_bio + + key = cdata + else: + raise TypeError( + "format must be an item from the PublicFormat enum" + ) + + bio = self._create_mem_bio_gc() + res = write_bio(bio, key) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio) + + def _openssh_public_key_bytes(self, key): + if isinstance(key, rsa.RSAPublicKey): + public_numbers = key.public_numbers() + return b"ssh-rsa " + base64.b64encode( + serialization._ssh_write_string(b"ssh-rsa") + + serialization._ssh_write_mpint(public_numbers.e) + + serialization._ssh_write_mpint(public_numbers.n) + ) + elif isinstance(key, dsa.DSAPublicKey): + public_numbers = key.public_numbers() + parameter_numbers = public_numbers.parameter_numbers + return b"ssh-dss " + base64.b64encode( + serialization._ssh_write_string(b"ssh-dss") + + serialization._ssh_write_mpint(parameter_numbers.p) + + serialization._ssh_write_mpint(parameter_numbers.q) + + serialization._ssh_write_mpint(parameter_numbers.g) + + serialization._ssh_write_mpint(public_numbers.y) + ) + else: + assert isinstance(key, ec.EllipticCurvePublicKey) + public_numbers = key.public_numbers() + try: + curve_name = { + ec.SECP256R1: b"nistp256", + ec.SECP384R1: b"nistp384", + ec.SECP521R1: b"nistp521", + }[type(public_numbers.curve)] + except KeyError: + raise ValueError( + "Only SECP256R1, SECP384R1, and SECP521R1 curves are " + "supported by the SSH public key format" + ) + return b"ecdsa-sha2-" + curve_name + b" " + base64.b64encode( + serialization._ssh_write_string(b"ecdsa-sha2-" + curve_name) + + serialization._ssh_write_string(curve_name) + + serialization._ssh_write_string(public_numbers.encode_point()) + ) + + def _parameter_bytes(self, encoding, format, cdata): + if encoding is serialization.Encoding.OpenSSH: + raise TypeError( + "OpenSSH encoding is not supported" + ) + + # Only DH is supported here currently. + q = self._ffi.new("BIGNUM **") + self._lib.DH_get0_pqg(cdata, + self._ffi.NULL, + q, + self._ffi.NULL) + if encoding is serialization.Encoding.PEM: + if q[0] != self._ffi.NULL: + write_bio = self._lib.PEM_write_bio_DHxparams + else: + write_bio = self._lib.PEM_write_bio_DHparams + elif encoding is serialization.Encoding.DER: + if q[0] != self._ffi.NULL: + write_bio = self._lib.Cryptography_i2d_DHxparams_bio + else: + write_bio = self._lib.i2d_DHparams_bio + else: + raise TypeError("encoding must be an item from the Encoding enum") + + bio = self._create_mem_bio_gc() + res = write_bio(bio, cdata) + self.openssl_assert(res == 1) + return self._read_mem_bio(bio) + + def generate_dh_parameters(self, generator, key_size): + if key_size < 512: + raise ValueError("DH key_size must be at least 512 bits") + + if generator not in (2, 5): + raise ValueError("DH generator must be 2 or 5") + + dh_param_cdata = self._lib.DH_new() + self.openssl_assert(dh_param_cdata != self._ffi.NULL) + dh_param_cdata = self._ffi.gc(dh_param_cdata, self._lib.DH_free) + + res = self._lib.DH_generate_parameters_ex( + dh_param_cdata, + key_size, + generator, + self._ffi.NULL + ) + self.openssl_assert(res == 1) + + return _DHParameters(self, dh_param_cdata) + + def _dh_cdata_to_evp_pkey(self, dh_cdata): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set1_DH(evp_pkey, dh_cdata) + self.openssl_assert(res == 1) + return evp_pkey + + def generate_dh_private_key(self, parameters): + dh_key_cdata = _dh_params_dup(parameters._dh_cdata, self) + + res = self._lib.DH_generate_key(dh_key_cdata) + self.openssl_assert(res == 1) + + evp_pkey = self._dh_cdata_to_evp_pkey(dh_key_cdata) + + return _DHPrivateKey(self, dh_key_cdata, evp_pkey) + + def generate_dh_private_key_and_parameters(self, generator, key_size): + return self.generate_dh_private_key( + self.generate_dh_parameters(generator, key_size)) + + def load_dh_private_numbers(self, numbers): + parameter_numbers = numbers.public_numbers.parameter_numbers + + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + p = self._int_to_bn(parameter_numbers.p) + g = self._int_to_bn(parameter_numbers.g) + + if parameter_numbers.q is not None: + q = self._int_to_bn(parameter_numbers.q) + else: + q = self._ffi.NULL + + pub_key = self._int_to_bn(numbers.public_numbers.y) + priv_key = self._int_to_bn(numbers.x) + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + res = self._lib.DH_set0_key(dh_cdata, pub_key, priv_key) + self.openssl_assert(res == 1) + + codes = self._ffi.new("int[]", 1) + res = self._lib.Cryptography_DH_check(dh_cdata, codes) + self.openssl_assert(res == 1) + + # DH_check will return DH_NOT_SUITABLE_GENERATOR if p % 24 does not + # equal 11 when the generator is 2 (a quadratic nonresidue). + # We want to ignore that error because p % 24 == 23 is also fine. + # Specifically, g is then a quadratic residue. Within the context of + # Diffie-Hellman this means it can only generate half the possible + # values. That sounds bad, but quadratic nonresidues leak a bit of + # the key to the attacker in exchange for having the full key space + # available. See: https://crypto.stackexchange.com/questions/12961 + if codes[0] != 0 and not ( + parameter_numbers.g == 2 and + codes[0] ^ self._lib.DH_NOT_SUITABLE_GENERATOR == 0 + ): + raise ValueError( + "DH private numbers did not pass safety checks." + ) + + evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata) + + return _DHPrivateKey(self, dh_cdata, evp_pkey) + + def load_dh_public_numbers(self, numbers): + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + parameter_numbers = numbers.parameter_numbers + + p = self._int_to_bn(parameter_numbers.p) + g = self._int_to_bn(parameter_numbers.g) + + if parameter_numbers.q is not None: + q = self._int_to_bn(parameter_numbers.q) + else: + q = self._ffi.NULL + + pub_key = self._int_to_bn(numbers.y) + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + res = self._lib.DH_set0_key(dh_cdata, pub_key, self._ffi.NULL) + self.openssl_assert(res == 1) + + evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata) + + return _DHPublicKey(self, dh_cdata, evp_pkey) + + def load_dh_parameter_numbers(self, numbers): + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + p = self._int_to_bn(numbers.p) + g = self._int_to_bn(numbers.g) + + if numbers.q is not None: + q = self._int_to_bn(numbers.q) + else: + q = self._ffi.NULL + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + return _DHParameters(self, dh_cdata) + + def dh_parameters_supported(self, p, g, q=None): + dh_cdata = self._lib.DH_new() + self.openssl_assert(dh_cdata != self._ffi.NULL) + dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) + + p = self._int_to_bn(p) + g = self._int_to_bn(g) + + if q is not None: + q = self._int_to_bn(q) + else: + q = self._ffi.NULL + + res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) + self.openssl_assert(res == 1) + + codes = self._ffi.new("int[]", 1) + res = self._lib.Cryptography_DH_check(dh_cdata, codes) + self.openssl_assert(res == 1) + + return codes[0] == 0 + + def dh_x942_serialization_supported(self): + return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 + + def x509_name_bytes(self, name): + x509_name = _encode_name_gc(self, name) + pp = self._ffi.new("unsigned char **") + res = self._lib.i2d_X509_NAME(x509_name, pp) + self.openssl_assert(pp[0] != self._ffi.NULL) + pp = self._ffi.gc( + pp, lambda pointer: self._lib.OPENSSL_free(pointer[0]) + ) + self.openssl_assert(res > 0) + return self._ffi.buffer(pp[0], res)[:] + + def x25519_load_public_bytes(self, data): + evp_pkey = self._create_evp_pkey_gc() + res = self._lib.EVP_PKEY_set_type(evp_pkey, self._lib.NID_X25519) + backend.openssl_assert(res == 1) + res = self._lib.EVP_PKEY_set1_tls_encodedpoint( + evp_pkey, data, len(data) + ) + backend.openssl_assert(res == 1) + return _X25519PublicKey(self, evp_pkey) + + def x25519_load_private_bytes(self, data): + # OpenSSL only has facilities for loading PKCS8 formatted private + # keys using the algorithm identifiers specified in + # https://tools.ietf.org/html/draft-ietf-curdle-pkix-09. + # This is the standard PKCS8 prefix for a 32 byte X25519 key. + # The form is: + # 0:d=0 hl=2 l= 46 cons: SEQUENCE + # 2:d=1 hl=2 l= 1 prim: INTEGER :00 + # 5:d=1 hl=2 l= 5 cons: SEQUENCE + # 7:d=2 hl=2 l= 3 prim: OBJECT :1.3.101.110 + # 12:d=1 hl=2 l= 34 prim: OCTET STRING (the key) + # Of course there's a bit more complexity. In reality OCTET STRING + # contains an OCTET STRING of length 32! So the last two bytes here + # are \x04\x20, which is an OCTET STRING of length 32. + pkcs8_prefix = b'0.\x02\x01\x000\x05\x06\x03+en\x04"\x04 ' + bio = self._bytes_to_bio(pkcs8_prefix + data) + evp_pkey = backend._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL) + self.openssl_assert(evp_pkey != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) + self.openssl_assert( + self._lib.EVP_PKEY_id(evp_pkey) == self._lib.EVP_PKEY_X25519 + ) + return _X25519PrivateKey(self, evp_pkey) + + def x25519_generate_key(self): + evp_pkey_ctx = self._lib.EVP_PKEY_CTX_new_id( + self._lib.NID_X25519, self._ffi.NULL + ) + self.openssl_assert(evp_pkey_ctx != self._ffi.NULL) + evp_pkey_ctx = self._ffi.gc( + evp_pkey_ctx, self._lib.EVP_PKEY_CTX_free + ) + res = self._lib.EVP_PKEY_keygen_init(evp_pkey_ctx) + self.openssl_assert(res == 1) + evp_ppkey = self._ffi.new("EVP_PKEY **") + res = self._lib.EVP_PKEY_keygen(evp_pkey_ctx, evp_ppkey) + self.openssl_assert(res == 1) + self.openssl_assert(evp_ppkey[0] != self._ffi.NULL) + evp_pkey = self._ffi.gc(evp_ppkey[0], self._lib.EVP_PKEY_free) + return _X25519PrivateKey(self, evp_pkey) + + def x25519_supported(self): + return self._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER + + def derive_scrypt(self, key_material, salt, length, n, r, p): + buf = self._ffi.new("unsigned char[]", length) + res = self._lib.EVP_PBE_scrypt( + key_material, len(key_material), salt, len(salt), n, r, p, + scrypt._MEM_LIMIT, buf, length + ) + self.openssl_assert(res == 1) + return self._ffi.buffer(buf)[:] + + def aead_cipher_supported(self, cipher): + cipher_name = aead._aead_cipher_name(cipher) + return ( + self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL + ) + + +class GetCipherByName(object): + def __init__(self, fmt): + self._fmt = fmt + + def __call__(self, backend, cipher, mode): + cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower() + return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) + + +def _get_xts_cipher(backend, cipher, mode): + cipher_name = "aes-{0}-xts".format(cipher.key_size // 2) + return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) + + +backend = Backend() diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ciphers.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ciphers.py new file mode 100644 index 0000000..e0ee06e --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ciphers.py @@ -0,0 +1,222 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import ciphers +from cryptography.hazmat.primitives.ciphers import modes + + +@utils.register_interface(ciphers.CipherContext) +@utils.register_interface(ciphers.AEADCipherContext) +@utils.register_interface(ciphers.AEADEncryptionContext) +@utils.register_interface(ciphers.AEADDecryptionContext) +class _CipherContext(object): + _ENCRYPT = 1 + _DECRYPT = 0 + + def __init__(self, backend, cipher, mode, operation): + self._backend = backend + self._cipher = cipher + self._mode = mode + self._operation = operation + self._tag = None + + if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): + self._block_size_bytes = self._cipher.block_size // 8 + else: + self._block_size_bytes = 1 + + ctx = self._backend._lib.EVP_CIPHER_CTX_new() + ctx = self._backend._ffi.gc( + ctx, self._backend._lib.EVP_CIPHER_CTX_free + ) + + registry = self._backend._cipher_registry + try: + adapter = registry[type(cipher), type(mode)] + except KeyError: + raise UnsupportedAlgorithm( + "cipher {0} in {1} mode is not supported " + "by this backend.".format( + cipher.name, mode.name if mode else mode), + _Reasons.UNSUPPORTED_CIPHER + ) + + evp_cipher = adapter(self._backend, cipher, mode) + if evp_cipher == self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "cipher {0} in {1} mode is not supported " + "by this backend.".format( + cipher.name, mode.name if mode else mode), + _Reasons.UNSUPPORTED_CIPHER + ) + + if isinstance(mode, modes.ModeWithInitializationVector): + iv_nonce = mode.initialization_vector + elif isinstance(mode, modes.ModeWithTweak): + iv_nonce = mode.tweak + elif isinstance(mode, modes.ModeWithNonce): + iv_nonce = mode.nonce + elif isinstance(cipher, modes.ModeWithNonce): + iv_nonce = cipher.nonce + else: + iv_nonce = self._backend._ffi.NULL + # begin init with cipher and operation type + res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + operation) + self._backend.openssl_assert(res != 0) + # set the key length to handle variable key ciphers + res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( + ctx, len(cipher.key) + ) + self._backend.openssl_assert(res != 0) + if isinstance(mode, modes.GCM): + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, + len(iv_nonce), self._backend._ffi.NULL + ) + self._backend.openssl_assert(res != 0) + if mode.tag is not None: + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, + len(mode.tag), mode.tag + ) + self._backend.openssl_assert(res != 0) + self._tag = mode.tag + elif ( + self._operation == self._DECRYPT and + self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and + not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL + ): + raise NotImplementedError( + "delayed passing of GCM tag requires OpenSSL >= 1.0.2." + " To use this feature please update OpenSSL" + ) + + # pass key/iv + res = self._backend._lib.EVP_CipherInit_ex( + ctx, + self._backend._ffi.NULL, + self._backend._ffi.NULL, + cipher.key, + iv_nonce, + operation + ) + self._backend.openssl_assert(res != 0) + # We purposely disable padding here as it's handled higher up in the + # API. + self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) + self._ctx = ctx + + def update(self, data): + buf = bytearray(len(data) + self._block_size_bytes - 1) + n = self.update_into(data, buf) + return bytes(buf[:n]) + + def update_into(self, data, buf): + if len(buf) < (len(data) + self._block_size_bytes - 1): + raise ValueError( + "buffer must be at least {0} bytes for this " + "payload".format(len(data) + self._block_size_bytes - 1) + ) + + buf = self._backend._ffi.cast( + "unsigned char *", self._backend._ffi.from_buffer(buf) + ) + outlen = self._backend._ffi.new("int *") + res = self._backend._lib.EVP_CipherUpdate(self._ctx, buf, outlen, + data, len(data)) + self._backend.openssl_assert(res != 0) + return outlen[0] + + def finalize(self): + # OpenSSL 1.0.1 on Ubuntu 12.04 (and possibly other distributions) + # appears to have a bug where you must make at least one call to update + # even if you are only using authenticate_additional_data or the + # GCM tag will be wrong. An (empty) call to update resolves this + # and is harmless for all other versions of OpenSSL. + if isinstance(self._mode, modes.GCM): + self.update(b"") + + if ( + self._operation == self._DECRYPT and + isinstance(self._mode, modes.ModeWithAuthenticationTag) and + self.tag is None + ): + raise ValueError( + "Authentication tag must be provided when decrypting." + ) + + buf = self._backend._ffi.new("unsigned char[]", self._block_size_bytes) + outlen = self._backend._ffi.new("int *") + res = self._backend._lib.EVP_CipherFinal_ex(self._ctx, buf, outlen) + if res == 0: + errors = self._backend._consume_errors() + + if not errors and isinstance(self._mode, modes.GCM): + raise InvalidTag + + self._backend.openssl_assert( + errors[0]._lib_reason_match( + self._backend._lib.ERR_LIB_EVP, + self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH + ) + ) + raise ValueError( + "The length of the provided data is not a multiple of " + "the block length." + ) + + if (isinstance(self._mode, modes.GCM) and + self._operation == self._ENCRYPT): + tag_buf = self._backend._ffi.new( + "unsigned char[]", self._block_size_bytes + ) + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + self._ctx, self._backend._lib.EVP_CTRL_AEAD_GET_TAG, + self._block_size_bytes, tag_buf + ) + self._backend.openssl_assert(res != 0) + self._tag = self._backend._ffi.buffer(tag_buf)[:] + + res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx) + self._backend.openssl_assert(res == 1) + return self._backend._ffi.buffer(buf)[:outlen[0]] + + def finalize_with_tag(self, tag): + if ( + self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and + not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL + ): + raise NotImplementedError( + "finalize_with_tag requires OpenSSL >= 1.0.2. To use this " + "method please update OpenSSL" + ) + if len(tag) < self._mode._min_tag_length: + raise ValueError( + "Authentication tag must be {0} bytes or longer.".format( + self._mode._min_tag_length) + ) + res = self._backend._lib.EVP_CIPHER_CTX_ctrl( + self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, + len(tag), tag + ) + self._backend.openssl_assert(res != 0) + self._tag = tag + return self.finalize() + + def authenticate_additional_data(self, data): + outlen = self._backend._ffi.new("int *") + res = self._backend._lib.EVP_CipherUpdate( + self._ctx, self._backend._ffi.NULL, outlen, data, len(data) + ) + self._backend.openssl_assert(res != 0) + + tag = utils.read_only_property("_tag") diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/cmac.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/cmac.py new file mode 100644 index 0000000..e20f66d --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/cmac.py @@ -0,0 +1,81 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + + +from cryptography import utils +from cryptography.exceptions import ( + InvalidSignature, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.primitives import constant_time, mac +from cryptography.hazmat.primitives.ciphers.modes import CBC + + +@utils.register_interface(mac.MACContext) +class _CMACContext(object): + def __init__(self, backend, algorithm, ctx=None): + if not backend.cmac_algorithm_supported(algorithm): + raise UnsupportedAlgorithm("This backend does not support CMAC.", + _Reasons.UNSUPPORTED_CIPHER) + + self._backend = backend + self._key = algorithm.key + self._algorithm = algorithm + self._output_length = algorithm.block_size // 8 + + if ctx is None: + registry = self._backend._cipher_registry + adapter = registry[type(algorithm), CBC] + + evp_cipher = adapter(self._backend, algorithm, CBC) + + ctx = self._backend._lib.CMAC_CTX_new() + + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free) + + res = self._backend._lib.CMAC_Init( + ctx, self._key, len(self._key), + evp_cipher, self._backend._ffi.NULL + ) + self._backend.openssl_assert(res == 1) + + self._ctx = ctx + + algorithm = utils.read_only_property("_algorithm") + + def update(self, data): + res = self._backend._lib.CMAC_Update(self._ctx, data, len(data)) + self._backend.openssl_assert(res == 1) + + def finalize(self): + buf = self._backend._ffi.new("unsigned char[]", self._output_length) + length = self._backend._ffi.new("size_t *", self._output_length) + res = self._backend._lib.CMAC_Final( + self._ctx, buf, length + ) + self._backend.openssl_assert(res == 1) + + self._ctx = None + + return self._backend._ffi.buffer(buf)[:] + + def copy(self): + copied_ctx = self._backend._lib.CMAC_CTX_new() + copied_ctx = self._backend._ffi.gc( + copied_ctx, self._backend._lib.CMAC_CTX_free + ) + res = self._backend._lib.CMAC_CTX_copy( + copied_ctx, self._ctx + ) + self._backend.openssl_assert(res == 1) + return _CMACContext( + self._backend, self._algorithm, ctx=copied_ctx + ) + + def verify(self, signature): + digest = self.finalize() + if not constant_time.bytes_eq(digest, signature): + raise InvalidSignature("Signature did not match digest.") diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/decode_asn1.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/decode_asn1.py new file mode 100644 index 0000000..31fb8cf --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -0,0 +1,826 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import datetime +import ipaddress + +from asn1crypto.core import Integer, SequenceOf + +from cryptography import x509 +from cryptography.x509.extensions import _TLS_FEATURE_TYPE_TO_ENUM +from cryptography.x509.name import _ASN1_TYPE_TO_ENUM +from cryptography.x509.oid import ( + CRLEntryExtensionOID, CertificatePoliciesOID, ExtensionOID +) + + +class _Integers(SequenceOf): + _child_spec = Integer + + +def _obj2txt(backend, obj): + # Set to 80 on the recommendation of + # https://www.openssl.org/docs/crypto/OBJ_nid2ln.html#return_values + # + # But OIDs longer than this occur in real life (e.g. Active + # Directory makes some very long OIDs). So we need to detect + # and properly handle the case where the default buffer is not + # big enough. + # + buf_len = 80 + buf = backend._ffi.new("char[]", buf_len) + + # 'res' is the number of bytes that *would* be written if the + # buffer is large enough. If 'res' > buf_len - 1, we need to + # alloc a big-enough buffer and go again. + res = backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) + if res > buf_len - 1: # account for terminating null byte + buf_len = res + 1 + buf = backend._ffi.new("char[]", buf_len) + res = backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) + backend.openssl_assert(res > 0) + return backend._ffi.buffer(buf, res)[:].decode() + + +def _decode_x509_name_entry(backend, x509_name_entry): + obj = backend._lib.X509_NAME_ENTRY_get_object(x509_name_entry) + backend.openssl_assert(obj != backend._ffi.NULL) + data = backend._lib.X509_NAME_ENTRY_get_data(x509_name_entry) + backend.openssl_assert(data != backend._ffi.NULL) + value = _asn1_string_to_utf8(backend, data) + oid = _obj2txt(backend, obj) + type = _ASN1_TYPE_TO_ENUM[data.type] + + return x509.NameAttribute(x509.ObjectIdentifier(oid), value, type) + + +def _decode_x509_name(backend, x509_name): + count = backend._lib.X509_NAME_entry_count(x509_name) + attributes = [] + prev_set_id = -1 + for x in range(count): + entry = backend._lib.X509_NAME_get_entry(x509_name, x) + attribute = _decode_x509_name_entry(backend, entry) + set_id = backend._lib.Cryptography_X509_NAME_ENTRY_set(entry) + if set_id != prev_set_id: + attributes.append(set([attribute])) + else: + # is in the same RDN a previous entry + attributes[-1].add(attribute) + prev_set_id = set_id + + return x509.Name(x509.RelativeDistinguishedName(rdn) for rdn in attributes) + + +def _decode_general_names(backend, gns): + num = backend._lib.sk_GENERAL_NAME_num(gns) + names = [] + for i in range(num): + gn = backend._lib.sk_GENERAL_NAME_value(gns, i) + backend.openssl_assert(gn != backend._ffi.NULL) + names.append(_decode_general_name(backend, gn)) + + return names + + +def _decode_general_name(backend, gn): + if gn.type == backend._lib.GEN_DNS: + # Convert to bytes and then decode to utf8. We don't use + # asn1_string_to_utf8 here because it doesn't properly convert + # utf8 from ia5strings. + data = _asn1_string_to_bytes(backend, gn.d.dNSName).decode("utf8") + # We don't use the constructor for DNSName so we can bypass validation + # This allows us to create DNSName objects that have unicode chars + # when a certificate (against the RFC) contains them. + return x509.DNSName._init_without_validation(data) + elif gn.type == backend._lib.GEN_URI: + # Convert to bytes and then decode to utf8. We don't use + # asn1_string_to_utf8 here because it doesn't properly convert + # utf8 from ia5strings. + data = _asn1_string_to_bytes( + backend, gn.d.uniformResourceIdentifier + ).decode("utf8") + # We don't use the constructor for URI so we can bypass validation + # This allows us to create URI objects that have unicode chars + # when a certificate (against the RFC) contains them. + return x509.UniformResourceIdentifier._init_without_validation(data) + elif gn.type == backend._lib.GEN_RID: + oid = _obj2txt(backend, gn.d.registeredID) + return x509.RegisteredID(x509.ObjectIdentifier(oid)) + elif gn.type == backend._lib.GEN_IPADD: + data = _asn1_string_to_bytes(backend, gn.d.iPAddress) + data_len = len(data) + if data_len == 8 or data_len == 32: + # This is an IPv4 or IPv6 Network and not a single IP. This + # type of data appears in Name Constraints. Unfortunately, + # ipaddress doesn't support packed bytes + netmask. Additionally, + # IPv6Network can only handle CIDR rather than the full 16 byte + # netmask. To handle this we convert the netmask to integer, then + # find the first 0 bit, which will be the prefix. If another 1 + # bit is present after that the netmask is invalid. + base = ipaddress.ip_address(data[:data_len // 2]) + netmask = ipaddress.ip_address(data[data_len // 2:]) + bits = bin(int(netmask))[2:] + prefix = bits.find('0') + # If no 0 bits are found it is a /32 or /128 + if prefix == -1: + prefix = len(bits) + + if "1" in bits[prefix:]: + raise ValueError("Invalid netmask") + + ip = ipaddress.ip_network(base.exploded + u"/{0}".format(prefix)) + else: + ip = ipaddress.ip_address(data) + + return x509.IPAddress(ip) + elif gn.type == backend._lib.GEN_DIRNAME: + return x509.DirectoryName( + _decode_x509_name(backend, gn.d.directoryName) + ) + elif gn.type == backend._lib.GEN_EMAIL: + # Convert to bytes and then decode to utf8. We don't use + # asn1_string_to_utf8 here because it doesn't properly convert + # utf8 from ia5strings. + data = _asn1_string_to_bytes(backend, gn.d.rfc822Name).decode("utf8") + # We don't use the constructor for RFC822Name so we can bypass + # validation. This allows us to create RFC822Name objects that have + # unicode chars when a certificate (against the RFC) contains them. + return x509.RFC822Name._init_without_validation(data) + elif gn.type == backend._lib.GEN_OTHERNAME: + type_id = _obj2txt(backend, gn.d.otherName.type_id) + value = _asn1_to_der(backend, gn.d.otherName.value) + return x509.OtherName(x509.ObjectIdentifier(type_id), value) + else: + # x400Address or ediPartyName + raise x509.UnsupportedGeneralNameType( + "{0} is not a supported type".format( + x509._GENERAL_NAMES.get(gn.type, gn.type) + ), + gn.type + ) + + +def _decode_ocsp_no_check(backend, ext): + return x509.OCSPNoCheck() + + +def _decode_crl_number(backend, ext): + asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) + asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) + return x509.CRLNumber(_asn1_integer_to_int(backend, asn1_int)) + + +def _decode_delta_crl_indicator(backend, ext): + asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) + asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) + return x509.DeltaCRLIndicator(_asn1_integer_to_int(backend, asn1_int)) + + +class _X509ExtensionParser(object): + def __init__(self, ext_count, get_ext, handlers): + self.ext_count = ext_count + self.get_ext = get_ext + self.handlers = handlers + + def parse(self, backend, x509_obj): + extensions = [] + seen_oids = set() + for i in range(self.ext_count(backend, x509_obj)): + ext = self.get_ext(backend, x509_obj, i) + backend.openssl_assert(ext != backend._ffi.NULL) + crit = backend._lib.X509_EXTENSION_get_critical(ext) + critical = crit == 1 + oid = x509.ObjectIdentifier( + _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext)) + ) + if oid in seen_oids: + raise x509.DuplicateExtension( + "Duplicate {0} extension found".format(oid), oid + ) + + # This OID is only supported in OpenSSL 1.1.0+ but we want + # to support it in all versions of OpenSSL so we decode it + # ourselves. + if oid == ExtensionOID.TLS_FEATURE: + data = backend._lib.X509_EXTENSION_get_data(ext) + parsed = _Integers.load(_asn1_string_to_bytes(backend, data)) + value = x509.TLSFeature( + [_TLS_FEATURE_TYPE_TO_ENUM[x.native] for x in parsed] + ) + extensions.append(x509.Extension(oid, critical, value)) + seen_oids.add(oid) + continue + + try: + handler = self.handlers[oid] + except KeyError: + # Dump the DER payload into an UnrecognizedExtension object + data = backend._lib.X509_EXTENSION_get_data(ext) + backend.openssl_assert(data != backend._ffi.NULL) + der = backend._ffi.buffer(data.data, data.length)[:] + unrecognized = x509.UnrecognizedExtension(oid, der) + extensions.append( + x509.Extension(oid, critical, unrecognized) + ) + else: + ext_data = backend._lib.X509V3_EXT_d2i(ext) + if ext_data == backend._ffi.NULL: + backend._consume_errors() + raise ValueError( + "The {0} extension is invalid and can't be " + "parsed".format(oid) + ) + + value = handler(backend, ext_data) + extensions.append(x509.Extension(oid, critical, value)) + + seen_oids.add(oid) + + return x509.Extensions(extensions) + + +def _decode_certificate_policies(backend, cp): + cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *", cp) + cp = backend._ffi.gc(cp, backend._lib.CERTIFICATEPOLICIES_free) + + num = backend._lib.sk_POLICYINFO_num(cp) + certificate_policies = [] + for i in range(num): + qualifiers = None + pi = backend._lib.sk_POLICYINFO_value(cp, i) + oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid)) + if pi.qualifiers != backend._ffi.NULL: + qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers) + qualifiers = [] + for j in range(qnum): + pqi = backend._lib.sk_POLICYQUALINFO_value( + pi.qualifiers, j + ) + pqualid = x509.ObjectIdentifier( + _obj2txt(backend, pqi.pqualid) + ) + if pqualid == CertificatePoliciesOID.CPS_QUALIFIER: + cpsuri = backend._ffi.buffer( + pqi.d.cpsuri.data, pqi.d.cpsuri.length + )[:].decode('ascii') + qualifiers.append(cpsuri) + else: + assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE + user_notice = _decode_user_notice( + backend, pqi.d.usernotice + ) + qualifiers.append(user_notice) + + certificate_policies.append( + x509.PolicyInformation(oid, qualifiers) + ) + + return x509.CertificatePolicies(certificate_policies) + + +def _decode_user_notice(backend, un): + explicit_text = None + notice_reference = None + + if un.exptext != backend._ffi.NULL: + explicit_text = _asn1_string_to_utf8(backend, un.exptext) + + if un.noticeref != backend._ffi.NULL: + organization = _asn1_string_to_utf8( + backend, un.noticeref.organization + ) + + num = backend._lib.sk_ASN1_INTEGER_num( + un.noticeref.noticenos + ) + notice_numbers = [] + for i in range(num): + asn1_int = backend._lib.sk_ASN1_INTEGER_value( + un.noticeref.noticenos, i + ) + notice_num = _asn1_integer_to_int(backend, asn1_int) + notice_numbers.append(notice_num) + + notice_reference = x509.NoticeReference( + organization, notice_numbers + ) + + return x509.UserNotice(notice_reference, explicit_text) + + +def _decode_basic_constraints(backend, bc_st): + basic_constraints = backend._ffi.cast("BASIC_CONSTRAINTS *", bc_st) + basic_constraints = backend._ffi.gc( + basic_constraints, backend._lib.BASIC_CONSTRAINTS_free + ) + # The byte representation of an ASN.1 boolean true is \xff. OpenSSL + # chooses to just map this to its ordinal value, so true is 255 and + # false is 0. + ca = basic_constraints.ca == 255 + path_length = _asn1_integer_to_int_or_none( + backend, basic_constraints.pathlen + ) + + return x509.BasicConstraints(ca, path_length) + + +def _decode_subject_key_identifier(backend, asn1_string): + asn1_string = backend._ffi.cast("ASN1_OCTET_STRING *", asn1_string) + asn1_string = backend._ffi.gc( + asn1_string, backend._lib.ASN1_OCTET_STRING_free + ) + return x509.SubjectKeyIdentifier( + backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] + ) + + +def _decode_authority_key_identifier(backend, akid): + akid = backend._ffi.cast("AUTHORITY_KEYID *", akid) + akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free) + key_identifier = None + authority_cert_issuer = None + + if akid.keyid != backend._ffi.NULL: + key_identifier = backend._ffi.buffer( + akid.keyid.data, akid.keyid.length + )[:] + + if akid.issuer != backend._ffi.NULL: + authority_cert_issuer = _decode_general_names( + backend, akid.issuer + ) + + authority_cert_serial_number = _asn1_integer_to_int_or_none( + backend, akid.serial + ) + + return x509.AuthorityKeyIdentifier( + key_identifier, authority_cert_issuer, authority_cert_serial_number + ) + + +def _decode_authority_information_access(backend, aia): + aia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia) + aia = backend._ffi.gc(aia, backend._lib.sk_ACCESS_DESCRIPTION_free) + num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia) + access_descriptions = [] + for i in range(num): + ad = backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i) + backend.openssl_assert(ad.method != backend._ffi.NULL) + oid = x509.ObjectIdentifier(_obj2txt(backend, ad.method)) + backend.openssl_assert(ad.location != backend._ffi.NULL) + gn = _decode_general_name(backend, ad.location) + access_descriptions.append(x509.AccessDescription(oid, gn)) + + return x509.AuthorityInformationAccess(access_descriptions) + + +def _decode_key_usage(backend, bit_string): + bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string) + bit_string = backend._ffi.gc(bit_string, backend._lib.ASN1_BIT_STRING_free) + get_bit = backend._lib.ASN1_BIT_STRING_get_bit + digital_signature = get_bit(bit_string, 0) == 1 + content_commitment = get_bit(bit_string, 1) == 1 + key_encipherment = get_bit(bit_string, 2) == 1 + data_encipherment = get_bit(bit_string, 3) == 1 + key_agreement = get_bit(bit_string, 4) == 1 + key_cert_sign = get_bit(bit_string, 5) == 1 + crl_sign = get_bit(bit_string, 6) == 1 + encipher_only = get_bit(bit_string, 7) == 1 + decipher_only = get_bit(bit_string, 8) == 1 + return x509.KeyUsage( + digital_signature, + content_commitment, + key_encipherment, + data_encipherment, + key_agreement, + key_cert_sign, + crl_sign, + encipher_only, + decipher_only + ) + + +def _decode_general_names_extension(backend, gns): + gns = backend._ffi.cast("GENERAL_NAMES *", gns) + gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) + general_names = _decode_general_names(backend, gns) + return general_names + + +def _decode_subject_alt_name(backend, ext): + return x509.SubjectAlternativeName( + _decode_general_names_extension(backend, ext) + ) + + +def _decode_issuer_alt_name(backend, ext): + return x509.IssuerAlternativeName( + _decode_general_names_extension(backend, ext) + ) + + +def _decode_name_constraints(backend, nc): + nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc) + nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) + permitted = _decode_general_subtrees(backend, nc.permittedSubtrees) + excluded = _decode_general_subtrees(backend, nc.excludedSubtrees) + return x509.NameConstraints( + permitted_subtrees=permitted, excluded_subtrees=excluded + ) + + +def _decode_general_subtrees(backend, stack_subtrees): + if stack_subtrees == backend._ffi.NULL: + return None + + num = backend._lib.sk_GENERAL_SUBTREE_num(stack_subtrees) + subtrees = [] + + for i in range(num): + obj = backend._lib.sk_GENERAL_SUBTREE_value(stack_subtrees, i) + backend.openssl_assert(obj != backend._ffi.NULL) + name = _decode_general_name(backend, obj.base) + subtrees.append(name) + + return subtrees + + +def _decode_policy_constraints(backend, pc): + pc = backend._ffi.cast("POLICY_CONSTRAINTS *", pc) + pc = backend._ffi.gc(pc, backend._lib.POLICY_CONSTRAINTS_free) + + require_explicit_policy = _asn1_integer_to_int_or_none( + backend, pc.requireExplicitPolicy + ) + inhibit_policy_mapping = _asn1_integer_to_int_or_none( + backend, pc.inhibitPolicyMapping + ) + + return x509.PolicyConstraints( + require_explicit_policy, inhibit_policy_mapping + ) + + +def _decode_extended_key_usage(backend, sk): + sk = backend._ffi.cast("Cryptography_STACK_OF_ASN1_OBJECT *", sk) + sk = backend._ffi.gc(sk, backend._lib.sk_ASN1_OBJECT_free) + num = backend._lib.sk_ASN1_OBJECT_num(sk) + ekus = [] + + for i in range(num): + obj = backend._lib.sk_ASN1_OBJECT_value(sk, i) + backend.openssl_assert(obj != backend._ffi.NULL) + oid = x509.ObjectIdentifier(_obj2txt(backend, obj)) + ekus.append(oid) + + return x509.ExtendedKeyUsage(ekus) + + +_DISTPOINT_TYPE_FULLNAME = 0 +_DISTPOINT_TYPE_RELATIVENAME = 1 + + +def _decode_dist_points(backend, cdps): + cdps = backend._ffi.cast("Cryptography_STACK_OF_DIST_POINT *", cdps) + cdps = backend._ffi.gc(cdps, backend._lib.CRL_DIST_POINTS_free) + + num = backend._lib.sk_DIST_POINT_num(cdps) + dist_points = [] + for i in range(num): + full_name = None + relative_name = None + crl_issuer = None + reasons = None + cdp = backend._lib.sk_DIST_POINT_value(cdps, i) + if cdp.reasons != backend._ffi.NULL: + # We will check each bit from RFC 5280 + # ReasonFlags ::= BIT STRING { + # unused (0), + # keyCompromise (1), + # cACompromise (2), + # affiliationChanged (3), + # superseded (4), + # cessationOfOperation (5), + # certificateHold (6), + # privilegeWithdrawn (7), + # aACompromise (8) } + reasons = [] + get_bit = backend._lib.ASN1_BIT_STRING_get_bit + if get_bit(cdp.reasons, 1): + reasons.append(x509.ReasonFlags.key_compromise) + + if get_bit(cdp.reasons, 2): + reasons.append(x509.ReasonFlags.ca_compromise) + + if get_bit(cdp.reasons, 3): + reasons.append(x509.ReasonFlags.affiliation_changed) + + if get_bit(cdp.reasons, 4): + reasons.append(x509.ReasonFlags.superseded) + + if get_bit(cdp.reasons, 5): + reasons.append(x509.ReasonFlags.cessation_of_operation) + + if get_bit(cdp.reasons, 6): + reasons.append(x509.ReasonFlags.certificate_hold) + + if get_bit(cdp.reasons, 7): + reasons.append(x509.ReasonFlags.privilege_withdrawn) + + if get_bit(cdp.reasons, 8): + reasons.append(x509.ReasonFlags.aa_compromise) + + reasons = frozenset(reasons) + + if cdp.CRLissuer != backend._ffi.NULL: + crl_issuer = _decode_general_names(backend, cdp.CRLissuer) + + # Certificates may have a crl_issuer/reasons and no distribution + # point so make sure it's not null. + if cdp.distpoint != backend._ffi.NULL: + # Type 0 is fullName, there is no #define for it in the code. + if cdp.distpoint.type == _DISTPOINT_TYPE_FULLNAME: + full_name = _decode_general_names( + backend, cdp.distpoint.name.fullname + ) + # OpenSSL code doesn't test for a specific type for + # relativename, everything that isn't fullname is considered + # relativename. Per RFC 5280: + # + # DistributionPointName ::= CHOICE { + # fullName [0] GeneralNames, + # nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + else: + rns = cdp.distpoint.name.relativename + rnum = backend._lib.sk_X509_NAME_ENTRY_num(rns) + attributes = set() + for i in range(rnum): + rn = backend._lib.sk_X509_NAME_ENTRY_value( + rns, i + ) + backend.openssl_assert(rn != backend._ffi.NULL) + attributes.add( + _decode_x509_name_entry(backend, rn) + ) + + relative_name = x509.RelativeDistinguishedName(attributes) + + dist_points.append( + x509.DistributionPoint( + full_name, relative_name, reasons, crl_issuer + ) + ) + + return dist_points + + +def _decode_crl_distribution_points(backend, cdps): + dist_points = _decode_dist_points(backend, cdps) + return x509.CRLDistributionPoints(dist_points) + + +def _decode_freshest_crl(backend, cdps): + dist_points = _decode_dist_points(backend, cdps) + return x509.FreshestCRL(dist_points) + + +def _decode_inhibit_any_policy(backend, asn1_int): + asn1_int = backend._ffi.cast("ASN1_INTEGER *", asn1_int) + asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) + skip_certs = _asn1_integer_to_int(backend, asn1_int) + return x509.InhibitAnyPolicy(skip_certs) + + +def _decode_precert_signed_certificate_timestamps(backend, asn1_scts): + from cryptography.hazmat.backends.openssl.x509 import ( + _SignedCertificateTimestamp + ) + asn1_scts = backend._ffi.cast("Cryptography_STACK_OF_SCT *", asn1_scts) + asn1_scts = backend._ffi.gc(asn1_scts, backend._lib.SCT_LIST_free) + + scts = [] + for i in range(backend._lib.sk_SCT_num(asn1_scts)): + sct = backend._lib.sk_SCT_value(asn1_scts, i) + + scts.append(_SignedCertificateTimestamp(backend, asn1_scts, sct)) + return x509.PrecertificateSignedCertificateTimestamps(scts) + + +# CRLReason ::= ENUMERATED { +# unspecified (0), +# keyCompromise (1), +# cACompromise (2), +# affiliationChanged (3), +# superseded (4), +# cessationOfOperation (5), +# certificateHold (6), +# -- value 7 is not used +# removeFromCRL (8), +# privilegeWithdrawn (9), +# aACompromise (10) } +_CRL_ENTRY_REASON_CODE_TO_ENUM = { + 0: x509.ReasonFlags.unspecified, + 1: x509.ReasonFlags.key_compromise, + 2: x509.ReasonFlags.ca_compromise, + 3: x509.ReasonFlags.affiliation_changed, + 4: x509.ReasonFlags.superseded, + 5: x509.ReasonFlags.cessation_of_operation, + 6: x509.ReasonFlags.certificate_hold, + 8: x509.ReasonFlags.remove_from_crl, + 9: x509.ReasonFlags.privilege_withdrawn, + 10: x509.ReasonFlags.aa_compromise, +} + + +_CRL_ENTRY_REASON_ENUM_TO_CODE = { + x509.ReasonFlags.unspecified: 0, + x509.ReasonFlags.key_compromise: 1, + x509.ReasonFlags.ca_compromise: 2, + x509.ReasonFlags.affiliation_changed: 3, + x509.ReasonFlags.superseded: 4, + x509.ReasonFlags.cessation_of_operation: 5, + x509.ReasonFlags.certificate_hold: 6, + x509.ReasonFlags.remove_from_crl: 8, + x509.ReasonFlags.privilege_withdrawn: 9, + x509.ReasonFlags.aa_compromise: 10 +} + + +def _decode_crl_reason(backend, enum): + enum = backend._ffi.cast("ASN1_ENUMERATED *", enum) + enum = backend._ffi.gc(enum, backend._lib.ASN1_ENUMERATED_free) + code = backend._lib.ASN1_ENUMERATED_get(enum) + + try: + return x509.CRLReason(_CRL_ENTRY_REASON_CODE_TO_ENUM[code]) + except KeyError: + raise ValueError("Unsupported reason code: {0}".format(code)) + + +def _decode_invalidity_date(backend, inv_date): + generalized_time = backend._ffi.cast( + "ASN1_GENERALIZEDTIME *", inv_date + ) + generalized_time = backend._ffi.gc( + generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free + ) + return x509.InvalidityDate( + _parse_asn1_generalized_time(backend, generalized_time) + ) + + +def _decode_cert_issuer(backend, gns): + gns = backend._ffi.cast("GENERAL_NAMES *", gns) + gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) + general_names = _decode_general_names(backend, gns) + return x509.CertificateIssuer(general_names) + + +def _asn1_to_der(backend, asn1_type): + buf = backend._ffi.new("unsigned char **") + res = backend._lib.i2d_ASN1_TYPE(asn1_type, buf) + backend.openssl_assert(res >= 0) + backend.openssl_assert(buf[0] != backend._ffi.NULL) + buf = backend._ffi.gc( + buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0]) + ) + return backend._ffi.buffer(buf[0], res)[:] + + +def _asn1_integer_to_int(backend, asn1_int): + bn = backend._lib.ASN1_INTEGER_to_BN(asn1_int, backend._ffi.NULL) + backend.openssl_assert(bn != backend._ffi.NULL) + bn = backend._ffi.gc(bn, backend._lib.BN_free) + return backend._bn_to_int(bn) + + +def _asn1_integer_to_int_or_none(backend, asn1_int): + if asn1_int == backend._ffi.NULL: + return None + else: + return _asn1_integer_to_int(backend, asn1_int) + + +def _asn1_string_to_bytes(backend, asn1_string): + return backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] + + +def _asn1_string_to_ascii(backend, asn1_string): + return _asn1_string_to_bytes(backend, asn1_string).decode("ascii") + + +def _asn1_string_to_utf8(backend, asn1_string): + buf = backend._ffi.new("unsigned char **") + res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string) + if res == -1: + raise ValueError( + "Unsupported ASN1 string type. Type: {0}".format(asn1_string.type) + ) + + backend.openssl_assert(buf[0] != backend._ffi.NULL) + buf = backend._ffi.gc( + buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0]) + ) + return backend._ffi.buffer(buf[0], res)[:].decode('utf8') + + +def _parse_asn1_time(backend, asn1_time): + backend.openssl_assert(asn1_time != backend._ffi.NULL) + generalized_time = backend._lib.ASN1_TIME_to_generalizedtime( + asn1_time, backend._ffi.NULL + ) + if generalized_time == backend._ffi.NULL: + raise ValueError( + "Couldn't parse ASN.1 time as generalizedtime {!r}".format( + _asn1_string_to_bytes(backend, asn1_time) + ) + ) + + generalized_time = backend._ffi.gc( + generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free + ) + return _parse_asn1_generalized_time(backend, generalized_time) + + +def _parse_asn1_generalized_time(backend, generalized_time): + time = _asn1_string_to_ascii( + backend, backend._ffi.cast("ASN1_STRING *", generalized_time) + ) + return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ") + + +_EXTENSION_HANDLERS_NO_SCT = { + ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints, + ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, + ExtensionOID.KEY_USAGE: _decode_key_usage, + ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, + ExtensionOID.EXTENDED_KEY_USAGE: _decode_extended_key_usage, + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( + _decode_authority_information_access + ), + ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, + ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, + ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, + ExtensionOID.OCSP_NO_CHECK: _decode_ocsp_no_check, + ExtensionOID.INHIBIT_ANY_POLICY: _decode_inhibit_any_policy, + ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, + ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, + ExtensionOID.POLICY_CONSTRAINTS: _decode_policy_constraints, +} +_EXTENSION_HANDLERS = _EXTENSION_HANDLERS_NO_SCT.copy() +_EXTENSION_HANDLERS[ + ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS +] = _decode_precert_signed_certificate_timestamps + + +_REVOKED_EXTENSION_HANDLERS = { + CRLEntryExtensionOID.CRL_REASON: _decode_crl_reason, + CRLEntryExtensionOID.INVALIDITY_DATE: _decode_invalidity_date, + CRLEntryExtensionOID.CERTIFICATE_ISSUER: _decode_cert_issuer, +} + +_CRL_EXTENSION_HANDLERS = { + ExtensionOID.CRL_NUMBER: _decode_crl_number, + ExtensionOID.DELTA_CRL_INDICATOR: _decode_delta_crl_indicator, + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, + ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( + _decode_authority_information_access + ), +} + +_CERTIFICATE_EXTENSION_PARSER_NO_SCT = _X509ExtensionParser( + ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x), + get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i), + handlers=_EXTENSION_HANDLERS_NO_SCT +) + +_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser( + ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x), + get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i), + handlers=_EXTENSION_HANDLERS +) + +_CSR_EXTENSION_PARSER = _X509ExtensionParser( + ext_count=lambda backend, x: backend._lib.sk_X509_EXTENSION_num(x), + get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i), + handlers=_EXTENSION_HANDLERS +) + +_REVOKED_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser( + ext_count=lambda backend, x: backend._lib.X509_REVOKED_get_ext_count(x), + get_ext=lambda backend, x, i: backend._lib.X509_REVOKED_get_ext(x, i), + handlers=_REVOKED_EXTENSION_HANDLERS, +) + +_CRL_EXTENSION_PARSER = _X509ExtensionParser( + ext_count=lambda backend, x: backend._lib.X509_CRL_get_ext_count(x), + get_ext=lambda backend, x, i: backend._lib.X509_CRL_get_ext(x, i), + handlers=_CRL_EXTENSION_HANDLERS, +) diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dh.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dh.py new file mode 100644 index 0000000..095f062 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dh.py @@ -0,0 +1,280 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import dh + + +def _dh_params_dup(dh_cdata, backend): + lib = backend._lib + ffi = backend._ffi + + param_cdata = lib.DHparams_dup(dh_cdata) + backend.openssl_assert(param_cdata != ffi.NULL) + param_cdata = ffi.gc(param_cdata, lib.DH_free) + if lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102: + # In OpenSSL versions < 1.0.2 or libressl DHparams_dup don't copy q + q = ffi.new("BIGNUM **") + lib.DH_get0_pqg(dh_cdata, ffi.NULL, q, ffi.NULL) + q_dup = lib.BN_dup(q[0]) + res = lib.DH_set0_pqg(param_cdata, ffi.NULL, q_dup, ffi.NULL) + backend.openssl_assert(res == 1) + + return param_cdata + + +def _dh_cdata_to_parameters(dh_cdata, backend): + param_cdata = _dh_params_dup(dh_cdata, backend) + return _DHParameters(backend, param_cdata) + + +@utils.register_interface(dh.DHParametersWithSerialization) +class _DHParameters(object): + def __init__(self, backend, dh_cdata): + self._backend = backend + self._dh_cdata = dh_cdata + + def parameter_numbers(self): + p = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) + return dh.DHParameterNumbers( + p=self._backend._bn_to_int(p[0]), + g=self._backend._bn_to_int(g[0]), + q=q_val + ) + + def generate_private_key(self): + return self._backend.generate_dh_private_key(self) + + def parameter_bytes(self, encoding, format): + if format is not serialization.ParameterFormat.PKCS3: + raise ValueError( + "Only PKCS3 serialization is supported" + ) + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION) + + return self._backend._parameter_bytes( + encoding, + format, + self._dh_cdata + ) + + +def _handle_dh_compute_key_error(errors, backend): + lib = backend._lib + + backend.openssl_assert( + errors[0]._lib_reason_match( + lib.ERR_LIB_DH, lib.DH_R_INVALID_PUBKEY + ) + ) + + raise ValueError("Public key value is invalid for this exchange.") + + +def _get_dh_num_bits(backend, dh_cdata): + p = backend._ffi.new("BIGNUM **") + backend._lib.DH_get0_pqg(dh_cdata, p, + backend._ffi.NULL, + backend._ffi.NULL) + backend.openssl_assert(p[0] != backend._ffi.NULL) + return backend._lib.BN_num_bits(p[0]) + + +@utils.register_interface(dh.DHPrivateKeyWithSerialization) +class _DHPrivateKey(object): + def __init__(self, backend, dh_cdata, evp_pkey): + self._backend = backend + self._dh_cdata = dh_cdata + self._evp_pkey = evp_pkey + self._key_size_bytes = self._backend._lib.DH_size(dh_cdata) + + @property + def key_size(self): + return _get_dh_num_bits(self._backend, self._dh_cdata) + + def private_numbers(self): + p = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) + pub_key = self._backend._ffi.new("BIGNUM **") + priv_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, priv_key) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) + return dh.DHPrivateNumbers( + public_numbers=dh.DHPublicNumbers( + parameter_numbers=dh.DHParameterNumbers( + p=self._backend._bn_to_int(p[0]), + g=self._backend._bn_to_int(g[0]), + q=q_val + ), + y=self._backend._bn_to_int(pub_key[0]) + ), + x=self._backend._bn_to_int(priv_key[0]) + ) + + def exchange(self, peer_public_key): + + buf = self._backend._ffi.new("unsigned char[]", self._key_size_bytes) + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_key(peer_public_key._dh_cdata, pub_key, + self._backend._ffi.NULL) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + res = self._backend._lib.DH_compute_key( + buf, + pub_key[0], + self._dh_cdata + ) + + if res == -1: + errors = self._backend._consume_errors() + return _handle_dh_compute_key_error(errors, self._backend) + else: + self._backend.openssl_assert(res >= 1) + + key = self._backend._ffi.buffer(buf)[:res] + pad = self._key_size_bytes - len(key) + + if pad > 0: + key = (b"\x00" * pad) + key + + return key + + def public_key(self): + dh_cdata = _dh_params_dup(self._dh_cdata, self._backend) + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_key(self._dh_cdata, + pub_key, self._backend._ffi.NULL) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + pub_key_dup = self._backend._lib.BN_dup(pub_key[0]) + self._backend.openssl_assert(pub_key_dup != self._backend._ffi.NULL) + + res = self._backend._lib.DH_set0_key(dh_cdata, + pub_key_dup, + self._backend._ffi.NULL) + self._backend.openssl_assert(res == 1) + evp_pkey = self._backend._dh_cdata_to_evp_pkey(dh_cdata) + return _DHPublicKey(self._backend, dh_cdata, evp_pkey) + + def parameters(self): + return _dh_cdata_to_parameters(self._dh_cdata, self._backend) + + def private_bytes(self, encoding, format, encryption_algorithm): + if format is not serialization.PrivateFormat.PKCS8: + raise ValueError( + "DH private keys support only PKCS8 serialization" + ) + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION) + + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self._evp_pkey, + self._dh_cdata + ) + + +@utils.register_interface(dh.DHPublicKeyWithSerialization) +class _DHPublicKey(object): + def __init__(self, backend, dh_cdata, evp_pkey): + self._backend = backend + self._dh_cdata = dh_cdata + self._evp_pkey = evp_pkey + self._key_size_bits = _get_dh_num_bits(self._backend, self._dh_cdata) + + @property + def key_size(self): + return self._key_size_bits + + def public_numbers(self): + p = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + if q[0] == self._backend._ffi.NULL: + q_val = None + else: + q_val = self._backend._bn_to_int(q[0]) + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_key(self._dh_cdata, + pub_key, self._backend._ffi.NULL) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + return dh.DHPublicNumbers( + parameter_numbers=dh.DHParameterNumbers( + p=self._backend._bn_to_int(p[0]), + g=self._backend._bn_to_int(g[0]), + q=q_val + ), + y=self._backend._bn_to_int(pub_key[0]) + ) + + def parameters(self): + return _dh_cdata_to_parameters(self._dh_cdata, self._backend) + + def public_bytes(self, encoding, format): + if format is not serialization.PublicFormat.SubjectPublicKeyInfo: + raise ValueError( + "DH public keys support only " + "SubjectPublicKeyInfo serialization" + ) + + if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: + q = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DH_get0_pqg(self._dh_cdata, + self._backend._ffi.NULL, + q, + self._backend._ffi.NULL) + if q[0] != self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "DH X9.42 serialization is not supported", + _Reasons.UNSUPPORTED_SERIALIZATION) + + return self._backend._public_key_bytes( + encoding, + format, + self, + self._evp_pkey, + None + ) diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dsa.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dsa.py new file mode 100644 index 0000000..48886e4 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/dsa.py @@ -0,0 +1,269 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.backends.openssl.utils import ( + _calculate_digest_and_algorithm, _check_not_prehashed, + _warn_sign_verify_deprecated +) +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, AsymmetricVerificationContext, dsa +) + + +def _dsa_sig_sign(backend, private_key, data): + sig_buf_len = backend._lib.DSA_size(private_key._dsa_cdata) + sig_buf = backend._ffi.new("unsigned char[]", sig_buf_len) + buflen = backend._ffi.new("unsigned int *") + + # The first parameter passed to DSA_sign is unused by OpenSSL but + # must be an integer. + res = backend._lib.DSA_sign( + 0, data, len(data), sig_buf, buflen, private_key._dsa_cdata + ) + backend.openssl_assert(res == 1) + backend.openssl_assert(buflen[0]) + + return backend._ffi.buffer(sig_buf)[:buflen[0]] + + +def _dsa_sig_verify(backend, public_key, signature, data): + # The first parameter passed to DSA_verify is unused by OpenSSL but + # must be an integer. + res = backend._lib.DSA_verify( + 0, data, len(data), signature, len(signature), public_key._dsa_cdata + ) + + if res != 1: + backend._consume_errors() + raise InvalidSignature + + +@utils.register_interface(AsymmetricVerificationContext) +class _DSAVerificationContext(object): + def __init__(self, backend, public_key, signature, algorithm): + self._backend = backend + self._public_key = public_key + self._signature = signature + self._algorithm = algorithm + + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data): + self._hash_ctx.update(data) + + def verify(self): + data_to_verify = self._hash_ctx.finalize() + + _dsa_sig_verify( + self._backend, self._public_key, self._signature, data_to_verify + ) + + +@utils.register_interface(AsymmetricSignatureContext) +class _DSASignatureContext(object): + def __init__(self, backend, private_key, algorithm): + self._backend = backend + self._private_key = private_key + self._algorithm = algorithm + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data): + self._hash_ctx.update(data) + + def finalize(self): + data_to_sign = self._hash_ctx.finalize() + return _dsa_sig_sign(self._backend, self._private_key, data_to_sign) + + +@utils.register_interface(dsa.DSAParametersWithNumbers) +class _DSAParameters(object): + def __init__(self, backend, dsa_cdata): + self._backend = backend + self._dsa_cdata = dsa_cdata + + def parameter_numbers(self): + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + return dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + g=self._backend._bn_to_int(g[0]) + ) + + def generate_private_key(self): + return self._backend.generate_dsa_private_key(self) + + +@utils.register_interface(dsa.DSAPrivateKeyWithSerialization) +class _DSAPrivateKey(object): + def __init__(self, backend, dsa_cdata, evp_pkey): + self._backend = backend + self._dsa_cdata = dsa_cdata + self._evp_pkey = evp_pkey + + p = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg( + dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL + ) + self._backend.openssl_assert(p[0] != backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(p[0]) + + key_size = utils.read_only_property("_key_size") + + def signer(self, signature_algorithm): + _warn_sign_verify_deprecated() + _check_not_prehashed(signature_algorithm) + return _DSASignatureContext(self._backend, self, signature_algorithm) + + def private_numbers(self): + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + pub_key = self._backend._ffi.new("BIGNUM **") + priv_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + self._backend._lib.DSA_get0_key(self._dsa_cdata, pub_key, priv_key) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) + return dsa.DSAPrivateNumbers( + public_numbers=dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + g=self._backend._bn_to_int(g[0]) + ), + y=self._backend._bn_to_int(pub_key[0]) + ), + x=self._backend._bn_to_int(priv_key[0]) + ) + + def public_key(self): + dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) + self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_key( + self._dsa_cdata, pub_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + pub_key_dup = self._backend._lib.BN_dup(pub_key[0]) + res = self._backend._lib.DSA_set0_key( + dsa_cdata, pub_key_dup, self._backend._ffi.NULL + ) + self._backend.openssl_assert(res == 1) + evp_pkey = self._backend._dsa_cdata_to_evp_pkey(dsa_cdata) + return _DSAPublicKey(self._backend, dsa_cdata, evp_pkey) + + def parameters(self): + dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) + self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + return _DSAParameters(self._backend, dsa_cdata) + + def private_bytes(self, encoding, format, encryption_algorithm): + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self._evp_pkey, + self._dsa_cdata + ) + + def sign(self, data, algorithm): + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _dsa_sig_sign(self._backend, self, data) + + +@utils.register_interface(dsa.DSAPublicKeyWithSerialization) +class _DSAPublicKey(object): + def __init__(self, backend, dsa_cdata, evp_pkey): + self._backend = backend + self._dsa_cdata = dsa_cdata + self._evp_pkey = evp_pkey + p = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg( + dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL + ) + self._backend.openssl_assert(p[0] != backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(p[0]) + + key_size = utils.read_only_property("_key_size") + + def verifier(self, signature, signature_algorithm): + _warn_sign_verify_deprecated() + if not isinstance(signature, bytes): + raise TypeError("signature must be bytes.") + + _check_not_prehashed(signature_algorithm) + return _DSAVerificationContext( + self._backend, self, signature, signature_algorithm + ) + + def public_numbers(self): + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + g = self._backend._ffi.new("BIGNUM **") + pub_key = self._backend._ffi.new("BIGNUM **") + self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) + self._backend._lib.DSA_get0_key( + self._dsa_cdata, pub_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) + return dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + g=self._backend._bn_to_int(g[0]) + ), + y=self._backend._bn_to_int(pub_key[0]) + ) + + def parameters(self): + dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) + dsa_cdata = self._backend._ffi.gc( + dsa_cdata, self._backend._lib.DSA_free + ) + return _DSAParameters(self._backend, dsa_cdata) + + def public_bytes(self, encoding, format): + if format is serialization.PublicFormat.PKCS1: + raise ValueError( + "DSA public keys do not support PKCS1 serialization" + ) + + return self._backend._public_key_bytes( + encoding, + format, + self, + self._evp_pkey, + None + ) + + def verify(self, signature, data, algorithm): + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _dsa_sig_verify(self._backend, self, signature, data) diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ec.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ec.py new file mode 100644 index 0000000..69da234 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/ec.py @@ -0,0 +1,298 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.exceptions import ( + InvalidSignature, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.openssl.utils import ( + _calculate_digest_and_algorithm, _check_not_prehashed, + _warn_sign_verify_deprecated +) +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, AsymmetricVerificationContext, ec +) + + +def _check_signature_algorithm(signature_algorithm): + if not isinstance(signature_algorithm, ec.ECDSA): + raise UnsupportedAlgorithm( + "Unsupported elliptic curve signature algorithm.", + _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM) + + +def _ec_key_curve_sn(backend, ec_key): + group = backend._lib.EC_KEY_get0_group(ec_key) + backend.openssl_assert(group != backend._ffi.NULL) + + nid = backend._lib.EC_GROUP_get_curve_name(group) + # The following check is to find EC keys with unnamed curves and raise + # an error for now. + if nid == backend._lib.NID_undef: + raise NotImplementedError( + "ECDSA certificates with unnamed curves are unsupported " + "at this time" + ) + + curve_name = backend._lib.OBJ_nid2sn(nid) + backend.openssl_assert(curve_name != backend._ffi.NULL) + + sn = backend._ffi.string(curve_name).decode('ascii') + return sn + + +def _mark_asn1_named_ec_curve(backend, ec_cdata): + """ + Set the named curve flag on the EC_KEY. This causes OpenSSL to + serialize EC keys along with their curve OID which makes + deserialization easier. + """ + + backend._lib.EC_KEY_set_asn1_flag( + ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE + ) + + +def _sn_to_elliptic_curve(backend, sn): + try: + return ec._CURVE_TYPES[sn]() + except KeyError: + raise UnsupportedAlgorithm( + "{0} is not a supported elliptic curve".format(sn), + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE + ) + + +def _ecdsa_sig_sign(backend, private_key, data): + max_size = backend._lib.ECDSA_size(private_key._ec_key) + backend.openssl_assert(max_size > 0) + + sigbuf = backend._ffi.new("unsigned char[]", max_size) + siglen_ptr = backend._ffi.new("unsigned int[]", 1) + res = backend._lib.ECDSA_sign( + 0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key + ) + backend.openssl_assert(res == 1) + return backend._ffi.buffer(sigbuf)[:siglen_ptr[0]] + + +def _ecdsa_sig_verify(backend, public_key, signature, data): + res = backend._lib.ECDSA_verify( + 0, data, len(data), signature, len(signature), public_key._ec_key + ) + if res != 1: + backend._consume_errors() + raise InvalidSignature + + +@utils.register_interface(AsymmetricSignatureContext) +class _ECDSASignatureContext(object): + def __init__(self, backend, private_key, algorithm): + self._backend = backend + self._private_key = private_key + self._digest = hashes.Hash(algorithm, backend) + + def update(self, data): + self._digest.update(data) + + def finalize(self): + digest = self._digest.finalize() + + return _ecdsa_sig_sign(self._backend, self._private_key, digest) + + +@utils.register_interface(AsymmetricVerificationContext) +class _ECDSAVerificationContext(object): + def __init__(self, backend, public_key, signature, algorithm): + self._backend = backend + self._public_key = public_key + self._signature = signature + self._digest = hashes.Hash(algorithm, backend) + + def update(self, data): + self._digest.update(data) + + def verify(self): + digest = self._digest.finalize() + _ecdsa_sig_verify( + self._backend, self._public_key, self._signature, digest + ) + + +@utils.register_interface(ec.EllipticCurvePrivateKeyWithSerialization) +class _EllipticCurvePrivateKey(object): + def __init__(self, backend, ec_key_cdata, evp_pkey): + self._backend = backend + _mark_asn1_named_ec_curve(backend, ec_key_cdata) + self._ec_key = ec_key_cdata + self._evp_pkey = evp_pkey + + sn = _ec_key_curve_sn(backend, ec_key_cdata) + self._curve = _sn_to_elliptic_curve(backend, sn) + + curve = utils.read_only_property("_curve") + + @property + def key_size(self): + return self.curve.key_size + + def signer(self, signature_algorithm): + _warn_sign_verify_deprecated() + _check_signature_algorithm(signature_algorithm) + _check_not_prehashed(signature_algorithm.algorithm) + return _ECDSASignatureContext( + self._backend, self, signature_algorithm.algorithm + ) + + def exchange(self, algorithm, peer_public_key): + if not ( + self._backend.elliptic_curve_exchange_algorithm_supported( + algorithm, self.curve + ) + ): + raise UnsupportedAlgorithm( + "This backend does not support the ECDH algorithm.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + + if peer_public_key.curve.name != self.curve.name: + raise ValueError( + "peer_public_key and self are not on the same curve" + ) + + group = self._backend._lib.EC_KEY_get0_group(self._ec_key) + z_len = (self._backend._lib.EC_GROUP_get_degree(group) + 7) // 8 + self._backend.openssl_assert(z_len > 0) + z_buf = self._backend._ffi.new("uint8_t[]", z_len) + peer_key = self._backend._lib.EC_KEY_get0_public_key( + peer_public_key._ec_key + ) + + r = self._backend._lib.ECDH_compute_key( + z_buf, z_len, peer_key, self._ec_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(r > 0) + return self._backend._ffi.buffer(z_buf)[:z_len] + + def public_key(self): + group = self._backend._lib.EC_KEY_get0_group(self._ec_key) + self._backend.openssl_assert(group != self._backend._ffi.NULL) + + curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group) + + public_ec_key = self._backend._lib.EC_KEY_new_by_curve_name(curve_nid) + self._backend.openssl_assert(public_ec_key != self._backend._ffi.NULL) + public_ec_key = self._backend._ffi.gc( + public_ec_key, self._backend._lib.EC_KEY_free + ) + + point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) + self._backend.openssl_assert(point != self._backend._ffi.NULL) + + res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point) + self._backend.openssl_assert(res == 1) + + evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key) + + return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey) + + def private_numbers(self): + bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key) + private_value = self._backend._bn_to_int(bn) + return ec.EllipticCurvePrivateNumbers( + private_value=private_value, + public_numbers=self.public_key().public_numbers() + ) + + def private_bytes(self, encoding, format, encryption_algorithm): + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self._evp_pkey, + self._ec_key + ) + + def sign(self, data, signature_algorithm): + _check_signature_algorithm(signature_algorithm) + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, signature_algorithm._algorithm + ) + return _ecdsa_sig_sign(self._backend, self, data) + + +@utils.register_interface(ec.EllipticCurvePublicKeyWithSerialization) +class _EllipticCurvePublicKey(object): + def __init__(self, backend, ec_key_cdata, evp_pkey): + self._backend = backend + _mark_asn1_named_ec_curve(backend, ec_key_cdata) + self._ec_key = ec_key_cdata + self._evp_pkey = evp_pkey + + sn = _ec_key_curve_sn(backend, ec_key_cdata) + self._curve = _sn_to_elliptic_curve(backend, sn) + + curve = utils.read_only_property("_curve") + + @property + def key_size(self): + return self.curve.key_size + + def verifier(self, signature, signature_algorithm): + _warn_sign_verify_deprecated() + if not isinstance(signature, bytes): + raise TypeError("signature must be bytes.") + + _check_signature_algorithm(signature_algorithm) + _check_not_prehashed(signature_algorithm.algorithm) + return _ECDSAVerificationContext( + self._backend, self, signature, signature_algorithm.algorithm + ) + + def public_numbers(self): + get_func, group = ( + self._backend._ec_key_determine_group_get_func(self._ec_key) + ) + point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) + self._backend.openssl_assert(point != self._backend._ffi.NULL) + + with self._backend._tmp_bn_ctx() as bn_ctx: + bn_x = self._backend._lib.BN_CTX_get(bn_ctx) + bn_y = self._backend._lib.BN_CTX_get(bn_ctx) + + res = get_func(group, point, bn_x, bn_y, bn_ctx) + self._backend.openssl_assert(res == 1) + + x = self._backend._bn_to_int(bn_x) + y = self._backend._bn_to_int(bn_y) + + return ec.EllipticCurvePublicNumbers( + x=x, + y=y, + curve=self._curve + ) + + def public_bytes(self, encoding, format): + if format is serialization.PublicFormat.PKCS1: + raise ValueError( + "EC public keys do not support PKCS1 serialization" + ) + + return self._backend._public_key_bytes( + encoding, + format, + self, + self._evp_pkey, + None + ) + + def verify(self, signature, data, signature_algorithm): + _check_signature_algorithm(signature_algorithm) + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, signature_algorithm._algorithm + ) + _ecdsa_sig_verify(self._backend, self, signature, data) diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/encode_asn1.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/encode_asn1.py new file mode 100644 index 0000000..a2c7ed7 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -0,0 +1,611 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import calendar +import ipaddress + +import six + +from cryptography import utils, x509 +from cryptography.hazmat.backends.openssl.decode_asn1 import ( + _CRL_ENTRY_REASON_ENUM_TO_CODE, _DISTPOINT_TYPE_FULLNAME, + _DISTPOINT_TYPE_RELATIVENAME +) +from cryptography.x509.name import _ASN1Type +from cryptography.x509.oid import CRLEntryExtensionOID, ExtensionOID + + +def _encode_asn1_int(backend, x): + """ + Converts a python integer to an ASN1_INTEGER. The returned ASN1_INTEGER + will not be garbage collected (to support adding them to structs that take + ownership of the object). Be sure to register it for GC if it will be + discarded after use. + + """ + # Convert Python integer to OpenSSL "bignum" in case value exceeds + # machine's native integer limits (note: `int_to_bn` doesn't automatically + # GC). + i = backend._int_to_bn(x) + i = backend._ffi.gc(i, backend._lib.BN_free) + + # Wrap in an ASN.1 integer. Don't GC -- as documented. + i = backend._lib.BN_to_ASN1_INTEGER(i, backend._ffi.NULL) + backend.openssl_assert(i != backend._ffi.NULL) + return i + + +def _encode_asn1_int_gc(backend, x): + i = _encode_asn1_int(backend, x) + i = backend._ffi.gc(i, backend._lib.ASN1_INTEGER_free) + return i + + +def _encode_asn1_str(backend, data, length): + """ + Create an ASN1_OCTET_STRING from a Python byte string. + """ + s = backend._lib.ASN1_OCTET_STRING_new() + res = backend._lib.ASN1_OCTET_STRING_set(s, data, length) + backend.openssl_assert(res == 1) + return s + + +def _encode_asn1_utf8_str(backend, string): + """ + Create an ASN1_UTF8STRING from a Python unicode string. + This object will be an ASN1_STRING with UTF8 type in OpenSSL and + can be decoded with ASN1_STRING_to_UTF8. + """ + s = backend._lib.ASN1_UTF8STRING_new() + res = backend._lib.ASN1_STRING_set( + s, string.encode("utf8"), len(string.encode("utf8")) + ) + backend.openssl_assert(res == 1) + return s + + +def _encode_asn1_str_gc(backend, data, length): + s = _encode_asn1_str(backend, data, length) + s = backend._ffi.gc(s, backend._lib.ASN1_OCTET_STRING_free) + return s + + +def _encode_inhibit_any_policy(backend, inhibit_any_policy): + return _encode_asn1_int_gc(backend, inhibit_any_policy.skip_certs) + + +def _encode_name(backend, name): + """ + The X509_NAME created will not be gc'd. Use _encode_name_gc if needed. + """ + subject = backend._lib.X509_NAME_new() + for rdn in name.rdns: + set_flag = 0 # indicate whether to add to last RDN or create new RDN + for attribute in rdn: + name_entry = _encode_name_entry(backend, attribute) + # X509_NAME_add_entry dups the object so we need to gc this copy + name_entry = backend._ffi.gc( + name_entry, backend._lib.X509_NAME_ENTRY_free + ) + res = backend._lib.X509_NAME_add_entry( + subject, name_entry, -1, set_flag) + backend.openssl_assert(res == 1) + set_flag = -1 + return subject + + +def _encode_name_gc(backend, attributes): + subject = _encode_name(backend, attributes) + subject = backend._ffi.gc(subject, backend._lib.X509_NAME_free) + return subject + + +def _encode_sk_name_entry(backend, attributes): + """ + The sk_X509_NAME_ENTRY created will not be gc'd. + """ + stack = backend._lib.sk_X509_NAME_ENTRY_new_null() + for attribute in attributes: + name_entry = _encode_name_entry(backend, attribute) + res = backend._lib.sk_X509_NAME_ENTRY_push(stack, name_entry) + backend.openssl_assert(res == 1) + return stack + + +def _encode_name_entry(backend, attribute): + if attribute._type is _ASN1Type.BMPString: + value = attribute.value.encode('utf_16_be') + else: + value = attribute.value.encode('utf8') + + obj = _txt2obj_gc(backend, attribute.oid.dotted_string) + + name_entry = backend._lib.X509_NAME_ENTRY_create_by_OBJ( + backend._ffi.NULL, obj, attribute._type.value, value, len(value) + ) + return name_entry + + +def _encode_crl_number_delta_crl_indicator(backend, ext): + return _encode_asn1_int_gc(backend, ext.crl_number) + + +def _encode_crl_reason(backend, crl_reason): + asn1enum = backend._lib.ASN1_ENUMERATED_new() + backend.openssl_assert(asn1enum != backend._ffi.NULL) + asn1enum = backend._ffi.gc(asn1enum, backend._lib.ASN1_ENUMERATED_free) + res = backend._lib.ASN1_ENUMERATED_set( + asn1enum, _CRL_ENTRY_REASON_ENUM_TO_CODE[crl_reason.reason] + ) + backend.openssl_assert(res == 1) + + return asn1enum + + +def _encode_invalidity_date(backend, invalidity_date): + time = backend._lib.ASN1_GENERALIZEDTIME_set( + backend._ffi.NULL, calendar.timegm( + invalidity_date.invalidity_date.timetuple() + ) + ) + backend.openssl_assert(time != backend._ffi.NULL) + time = backend._ffi.gc(time, backend._lib.ASN1_GENERALIZEDTIME_free) + + return time + + +def _encode_certificate_policies(backend, certificate_policies): + cp = backend._lib.sk_POLICYINFO_new_null() + backend.openssl_assert(cp != backend._ffi.NULL) + cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free) + for policy_info in certificate_policies: + pi = backend._lib.POLICYINFO_new() + backend.openssl_assert(pi != backend._ffi.NULL) + res = backend._lib.sk_POLICYINFO_push(cp, pi) + backend.openssl_assert(res >= 1) + oid = _txt2obj(backend, policy_info.policy_identifier.dotted_string) + pi.policyid = oid + if policy_info.policy_qualifiers: + pqis = backend._lib.sk_POLICYQUALINFO_new_null() + backend.openssl_assert(pqis != backend._ffi.NULL) + for qualifier in policy_info.policy_qualifiers: + pqi = backend._lib.POLICYQUALINFO_new() + backend.openssl_assert(pqi != backend._ffi.NULL) + res = backend._lib.sk_POLICYQUALINFO_push(pqis, pqi) + backend.openssl_assert(res >= 1) + if isinstance(qualifier, six.text_type): + pqi.pqualid = _txt2obj( + backend, x509.OID_CPS_QUALIFIER.dotted_string + ) + pqi.d.cpsuri = _encode_asn1_str( + backend, + qualifier.encode("ascii"), + len(qualifier.encode("ascii")) + ) + else: + assert isinstance(qualifier, x509.UserNotice) + pqi.pqualid = _txt2obj( + backend, x509.OID_CPS_USER_NOTICE.dotted_string + ) + un = backend._lib.USERNOTICE_new() + backend.openssl_assert(un != backend._ffi.NULL) + pqi.d.usernotice = un + if qualifier.explicit_text: + un.exptext = _encode_asn1_utf8_str( + backend, qualifier.explicit_text + ) + + un.noticeref = _encode_notice_reference( + backend, qualifier.notice_reference + ) + + pi.qualifiers = pqis + + return cp + + +def _encode_notice_reference(backend, notice): + if notice is None: + return backend._ffi.NULL + else: + nr = backend._lib.NOTICEREF_new() + backend.openssl_assert(nr != backend._ffi.NULL) + # organization is a required field + nr.organization = _encode_asn1_utf8_str(backend, notice.organization) + + notice_stack = backend._lib.sk_ASN1_INTEGER_new_null() + nr.noticenos = notice_stack + for number in notice.notice_numbers: + num = _encode_asn1_int(backend, number) + res = backend._lib.sk_ASN1_INTEGER_push(notice_stack, num) + backend.openssl_assert(res >= 1) + + return nr + + +def _txt2obj(backend, name): + """ + Converts a Python string with an ASN.1 object ID in dotted form to a + ASN1_OBJECT. + """ + name = name.encode('ascii') + obj = backend._lib.OBJ_txt2obj(name, 1) + backend.openssl_assert(obj != backend._ffi.NULL) + return obj + + +def _txt2obj_gc(backend, name): + obj = _txt2obj(backend, name) + obj = backend._ffi.gc(obj, backend._lib.ASN1_OBJECT_free) + return obj + + +def _encode_ocsp_nocheck(backend, ext): + """ + The OCSP No Check extension is defined as a null ASN.1 value embedded in + an ASN.1 string. + """ + return _encode_asn1_str_gc(backend, b"\x05\x00", 2) + + +def _encode_key_usage(backend, key_usage): + set_bit = backend._lib.ASN1_BIT_STRING_set_bit + ku = backend._lib.ASN1_BIT_STRING_new() + ku = backend._ffi.gc(ku, backend._lib.ASN1_BIT_STRING_free) + res = set_bit(ku, 0, key_usage.digital_signature) + backend.openssl_assert(res == 1) + res = set_bit(ku, 1, key_usage.content_commitment) + backend.openssl_assert(res == 1) + res = set_bit(ku, 2, key_usage.key_encipherment) + backend.openssl_assert(res == 1) + res = set_bit(ku, 3, key_usage.data_encipherment) + backend.openssl_assert(res == 1) + res = set_bit(ku, 4, key_usage.key_agreement) + backend.openssl_assert(res == 1) + res = set_bit(ku, 5, key_usage.key_cert_sign) + backend.openssl_assert(res == 1) + res = set_bit(ku, 6, key_usage.crl_sign) + backend.openssl_assert(res == 1) + if key_usage.key_agreement: + res = set_bit(ku, 7, key_usage.encipher_only) + backend.openssl_assert(res == 1) + res = set_bit(ku, 8, key_usage.decipher_only) + backend.openssl_assert(res == 1) + else: + res = set_bit(ku, 7, 0) + backend.openssl_assert(res == 1) + res = set_bit(ku, 8, 0) + backend.openssl_assert(res == 1) + + return ku + + +def _encode_authority_key_identifier(backend, authority_keyid): + akid = backend._lib.AUTHORITY_KEYID_new() + backend.openssl_assert(akid != backend._ffi.NULL) + akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free) + if authority_keyid.key_identifier is not None: + akid.keyid = _encode_asn1_str( + backend, + authority_keyid.key_identifier, + len(authority_keyid.key_identifier) + ) + + if authority_keyid.authority_cert_issuer is not None: + akid.issuer = _encode_general_names( + backend, authority_keyid.authority_cert_issuer + ) + + if authority_keyid.authority_cert_serial_number is not None: + akid.serial = _encode_asn1_int( + backend, authority_keyid.authority_cert_serial_number + ) + + return akid + + +def _encode_basic_constraints(backend, basic_constraints): + constraints = backend._lib.BASIC_CONSTRAINTS_new() + constraints = backend._ffi.gc( + constraints, backend._lib.BASIC_CONSTRAINTS_free + ) + constraints.ca = 255 if basic_constraints.ca else 0 + if basic_constraints.ca and basic_constraints.path_length is not None: + constraints.pathlen = _encode_asn1_int( + backend, basic_constraints.path_length + ) + + return constraints + + +def _encode_authority_information_access(backend, authority_info_access): + aia = backend._lib.sk_ACCESS_DESCRIPTION_new_null() + backend.openssl_assert(aia != backend._ffi.NULL) + aia = backend._ffi.gc( + aia, backend._lib.sk_ACCESS_DESCRIPTION_free + ) + for access_description in authority_info_access: + ad = backend._lib.ACCESS_DESCRIPTION_new() + method = _txt2obj( + backend, access_description.access_method.dotted_string + ) + gn = _encode_general_name(backend, access_description.access_location) + ad.method = method + ad.location = gn + res = backend._lib.sk_ACCESS_DESCRIPTION_push(aia, ad) + backend.openssl_assert(res >= 1) + + return aia + + +def _encode_general_names(backend, names): + general_names = backend._lib.GENERAL_NAMES_new() + backend.openssl_assert(general_names != backend._ffi.NULL) + for name in names: + gn = _encode_general_name(backend, name) + res = backend._lib.sk_GENERAL_NAME_push(general_names, gn) + backend.openssl_assert(res != 0) + + return general_names + + +def _encode_alt_name(backend, san): + general_names = _encode_general_names(backend, san) + general_names = backend._ffi.gc( + general_names, backend._lib.GENERAL_NAMES_free + ) + return general_names + + +def _encode_subject_key_identifier(backend, ski): + return _encode_asn1_str_gc(backend, ski.digest, len(ski.digest)) + + +def _encode_general_name(backend, name): + if isinstance(name, x509.DNSName): + gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + gn.type = backend._lib.GEN_DNS + + ia5 = backend._lib.ASN1_IA5STRING_new() + backend.openssl_assert(ia5 != backend._ffi.NULL) + # ia5strings are supposed to be ITU T.50 but to allow round-tripping + # of broken certs that encode utf8 we'll encode utf8 here too. + value = name.value.encode("utf8") + + res = backend._lib.ASN1_STRING_set(ia5, value, len(value)) + backend.openssl_assert(res == 1) + gn.d.dNSName = ia5 + elif isinstance(name, x509.RegisteredID): + gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + gn.type = backend._lib.GEN_RID + obj = backend._lib.OBJ_txt2obj( + name.value.dotted_string.encode('ascii'), 1 + ) + backend.openssl_assert(obj != backend._ffi.NULL) + gn.d.registeredID = obj + elif isinstance(name, x509.DirectoryName): + gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + dir_name = _encode_name(backend, name.value) + gn.type = backend._lib.GEN_DIRNAME + gn.d.directoryName = dir_name + elif isinstance(name, x509.IPAddress): + gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + if isinstance(name.value, ipaddress.IPv4Network): + packed = ( + name.value.network_address.packed + + utils.int_to_bytes(((1 << 32) - name.value.num_addresses), 4) + ) + elif isinstance(name.value, ipaddress.IPv6Network): + packed = ( + name.value.network_address.packed + + utils.int_to_bytes((1 << 128) - name.value.num_addresses, 16) + ) + else: + packed = name.value.packed + ipaddr = _encode_asn1_str(backend, packed, len(packed)) + gn.type = backend._lib.GEN_IPADD + gn.d.iPAddress = ipaddr + elif isinstance(name, x509.OtherName): + gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + other_name = backend._lib.OTHERNAME_new() + backend.openssl_assert(other_name != backend._ffi.NULL) + + type_id = backend._lib.OBJ_txt2obj( + name.type_id.dotted_string.encode('ascii'), 1 + ) + backend.openssl_assert(type_id != backend._ffi.NULL) + data = backend._ffi.new("unsigned char[]", name.value) + data_ptr_ptr = backend._ffi.new("unsigned char **") + data_ptr_ptr[0] = data + value = backend._lib.d2i_ASN1_TYPE( + backend._ffi.NULL, data_ptr_ptr, len(name.value) + ) + if value == backend._ffi.NULL: + backend._consume_errors() + raise ValueError("Invalid ASN.1 data") + other_name.type_id = type_id + other_name.value = value + gn.type = backend._lib.GEN_OTHERNAME + gn.d.otherName = other_name + elif isinstance(name, x509.RFC822Name): + gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + # ia5strings are supposed to be ITU T.50 but to allow round-tripping + # of broken certs that encode utf8 we'll encode utf8 here too. + data = name.value.encode("utf8") + asn1_str = _encode_asn1_str(backend, data, len(data)) + gn.type = backend._lib.GEN_EMAIL + gn.d.rfc822Name = asn1_str + elif isinstance(name, x509.UniformResourceIdentifier): + gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + # ia5strings are supposed to be ITU T.50 but to allow round-tripping + # of broken certs that encode utf8 we'll encode utf8 here too. + data = name.value.encode("utf8") + asn1_str = _encode_asn1_str(backend, data, len(data)) + gn.type = backend._lib.GEN_URI + gn.d.uniformResourceIdentifier = asn1_str + else: + raise ValueError( + "{0} is an unknown GeneralName type".format(name) + ) + + return gn + + +def _encode_extended_key_usage(backend, extended_key_usage): + eku = backend._lib.sk_ASN1_OBJECT_new_null() + eku = backend._ffi.gc(eku, backend._lib.sk_ASN1_OBJECT_free) + for oid in extended_key_usage: + obj = _txt2obj(backend, oid.dotted_string) + res = backend._lib.sk_ASN1_OBJECT_push(eku, obj) + backend.openssl_assert(res >= 1) + + return eku + + +_CRLREASONFLAGS = { + x509.ReasonFlags.key_compromise: 1, + x509.ReasonFlags.ca_compromise: 2, + x509.ReasonFlags.affiliation_changed: 3, + x509.ReasonFlags.superseded: 4, + x509.ReasonFlags.cessation_of_operation: 5, + x509.ReasonFlags.certificate_hold: 6, + x509.ReasonFlags.privilege_withdrawn: 7, + x509.ReasonFlags.aa_compromise: 8, +} + + +def _encode_cdps_freshest_crl(backend, cdps): + cdp = backend._lib.sk_DIST_POINT_new_null() + cdp = backend._ffi.gc(cdp, backend._lib.sk_DIST_POINT_free) + for point in cdps: + dp = backend._lib.DIST_POINT_new() + backend.openssl_assert(dp != backend._ffi.NULL) + + if point.reasons: + bitmask = backend._lib.ASN1_BIT_STRING_new() + backend.openssl_assert(bitmask != backend._ffi.NULL) + dp.reasons = bitmask + for reason in point.reasons: + res = backend._lib.ASN1_BIT_STRING_set_bit( + bitmask, _CRLREASONFLAGS[reason], 1 + ) + backend.openssl_assert(res == 1) + + if point.full_name: + dpn = backend._lib.DIST_POINT_NAME_new() + backend.openssl_assert(dpn != backend._ffi.NULL) + dpn.type = _DISTPOINT_TYPE_FULLNAME + dpn.name.fullname = _encode_general_names(backend, point.full_name) + dp.distpoint = dpn + + if point.relative_name: + dpn = backend._lib.DIST_POINT_NAME_new() + backend.openssl_assert(dpn != backend._ffi.NULL) + dpn.type = _DISTPOINT_TYPE_RELATIVENAME + relativename = _encode_sk_name_entry(backend, point.relative_name) + backend.openssl_assert(relativename != backend._ffi.NULL) + dpn.name.relativename = relativename + dp.distpoint = dpn + + if point.crl_issuer: + dp.CRLissuer = _encode_general_names(backend, point.crl_issuer) + + res = backend._lib.sk_DIST_POINT_push(cdp, dp) + backend.openssl_assert(res >= 1) + + return cdp + + +def _encode_name_constraints(backend, name_constraints): + nc = backend._lib.NAME_CONSTRAINTS_new() + backend.openssl_assert(nc != backend._ffi.NULL) + nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) + permitted = _encode_general_subtree( + backend, name_constraints.permitted_subtrees + ) + nc.permittedSubtrees = permitted + excluded = _encode_general_subtree( + backend, name_constraints.excluded_subtrees + ) + nc.excludedSubtrees = excluded + + return nc + + +def _encode_policy_constraints(backend, policy_constraints): + pc = backend._lib.POLICY_CONSTRAINTS_new() + backend.openssl_assert(pc != backend._ffi.NULL) + pc = backend._ffi.gc(pc, backend._lib.POLICY_CONSTRAINTS_free) + if policy_constraints.require_explicit_policy is not None: + pc.requireExplicitPolicy = _encode_asn1_int( + backend, policy_constraints.require_explicit_policy + ) + + if policy_constraints.inhibit_policy_mapping is not None: + pc.inhibitPolicyMapping = _encode_asn1_int( + backend, policy_constraints.inhibit_policy_mapping + ) + + return pc + + +def _encode_general_subtree(backend, subtrees): + if subtrees is None: + return backend._ffi.NULL + else: + general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null() + for name in subtrees: + gs = backend._lib.GENERAL_SUBTREE_new() + gs.base = _encode_general_name(backend, name) + res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs) + assert res >= 1 + + return general_subtrees + + +_EXTENSION_ENCODE_HANDLERS = { + ExtensionOID.BASIC_CONSTRAINTS: _encode_basic_constraints, + ExtensionOID.SUBJECT_KEY_IDENTIFIER: _encode_subject_key_identifier, + ExtensionOID.KEY_USAGE: _encode_key_usage, + ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _encode_alt_name, + ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name, + ExtensionOID.EXTENDED_KEY_USAGE: _encode_extended_key_usage, + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier, + ExtensionOID.CERTIFICATE_POLICIES: _encode_certificate_policies, + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( + _encode_authority_information_access + ), + ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_cdps_freshest_crl, + ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl, + ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy, + ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck, + ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints, + ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints, +} + +_CRL_EXTENSION_ENCODE_HANDLERS = { + ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name, + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier, + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( + _encode_authority_information_access + ), + ExtensionOID.CRL_NUMBER: _encode_crl_number_delta_crl_indicator, + ExtensionOID.DELTA_CRL_INDICATOR: _encode_crl_number_delta_crl_indicator, +} + +_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = { + CRLEntryExtensionOID.CERTIFICATE_ISSUER: _encode_alt_name, + CRLEntryExtensionOID.CRL_REASON: _encode_crl_reason, + CRLEntryExtensionOID.INVALIDITY_DATE: _encode_invalidity_date, +} diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hashes.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hashes.py new file mode 100644 index 0000000..92ea53b --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hashes.py @@ -0,0 +1,61 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.primitives import hashes + + +@utils.register_interface(hashes.HashContext) +class _HashContext(object): + def __init__(self, backend, algorithm, ctx=None): + self._algorithm = algorithm + + self._backend = backend + + if ctx is None: + ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + ctx = self._backend._ffi.gc( + ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + ) + name = self._backend._build_openssl_digest_name(algorithm) + evp_md = self._backend._lib.EVP_get_digestbyname(name) + if evp_md == self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "{0} is not a supported hash on this backend.".format( + name), + _Reasons.UNSUPPORTED_HASH + ) + res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md, + self._backend._ffi.NULL) + self._backend.openssl_assert(res != 0) + + self._ctx = ctx + + algorithm = utils.read_only_property("_algorithm") + + def copy(self): + copied_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + copied_ctx = self._backend._ffi.gc( + copied_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + ) + res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx) + self._backend.openssl_assert(res != 0) + return _HashContext(self._backend, self.algorithm, ctx=copied_ctx) + + def update(self, data): + res = self._backend._lib.EVP_DigestUpdate(self._ctx, data, len(data)) + self._backend.openssl_assert(res != 0) + + def finalize(self): + buf = self._backend._ffi.new("unsigned char[]", + self._backend._lib.EVP_MAX_MD_SIZE) + outlen = self._backend._ffi.new("unsigned int *") + res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen) + self._backend.openssl_assert(res != 0) + self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size) + return self._backend._ffi.buffer(buf)[:outlen[0]] diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hmac.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hmac.py new file mode 100644 index 0000000..3577f47 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/hmac.py @@ -0,0 +1,73 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + + +from cryptography import utils +from cryptography.exceptions import ( + InvalidSignature, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.primitives import constant_time, hashes, mac + + +@utils.register_interface(mac.MACContext) +@utils.register_interface(hashes.HashContext) +class _HMACContext(object): + def __init__(self, backend, key, algorithm, ctx=None): + self._algorithm = algorithm + self._backend = backend + + if ctx is None: + ctx = self._backend._lib.Cryptography_HMAC_CTX_new() + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc( + ctx, self._backend._lib.Cryptography_HMAC_CTX_free + ) + name = self._backend._build_openssl_digest_name(algorithm) + evp_md = self._backend._lib.EVP_get_digestbyname(name) + if evp_md == self._backend._ffi.NULL: + raise UnsupportedAlgorithm( + "{0} is not a supported hash on this backend".format(name), + _Reasons.UNSUPPORTED_HASH + ) + res = self._backend._lib.HMAC_Init_ex( + ctx, key, len(key), evp_md, self._backend._ffi.NULL + ) + self._backend.openssl_assert(res != 0) + + self._ctx = ctx + self._key = key + + algorithm = utils.read_only_property("_algorithm") + + def copy(self): + copied_ctx = self._backend._lib.Cryptography_HMAC_CTX_new() + self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL) + copied_ctx = self._backend._ffi.gc( + copied_ctx, self._backend._lib.Cryptography_HMAC_CTX_free + ) + res = self._backend._lib.HMAC_CTX_copy(copied_ctx, self._ctx) + self._backend.openssl_assert(res != 0) + return _HMACContext( + self._backend, self._key, self.algorithm, ctx=copied_ctx + ) + + def update(self, data): + res = self._backend._lib.HMAC_Update(self._ctx, data, len(data)) + self._backend.openssl_assert(res != 0) + + def finalize(self): + buf = self._backend._ffi.new("unsigned char[]", + self._backend._lib.EVP_MAX_MD_SIZE) + outlen = self._backend._ffi.new("unsigned int *") + res = self._backend._lib.HMAC_Final(self._ctx, buf, outlen) + self._backend.openssl_assert(res != 0) + self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size) + return self._backend._ffi.buffer(buf)[:outlen[0]] + + def verify(self, signature): + digest = self.finalize() + if not constant_time.bytes_eq(digest, signature): + raise InvalidSignature("Signature did not match digest.") diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/rsa.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/rsa.py new file mode 100644 index 0000000..9a7bfaa --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/rsa.py @@ -0,0 +1,475 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import math + +from cryptography import utils +from cryptography.exceptions import ( + InvalidSignature, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.openssl.utils import ( + _calculate_digest_and_algorithm, _check_not_prehashed, + _warn_sign_verify_deprecated +) +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, AsymmetricVerificationContext, rsa +) +from cryptography.hazmat.primitives.asymmetric.padding import ( + AsymmetricPadding, MGF1, OAEP, PKCS1v15, PSS, calculate_max_pss_salt_length +) +from cryptography.hazmat.primitives.asymmetric.rsa import ( + RSAPrivateKeyWithSerialization, RSAPublicKeyWithSerialization +) + + +def _get_rsa_pss_salt_length(pss, key, hash_algorithm): + salt = pss._salt_length + + if salt is MGF1.MAX_LENGTH or salt is PSS.MAX_LENGTH: + return calculate_max_pss_salt_length(key, hash_algorithm) + else: + return salt + + +def _enc_dec_rsa(backend, key, data, padding): + if not isinstance(padding, AsymmetricPadding): + raise TypeError("Padding must be an instance of AsymmetricPadding.") + + if isinstance(padding, PKCS1v15): + padding_enum = backend._lib.RSA_PKCS1_PADDING + elif isinstance(padding, OAEP): + padding_enum = backend._lib.RSA_PKCS1_OAEP_PADDING + + if not isinstance(padding._mgf, MGF1): + raise UnsupportedAlgorithm( + "Only MGF1 is supported by this backend.", + _Reasons.UNSUPPORTED_MGF + ) + + if not backend.rsa_padding_supported(padding): + raise UnsupportedAlgorithm( + "This combination of padding and hash algorithm is not " + "supported by this backend.", + _Reasons.UNSUPPORTED_PADDING + ) + + else: + raise UnsupportedAlgorithm( + "{0} is not supported by this backend.".format( + padding.name + ), + _Reasons.UNSUPPORTED_PADDING + ) + + return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding) + + +def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding): + if isinstance(key, _RSAPublicKey): + init = backend._lib.EVP_PKEY_encrypt_init + crypt = backend._lib.EVP_PKEY_encrypt + else: + init = backend._lib.EVP_PKEY_decrypt_init + crypt = backend._lib.EVP_PKEY_decrypt + + pkey_ctx = backend._lib.EVP_PKEY_CTX_new( + key._evp_pkey, backend._ffi.NULL + ) + backend.openssl_assert(pkey_ctx != backend._ffi.NULL) + pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) + res = init(pkey_ctx) + backend.openssl_assert(res == 1) + res = backend._lib.EVP_PKEY_CTX_set_rsa_padding( + pkey_ctx, padding_enum) + backend.openssl_assert(res > 0) + buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey) + backend.openssl_assert(buf_size > 0) + if ( + isinstance(padding, OAEP) and + backend._lib.Cryptography_HAS_RSA_OAEP_MD + ): + mgf1_md = backend._lib.EVP_get_digestbyname( + padding._mgf._algorithm.name.encode("ascii")) + backend.openssl_assert(mgf1_md != backend._ffi.NULL) + res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) + backend.openssl_assert(res > 0) + oaep_md = backend._lib.EVP_get_digestbyname( + padding._algorithm.name.encode("ascii")) + backend.openssl_assert(oaep_md != backend._ffi.NULL) + res = backend._lib.EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, oaep_md) + backend.openssl_assert(res > 0) + + if ( + isinstance(padding, OAEP) and + padding._label is not None and + len(padding._label) > 0 + ): + # set0_rsa_oaep_label takes ownership of the char * so we need to + # copy it into some new memory + labelptr = backend._lib.OPENSSL_malloc(len(padding._label)) + backend.openssl_assert(labelptr != backend._ffi.NULL) + backend._ffi.memmove(labelptr, padding._label, len(padding._label)) + res = backend._lib.EVP_PKEY_CTX_set0_rsa_oaep_label( + pkey_ctx, labelptr, len(padding._label) + ) + backend.openssl_assert(res == 1) + + outlen = backend._ffi.new("size_t *", buf_size) + buf = backend._ffi.new("unsigned char[]", buf_size) + res = crypt(pkey_ctx, buf, outlen, data, len(data)) + if res <= 0: + _handle_rsa_enc_dec_error(backend, key) + + return backend._ffi.buffer(buf)[:outlen[0]] + + +def _handle_rsa_enc_dec_error(backend, key): + errors = backend._consume_errors() + backend.openssl_assert(errors) + assert errors[0].lib == backend._lib.ERR_LIB_RSA + if isinstance(key, _RSAPublicKey): + assert (errors[0].reason == + backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE) + raise ValueError( + "Data too long for key size. Encrypt less data or use a " + "larger key size." + ) + else: + decoding_errors = [ + backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01, + backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02, + backend._lib.RSA_R_OAEP_DECODING_ERROR, + # Though this error looks similar to the + # RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE, this occurs on decrypts, + # rather than on encrypts + backend._lib.RSA_R_DATA_TOO_LARGE_FOR_MODULUS, + ] + if backend._lib.Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR: + decoding_errors.append(backend._lib.RSA_R_PKCS_DECODING_ERROR) + + assert errors[0].reason in decoding_errors + raise ValueError("Decryption failed.") + + +def _rsa_sig_determine_padding(backend, key, padding, algorithm): + if not isinstance(padding, AsymmetricPadding): + raise TypeError("Expected provider of AsymmetricPadding.") + + pkey_size = backend._lib.EVP_PKEY_size(key._evp_pkey) + backend.openssl_assert(pkey_size > 0) + + if isinstance(padding, PKCS1v15): + padding_enum = backend._lib.RSA_PKCS1_PADDING + elif isinstance(padding, PSS): + if not isinstance(padding._mgf, MGF1): + raise UnsupportedAlgorithm( + "Only MGF1 is supported by this backend.", + _Reasons.UNSUPPORTED_MGF + ) + + # Size of key in bytes - 2 is the maximum + # PSS signature length (salt length is checked later) + if pkey_size - algorithm.digest_size - 2 < 0: + raise ValueError("Digest too large for key size. Use a larger " + "key or different digest.") + + padding_enum = backend._lib.RSA_PKCS1_PSS_PADDING + else: + raise UnsupportedAlgorithm( + "{0} is not supported by this backend.".format(padding.name), + _Reasons.UNSUPPORTED_PADDING + ) + + return padding_enum + + +def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func): + padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm) + evp_md = backend._lib.EVP_get_digestbyname(algorithm.name.encode("ascii")) + backend.openssl_assert(evp_md != backend._ffi.NULL) + pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL) + backend.openssl_assert(pkey_ctx != backend._ffi.NULL) + pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) + res = init_func(pkey_ctx) + backend.openssl_assert(res == 1) + res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md) + backend.openssl_assert(res > 0) + res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) + backend.openssl_assert(res > 0) + if isinstance(padding, PSS): + res = backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen( + pkey_ctx, _get_rsa_pss_salt_length(padding, key, algorithm) + ) + backend.openssl_assert(res > 0) + + mgf1_md = backend._lib.EVP_get_digestbyname( + padding._mgf._algorithm.name.encode("ascii") + ) + backend.openssl_assert(mgf1_md != backend._ffi.NULL) + res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) + backend.openssl_assert(res > 0) + + return pkey_ctx + + +def _rsa_sig_sign(backend, padding, algorithm, private_key, data): + pkey_ctx = _rsa_sig_setup( + backend, padding, algorithm, private_key, data, + backend._lib.EVP_PKEY_sign_init + ) + buflen = backend._ffi.new("size_t *") + res = backend._lib.EVP_PKEY_sign( + pkey_ctx, + backend._ffi.NULL, + buflen, + data, + len(data) + ) + backend.openssl_assert(res == 1) + buf = backend._ffi.new("unsigned char[]", buflen[0]) + res = backend._lib.EVP_PKEY_sign( + pkey_ctx, buf, buflen, data, len(data)) + if res != 1: + errors = backend._consume_errors() + assert errors[0].lib == backend._lib.ERR_LIB_RSA + reason = None + if (errors[0].reason == + backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE): + reason = ("Salt length too long for key size. Try using " + "MAX_LENGTH instead.") + else: + assert (errors[0].reason == + backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY) + reason = "Digest too large for key size. Use a larger key." + assert reason is not None + raise ValueError(reason) + + return backend._ffi.buffer(buf)[:] + + +def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data): + pkey_ctx = _rsa_sig_setup( + backend, padding, algorithm, public_key, data, + backend._lib.EVP_PKEY_verify_init + ) + res = backend._lib.EVP_PKEY_verify( + pkey_ctx, signature, len(signature), data, len(data) + ) + # The previous call can return negative numbers in the event of an + # error. This is not a signature failure but we need to fail if it + # occurs. + backend.openssl_assert(res >= 0) + if res == 0: + backend._consume_errors() + raise InvalidSignature + + +@utils.register_interface(AsymmetricSignatureContext) +class _RSASignatureContext(object): + def __init__(self, backend, private_key, padding, algorithm): + self._backend = backend + self._private_key = private_key + + # We now call _rsa_sig_determine_padding in _rsa_sig_setup. However + # we need to make a pointless call to it here so we maintain the + # API of erroring on init with this context if the values are invalid. + _rsa_sig_determine_padding(backend, private_key, padding, algorithm) + self._padding = padding + self._algorithm = algorithm + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data): + self._hash_ctx.update(data) + + def finalize(self): + return _rsa_sig_sign( + self._backend, + self._padding, + self._algorithm, + self._private_key, + self._hash_ctx.finalize() + ) + + +@utils.register_interface(AsymmetricVerificationContext) +class _RSAVerificationContext(object): + def __init__(self, backend, public_key, signature, padding, algorithm): + self._backend = backend + self._public_key = public_key + self._signature = signature + self._padding = padding + # We now call _rsa_sig_determine_padding in _rsa_sig_setup. However + # we need to make a pointless call to it here so we maintain the + # API of erroring on init with this context if the values are invalid. + _rsa_sig_determine_padding(backend, public_key, padding, algorithm) + + padding = padding + self._algorithm = algorithm + self._hash_ctx = hashes.Hash(self._algorithm, self._backend) + + def update(self, data): + self._hash_ctx.update(data) + + def verify(self): + return _rsa_sig_verify( + self._backend, + self._padding, + self._algorithm, + self._public_key, + self._signature, + self._hash_ctx.finalize() + ) + + +@utils.register_interface(RSAPrivateKeyWithSerialization) +class _RSAPrivateKey(object): + def __init__(self, backend, rsa_cdata, evp_pkey): + self._backend = backend + self._rsa_cdata = rsa_cdata + self._evp_pkey = evp_pkey + + n = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key( + self._rsa_cdata, n, self._backend._ffi.NULL, + self._backend._ffi.NULL + ) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(n[0]) + + key_size = utils.read_only_property("_key_size") + + def signer(self, padding, algorithm): + _warn_sign_verify_deprecated() + _check_not_prehashed(algorithm) + return _RSASignatureContext(self._backend, self, padding, algorithm) + + def decrypt(self, ciphertext, padding): + key_size_bytes = int(math.ceil(self.key_size / 8.0)) + if key_size_bytes != len(ciphertext): + raise ValueError("Ciphertext length must be equal to key size.") + + return _enc_dec_rsa(self._backend, self, ciphertext, padding) + + def public_key(self): + ctx = self._backend._lib.RSAPublicKey_dup(self._rsa_cdata) + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free) + res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL) + self._backend.openssl_assert(res == 1) + evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx) + return _RSAPublicKey(self._backend, ctx, evp_pkey) + + def private_numbers(self): + n = self._backend._ffi.new("BIGNUM **") + e = self._backend._ffi.new("BIGNUM **") + d = self._backend._ffi.new("BIGNUM **") + p = self._backend._ffi.new("BIGNUM **") + q = self._backend._ffi.new("BIGNUM **") + dmp1 = self._backend._ffi.new("BIGNUM **") + dmq1 = self._backend._ffi.new("BIGNUM **") + iqmp = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key(self._rsa_cdata, n, e, d) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(d[0] != self._backend._ffi.NULL) + self._backend._lib.RSA_get0_factors(self._rsa_cdata, p, q) + self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) + self._backend._lib.RSA_get0_crt_params( + self._rsa_cdata, dmp1, dmq1, iqmp + ) + self._backend.openssl_assert(dmp1[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(dmq1[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(iqmp[0] != self._backend._ffi.NULL) + return rsa.RSAPrivateNumbers( + p=self._backend._bn_to_int(p[0]), + q=self._backend._bn_to_int(q[0]), + d=self._backend._bn_to_int(d[0]), + dmp1=self._backend._bn_to_int(dmp1[0]), + dmq1=self._backend._bn_to_int(dmq1[0]), + iqmp=self._backend._bn_to_int(iqmp[0]), + public_numbers=rsa.RSAPublicNumbers( + e=self._backend._bn_to_int(e[0]), + n=self._backend._bn_to_int(n[0]), + ) + ) + + def private_bytes(self, encoding, format, encryption_algorithm): + return self._backend._private_key_bytes( + encoding, + format, + encryption_algorithm, + self._evp_pkey, + self._rsa_cdata + ) + + def sign(self, data, padding, algorithm): + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _rsa_sig_sign(self._backend, padding, algorithm, self, data) + + +@utils.register_interface(RSAPublicKeyWithSerialization) +class _RSAPublicKey(object): + def __init__(self, backend, rsa_cdata, evp_pkey): + self._backend = backend + self._rsa_cdata = rsa_cdata + self._evp_pkey = evp_pkey + + n = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key( + self._rsa_cdata, n, self._backend._ffi.NULL, + self._backend._ffi.NULL + ) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._key_size = self._backend._lib.BN_num_bits(n[0]) + + key_size = utils.read_only_property("_key_size") + + def verifier(self, signature, padding, algorithm): + _warn_sign_verify_deprecated() + if not isinstance(signature, bytes): + raise TypeError("signature must be bytes.") + + _check_not_prehashed(algorithm) + return _RSAVerificationContext( + self._backend, self, signature, padding, algorithm + ) + + def encrypt(self, plaintext, padding): + return _enc_dec_rsa(self._backend, self, plaintext, padding) + + def public_numbers(self): + n = self._backend._ffi.new("BIGNUM **") + e = self._backend._ffi.new("BIGNUM **") + self._backend._lib.RSA_get0_key( + self._rsa_cdata, n, e, self._backend._ffi.NULL + ) + self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) + self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) + return rsa.RSAPublicNumbers( + e=self._backend._bn_to_int(e[0]), + n=self._backend._bn_to_int(n[0]), + ) + + def public_bytes(self, encoding, format): + return self._backend._public_key_bytes( + encoding, + format, + self, + self._evp_pkey, + self._rsa_cdata + ) + + def verify(self, signature, data, padding, algorithm): + data, algorithm = _calculate_digest_and_algorithm( + self._backend, data, algorithm + ) + return _rsa_sig_verify( + self._backend, padding, algorithm, self, signature, data + ) diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/utils.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/utils.py new file mode 100644 index 0000000..05d0fe5 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/utils.py @@ -0,0 +1,45 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import warnings + +from cryptography import utils +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.utils import Prehashed + + +def _calculate_digest_and_algorithm(backend, data, algorithm): + if not isinstance(algorithm, Prehashed): + hash_ctx = hashes.Hash(algorithm, backend) + hash_ctx.update(data) + data = hash_ctx.finalize() + else: + algorithm = algorithm._algorithm + + if len(data) != algorithm.digest_size: + raise ValueError( + "The provided data must be the same length as the hash " + "algorithm's digest size." + ) + + return (data, algorithm) + + +def _check_not_prehashed(signature_algorithm): + if isinstance(signature_algorithm, Prehashed): + raise TypeError( + "Prehashed is only supported in the sign and verify methods. " + "It cannot be used with signer or verifier." + ) + + +def _warn_sign_verify_deprecated(): + warnings.warn( + "signer and verifier have been deprecated. Please use sign " + "and verify instead.", + utils.PersistentlyDeprecated, + stacklevel=3 + ) diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x25519.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x25519.py new file mode 100644 index 0000000..983ece6 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x25519.py @@ -0,0 +1,79 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.hazmat.primitives.asymmetric.x25519 import ( + X25519PrivateKey, X25519PublicKey +) + + +@utils.register_interface(X25519PublicKey) +class _X25519PublicKey(object): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_bytes(self): + ucharpp = self._backend._ffi.new("unsigned char **") + res = self._backend._lib.EVP_PKEY_get1_tls_encodedpoint( + self._evp_pkey, ucharpp + ) + self._backend.openssl_assert(res == 32) + self._backend.openssl_assert(ucharpp[0] != self._backend._ffi.NULL) + data = self._backend._ffi.gc( + ucharpp[0], self._backend._lib.OPENSSL_free + ) + return self._backend._ffi.buffer(data, res)[:] + + +@utils.register_interface(X25519PrivateKey) +class _X25519PrivateKey(object): + def __init__(self, backend, evp_pkey): + self._backend = backend + self._evp_pkey = evp_pkey + + def public_key(self): + bio = self._backend._create_mem_bio_gc() + res = self._backend._lib.i2d_PUBKEY_bio(bio, self._evp_pkey) + self._backend.openssl_assert(res == 1) + evp_pkey = self._backend._lib.d2i_PUBKEY_bio( + bio, self._backend._ffi.NULL + ) + self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL) + evp_pkey = self._backend._ffi.gc( + evp_pkey, self._backend._lib.EVP_PKEY_free + ) + return _X25519PublicKey(self._backend, evp_pkey) + + def exchange(self, peer_public_key): + if not isinstance(peer_public_key, X25519PublicKey): + raise TypeError("peer_public_key must be X25519PublicKey.") + + ctx = self._backend._lib.EVP_PKEY_CTX_new( + self._evp_pkey, self._backend._ffi.NULL + ) + self._backend.openssl_assert(ctx != self._backend._ffi.NULL) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.EVP_PKEY_CTX_free) + res = self._backend._lib.EVP_PKEY_derive_init(ctx) + self._backend.openssl_assert(res == 1) + res = self._backend._lib.EVP_PKEY_derive_set_peer( + ctx, peer_public_key._evp_pkey + ) + self._backend.openssl_assert(res == 1) + keylen = self._backend._ffi.new("size_t *") + res = self._backend._lib.EVP_PKEY_derive( + ctx, self._backend._ffi.NULL, keylen + ) + self._backend.openssl_assert(res == 1) + self._backend.openssl_assert(keylen[0] > 0) + buf = self._backend._ffi.new("unsigned char[]", keylen[0]) + res = self._backend._lib.EVP_PKEY_derive(ctx, buf, keylen) + if res != 1: + raise ValueError( + "Null shared key derived from public/private pair." + ) + + return self._backend._ffi.buffer(buf, keylen[0])[:] diff --git a/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x509.py b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x509.py new file mode 100644 index 0000000..b870eeb --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/backends/openssl/x509.py @@ -0,0 +1,518 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import datetime +import operator +import warnings + +from cryptography import utils, x509 +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.backends.openssl.decode_asn1 import ( + _CERTIFICATE_EXTENSION_PARSER, _CERTIFICATE_EXTENSION_PARSER_NO_SCT, + _CRL_EXTENSION_PARSER, _CSR_EXTENSION_PARSER, + _REVOKED_CERTIFICATE_EXTENSION_PARSER, _asn1_integer_to_int, + _asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_time +) +from cryptography.hazmat.backends.openssl.encode_asn1 import ( + _encode_asn1_int_gc +) +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa + + +@utils.register_interface(x509.Certificate) +class _Certificate(object): + def __init__(self, backend, x509): + self._backend = backend + self._x509 = x509 + + def __repr__(self): + return "".format(self.subject) + + def __eq__(self, other): + if not isinstance(other, x509.Certificate): + return NotImplemented + + res = self._backend._lib.X509_cmp(self._x509, other._x509) + return res == 0 + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.public_bytes(serialization.Encoding.DER)) + + def fingerprint(self, algorithm): + h = hashes.Hash(algorithm, self._backend) + h.update(self.public_bytes(serialization.Encoding.DER)) + return h.finalize() + + @property + def version(self): + version = self._backend._lib.X509_get_version(self._x509) + if version == 0: + return x509.Version.v1 + elif version == 2: + return x509.Version.v3 + else: + raise x509.InvalidVersion( + "{0} is not a valid X509 version".format(version), version + ) + + @property + def serial(self): + warnings.warn( + "Certificate serial is deprecated, use serial_number instead.", + utils.PersistentlyDeprecated, + stacklevel=2 + ) + return self.serial_number + + @property + def serial_number(self): + asn1_int = self._backend._lib.X509_get_serialNumber(self._x509) + self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) + return _asn1_integer_to_int(self._backend, asn1_int) + + def public_key(self): + pkey = self._backend._lib.X509_get_pubkey(self._x509) + if pkey == self._backend._ffi.NULL: + # Remove errors from the stack. + self._backend._consume_errors() + raise ValueError("Certificate public key is of an unknown type") + + pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) + + return self._backend._evp_pkey_to_public_key(pkey) + + @property + def not_valid_before(self): + asn1_time = self._backend._lib.X509_get_notBefore(self._x509) + return _parse_asn1_time(self._backend, asn1_time) + + @property + def not_valid_after(self): + asn1_time = self._backend._lib.X509_get_notAfter(self._x509) + return _parse_asn1_time(self._backend, asn1_time) + + @property + def issuer(self): + issuer = self._backend._lib.X509_get_issuer_name(self._x509) + self._backend.openssl_assert(issuer != self._backend._ffi.NULL) + return _decode_x509_name(self._backend, issuer) + + @property + def subject(self): + subject = self._backend._lib.X509_get_subject_name(self._x509) + self._backend.openssl_assert(subject != self._backend._ffi.NULL) + return _decode_x509_name(self._backend, subject) + + @property + def signature_hash_algorithm(self): + oid = self.signature_algorithm_oid + try: + return x509._SIG_OIDS_TO_HASH[oid] + except KeyError: + raise UnsupportedAlgorithm( + "Signature algorithm OID:{0} not recognized".format(oid) + ) + + @property + def signature_algorithm_oid(self): + alg = self._backend._ffi.new("X509_ALGOR **") + self._backend._lib.X509_get0_signature( + self._backend._ffi.NULL, alg, self._x509 + ) + self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) + oid = _obj2txt(self._backend, alg[0].algorithm) + return x509.ObjectIdentifier(oid) + + @utils.cached_property + def extensions(self): + if self._backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER: + return _CERTIFICATE_EXTENSION_PARSER.parse( + self._backend, self._x509 + ) + else: + return _CERTIFICATE_EXTENSION_PARSER_NO_SCT.parse( + self._backend, self._x509 + ) + + @property + def signature(self): + sig = self._backend._ffi.new("ASN1_BIT_STRING **") + self._backend._lib.X509_get0_signature( + sig, self._backend._ffi.NULL, self._x509 + ) + self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) + return _asn1_string_to_bytes(self._backend, sig[0]) + + @property + def tbs_certificate_bytes(self): + pp = self._backend._ffi.new("unsigned char **") + res = self._backend._lib.i2d_re_X509_tbs(self._x509, pp) + self._backend.openssl_assert(res > 0) + pp = self._backend._ffi.gc( + pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) + ) + return self._backend._ffi.buffer(pp[0], res)[:] + + def public_bytes(self, encoding): + bio = self._backend._create_mem_bio_gc() + if encoding is serialization.Encoding.PEM: + res = self._backend._lib.PEM_write_bio_X509(bio, self._x509) + elif encoding is serialization.Encoding.DER: + res = self._backend._lib.i2d_X509_bio(bio, self._x509) + else: + raise TypeError("encoding must be an item from the Encoding enum") + + self._backend.openssl_assert(res == 1) + return self._backend._read_mem_bio(bio) + + +@utils.register_interface(x509.RevokedCertificate) +class _RevokedCertificate(object): + def __init__(self, backend, crl, x509_revoked): + self._backend = backend + # The X509_REVOKED_value is a X509_REVOKED * that has + # no reference counting. This means when X509_CRL_free is + # called then the CRL and all X509_REVOKED * are freed. Since + # you can retain a reference to a single revoked certificate + # and let the CRL fall out of scope we need to retain a + # private reference to the CRL inside the RevokedCertificate + # object to prevent the gc from being called inappropriately. + self._crl = crl + self._x509_revoked = x509_revoked + + @property + def serial_number(self): + asn1_int = self._backend._lib.X509_REVOKED_get0_serialNumber( + self._x509_revoked + ) + self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) + return _asn1_integer_to_int(self._backend, asn1_int) + + @property + def revocation_date(self): + return _parse_asn1_time( + self._backend, + self._backend._lib.X509_REVOKED_get0_revocationDate( + self._x509_revoked + ) + ) + + @utils.cached_property + def extensions(self): + return _REVOKED_CERTIFICATE_EXTENSION_PARSER.parse( + self._backend, self._x509_revoked + ) + + +@utils.register_interface(x509.CertificateRevocationList) +class _CertificateRevocationList(object): + def __init__(self, backend, x509_crl): + self._backend = backend + self._x509_crl = x509_crl + + def __eq__(self, other): + if not isinstance(other, x509.CertificateRevocationList): + return NotImplemented + + res = self._backend._lib.X509_CRL_cmp(self._x509_crl, other._x509_crl) + return res == 0 + + def __ne__(self, other): + return not self == other + + def fingerprint(self, algorithm): + h = hashes.Hash(algorithm, self._backend) + bio = self._backend._create_mem_bio_gc() + res = self._backend._lib.i2d_X509_CRL_bio( + bio, self._x509_crl + ) + self._backend.openssl_assert(res == 1) + der = self._backend._read_mem_bio(bio) + h.update(der) + return h.finalize() + + def get_revoked_certificate_by_serial_number(self, serial_number): + revoked = self._backend._ffi.new("X509_REVOKED **") + asn1_int = _encode_asn1_int_gc(self._backend, serial_number) + res = self._backend._lib.X509_CRL_get0_by_serial( + self._x509_crl, revoked, asn1_int + ) + if res == 0: + return None + else: + self._backend.openssl_assert( + revoked[0] != self._backend._ffi.NULL + ) + return _RevokedCertificate( + self._backend, self._x509_crl, revoked[0] + ) + + @property + def signature_hash_algorithm(self): + oid = self.signature_algorithm_oid + try: + return x509._SIG_OIDS_TO_HASH[oid] + except KeyError: + raise UnsupportedAlgorithm( + "Signature algorithm OID:{0} not recognized".format(oid) + ) + + @property + def signature_algorithm_oid(self): + alg = self._backend._ffi.new("X509_ALGOR **") + self._backend._lib.X509_CRL_get0_signature( + self._x509_crl, self._backend._ffi.NULL, alg + ) + self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) + oid = _obj2txt(self._backend, alg[0].algorithm) + return x509.ObjectIdentifier(oid) + + @property + def issuer(self): + issuer = self._backend._lib.X509_CRL_get_issuer(self._x509_crl) + self._backend.openssl_assert(issuer != self._backend._ffi.NULL) + return _decode_x509_name(self._backend, issuer) + + @property + def next_update(self): + nu = self._backend._lib.X509_CRL_get_nextUpdate(self._x509_crl) + self._backend.openssl_assert(nu != self._backend._ffi.NULL) + return _parse_asn1_time(self._backend, nu) + + @property + def last_update(self): + lu = self._backend._lib.X509_CRL_get_lastUpdate(self._x509_crl) + self._backend.openssl_assert(lu != self._backend._ffi.NULL) + return _parse_asn1_time(self._backend, lu) + + @property + def signature(self): + sig = self._backend._ffi.new("ASN1_BIT_STRING **") + self._backend._lib.X509_CRL_get0_signature( + self._x509_crl, sig, self._backend._ffi.NULL + ) + self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) + return _asn1_string_to_bytes(self._backend, sig[0]) + + @property + def tbs_certlist_bytes(self): + pp = self._backend._ffi.new("unsigned char **") + res = self._backend._lib.i2d_re_X509_CRL_tbs(self._x509_crl, pp) + self._backend.openssl_assert(res > 0) + pp = self._backend._ffi.gc( + pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) + ) + return self._backend._ffi.buffer(pp[0], res)[:] + + def public_bytes(self, encoding): + bio = self._backend._create_mem_bio_gc() + if encoding is serialization.Encoding.PEM: + res = self._backend._lib.PEM_write_bio_X509_CRL( + bio, self._x509_crl + ) + elif encoding is serialization.Encoding.DER: + res = self._backend._lib.i2d_X509_CRL_bio(bio, self._x509_crl) + else: + raise TypeError("encoding must be an item from the Encoding enum") + + self._backend.openssl_assert(res == 1) + return self._backend._read_mem_bio(bio) + + def _revoked_cert(self, idx): + revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl) + r = self._backend._lib.sk_X509_REVOKED_value(revoked, idx) + self._backend.openssl_assert(r != self._backend._ffi.NULL) + return _RevokedCertificate(self._backend, self, r) + + def __iter__(self): + for i in range(len(self)): + yield self._revoked_cert(i) + + def __getitem__(self, idx): + if isinstance(idx, slice): + start, stop, step = idx.indices(len(self)) + return [self._revoked_cert(i) for i in range(start, stop, step)] + else: + idx = operator.index(idx) + if idx < 0: + idx += len(self) + if not 0 <= idx < len(self): + raise IndexError + return self._revoked_cert(idx) + + def __len__(self): + revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl) + if revoked == self._backend._ffi.NULL: + return 0 + else: + return self._backend._lib.sk_X509_REVOKED_num(revoked) + + @utils.cached_property + def extensions(self): + return _CRL_EXTENSION_PARSER.parse(self._backend, self._x509_crl) + + def is_signature_valid(self, public_key): + if not isinstance(public_key, (dsa.DSAPublicKey, rsa.RSAPublicKey, + ec.EllipticCurvePublicKey)): + raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,' + ' or EllipticCurvePublicKey.') + res = self._backend._lib.X509_CRL_verify( + self._x509_crl, public_key._evp_pkey + ) + + if res != 1: + self._backend._consume_errors() + return False + + return True + + +@utils.register_interface(x509.CertificateSigningRequest) +class _CertificateSigningRequest(object): + def __init__(self, backend, x509_req): + self._backend = backend + self._x509_req = x509_req + + def __eq__(self, other): + if not isinstance(other, _CertificateSigningRequest): + return NotImplemented + + self_bytes = self.public_bytes(serialization.Encoding.DER) + other_bytes = other.public_bytes(serialization.Encoding.DER) + return self_bytes == other_bytes + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.public_bytes(serialization.Encoding.DER)) + + def public_key(self): + pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req) + self._backend.openssl_assert(pkey != self._backend._ffi.NULL) + pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) + return self._backend._evp_pkey_to_public_key(pkey) + + @property + def subject(self): + subject = self._backend._lib.X509_REQ_get_subject_name(self._x509_req) + self._backend.openssl_assert(subject != self._backend._ffi.NULL) + return _decode_x509_name(self._backend, subject) + + @property + def signature_hash_algorithm(self): + oid = self.signature_algorithm_oid + try: + return x509._SIG_OIDS_TO_HASH[oid] + except KeyError: + raise UnsupportedAlgorithm( + "Signature algorithm OID:{0} not recognized".format(oid) + ) + + @property + def signature_algorithm_oid(self): + alg = self._backend._ffi.new("X509_ALGOR **") + self._backend._lib.X509_REQ_get0_signature( + self._x509_req, self._backend._ffi.NULL, alg + ) + self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) + oid = _obj2txt(self._backend, alg[0].algorithm) + return x509.ObjectIdentifier(oid) + + @utils.cached_property + def extensions(self): + x509_exts = self._backend._lib.X509_REQ_get_extensions(self._x509_req) + return _CSR_EXTENSION_PARSER.parse(self._backend, x509_exts) + + def public_bytes(self, encoding): + bio = self._backend._create_mem_bio_gc() + if encoding is serialization.Encoding.PEM: + res = self._backend._lib.PEM_write_bio_X509_REQ( + bio, self._x509_req + ) + elif encoding is serialization.Encoding.DER: + res = self._backend._lib.i2d_X509_REQ_bio(bio, self._x509_req) + else: + raise TypeError("encoding must be an item from the Encoding enum") + + self._backend.openssl_assert(res == 1) + return self._backend._read_mem_bio(bio) + + @property + def tbs_certrequest_bytes(self): + pp = self._backend._ffi.new("unsigned char **") + res = self._backend._lib.i2d_re_X509_REQ_tbs(self._x509_req, pp) + self._backend.openssl_assert(res > 0) + pp = self._backend._ffi.gc( + pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) + ) + return self._backend._ffi.buffer(pp[0], res)[:] + + @property + def signature(self): + sig = self._backend._ffi.new("ASN1_BIT_STRING **") + self._backend._lib.X509_REQ_get0_signature( + self._x509_req, sig, self._backend._ffi.NULL + ) + self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) + return _asn1_string_to_bytes(self._backend, sig[0]) + + @property + def is_signature_valid(self): + pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req) + self._backend.openssl_assert(pkey != self._backend._ffi.NULL) + pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) + res = self._backend._lib.X509_REQ_verify(self._x509_req, pkey) + + if res != 1: + self._backend._consume_errors() + return False + + return True + + +@utils.register_interface( + x509.certificate_transparency.SignedCertificateTimestamp +) +class _SignedCertificateTimestamp(object): + def __init__(self, backend, sct_list, sct): + self._backend = backend + # Keep the SCT_LIST that this SCT came from alive. + self._sct_list = sct_list + self._sct = sct + + @property + def version(self): + version = self._backend._lib.SCT_get_version(self._sct) + assert version == self._backend._lib.SCT_VERSION_V1 + return x509.certificate_transparency.Version.v1 + + @property + def log_id(self): + out = self._backend._ffi.new("unsigned char **") + log_id_length = self._backend._lib.SCT_get0_log_id(self._sct, out) + assert log_id_length >= 0 + return self._backend._ffi.buffer(out[0], log_id_length)[:] + + @property + def timestamp(self): + timestamp = self._backend._lib.SCT_get_timestamp(self._sct) + milliseconds = timestamp % 1000 + return datetime.datetime.utcfromtimestamp( + timestamp // 1000 + ).replace(microsecond=milliseconds * 1000) + + @property + def entry_type(self): + entry_type = self._backend._lib.SCT_get_log_entry_type(self._sct) + # We currently only support loading SCTs from the X.509 extension, so + # we only have precerts. + assert entry_type == self._backend._lib.CT_LOG_ENTRY_TYPE_PRECERT + return x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE diff --git a/server/www/packages/packages-common/cryptography/hazmat/bindings/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/bindings/__init__.py new file mode 100644 index 0000000..4b54088 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/bindings/__init__.py @@ -0,0 +1,5 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function diff --git a/server/www/packages/packages-common/cryptography/hazmat/bindings/_constant_time.cp37-win32.pyd b/server/www/packages/packages-common/cryptography/hazmat/bindings/_constant_time.cp37-win32.pyd new file mode 100644 index 0000000000000000000000000000000000000000..7e80078c6e1a763b0f5927677f50bb9f301a0a3c GIT binary patch literal 9728 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

pBR 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

  • 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

    B4 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 z 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

    tD6RB(YoUF=g+*GAk#uC2 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

    mw_AKXa4&HRq_j!FJ3AZ#2T@?nd*Q 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 z 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

    N)-`Y5ML%x7S>BhBVkYqw! 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

    & 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 BzBVUhpCE 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 w1DR4 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 z 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
    `^rtca|WE?w(Wj2%k&y| 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 literal 0 HcmV?d00001 diff --git a/server/www/packages/packages-common/cryptography/hazmat/bindings/_padding.cp37-win32.pyd b/server/www/packages/packages-common/cryptography/hazmat/bindings/_padding.cp37-win32.pyd new file mode 100644 index 0000000000000000000000000000000000000000..72ae81342f8a4ed7d5b97742b829c1f831dd90e2 GIT binary patch literal 9728 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 literal 0 HcmV?d00001 diff --git a/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/__init__.py new file mode 100644 index 0000000..4b54088 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/__init__.py @@ -0,0 +1,5 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function diff --git a/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/_conditional.py b/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/_conditional.py new file mode 100644 index 0000000..b3e4e8b --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/_conditional.py @@ -0,0 +1,302 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + + +def cryptography_has_ec2m(): + return [ + "EC_POINT_set_affine_coordinates_GF2m", + "EC_POINT_get_affine_coordinates_GF2m", + "EC_POINT_set_compressed_coordinates_GF2m", + ] + + +def cryptography_has_ec_1_0_2(): + return [ + "EC_curve_nid2nist", + ] + + +def cryptography_has_set_ecdh_auto(): + return [ + "SSL_CTX_set_ecdh_auto", + ] + + +def cryptography_has_rsa_r_pkcs_decoding_error(): + return [ + "RSA_R_PKCS_DECODING_ERROR" + ] + + +def cryptography_has_rsa_oaep_md(): + return [ + "EVP_PKEY_CTX_set_rsa_oaep_md", + ] + + +def cryptography_has_rsa_oaep_label(): + return [ + "EVP_PKEY_CTX_set0_rsa_oaep_label", + ] + + +def cryptography_has_ssl3_method(): + return [ + "SSLv3_method", + "SSLv3_client_method", + "SSLv3_server_method", + ] + + +def cryptography_has_alpn(): + return [ + "SSL_CTX_set_alpn_protos", + "SSL_set_alpn_protos", + "SSL_CTX_set_alpn_select_cb", + "SSL_get0_alpn_selected", + ] + + +def cryptography_has_compression(): + return [ + "SSL_get_current_compression", + "SSL_get_current_expansion", + "SSL_COMP_get_name", + ] + + +def cryptography_has_get_server_tmp_key(): + return [ + "SSL_get_server_tmp_key", + ] + + +def cryptography_has_102_verification_error_codes(): + return [ + 'X509_V_ERR_SUITE_B_INVALID_VERSION', + 'X509_V_ERR_SUITE_B_INVALID_ALGORITHM', + 'X509_V_ERR_SUITE_B_INVALID_CURVE', + 'X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM', + 'X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED', + 'X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256', + 'X509_V_ERR_HOSTNAME_MISMATCH', + 'X509_V_ERR_EMAIL_MISMATCH', + 'X509_V_ERR_IP_ADDRESS_MISMATCH' + ] + + +def cryptography_has_102_verification_params(): + return [ + "X509_V_FLAG_SUITEB_128_LOS_ONLY", + "X509_V_FLAG_SUITEB_192_LOS", + "X509_V_FLAG_SUITEB_128_LOS", + "X509_VERIFY_PARAM_set1_host", + "X509_VERIFY_PARAM_set1_email", + "X509_VERIFY_PARAM_set1_ip", + "X509_VERIFY_PARAM_set1_ip_asc", + "X509_VERIFY_PARAM_set_hostflags", + ] + + +def cryptography_has_x509_v_flag_trusted_first(): + return [ + "X509_V_FLAG_TRUSTED_FIRST", + ] + + +def cryptography_has_x509_v_flag_partial_chain(): + return [ + "X509_V_FLAG_PARTIAL_CHAIN", + ] + + +def cryptography_has_set_cert_cb(): + return [ + "SSL_CTX_set_cert_cb", + "SSL_set_cert_cb", + ] + + +def cryptography_has_ssl_st(): + return [ + "SSL_ST_BEFORE", + "SSL_ST_OK", + "SSL_ST_INIT", + "SSL_ST_RENEGOTIATE", + ] + + +def cryptography_has_tls_st(): + return [ + "TLS_ST_BEFORE", + "TLS_ST_OK", + ] + + +def cryptography_has_locking_callbacks(): + return [ + "CRYPTO_LOCK", + "CRYPTO_UNLOCK", + "CRYPTO_READ", + "CRYPTO_LOCK_SSL", + "CRYPTO_lock", + ] + + +def cryptography_has_scrypt(): + return [ + "EVP_PBE_scrypt", + ] + + +def cryptography_has_generic_dtls_method(): + return [ + "DTLS_method", + "DTLS_server_method", + "DTLS_client_method", + "SSL_OP_NO_DTLSv1", + "SSL_OP_NO_DTLSv1_2", + "DTLS_set_link_mtu", + "DTLS_get_link_min_mtu", + ] + + +def cryptography_has_evp_pkey_dhx(): + return [ + "EVP_PKEY_DHX", + ] + + +def cryptography_has_mem_functions(): + return [ + "Cryptography_CRYPTO_set_mem_functions", + ] + + +def cryptography_has_sct(): + return [ + "SCT_get_version", + "SCT_get_log_entry_type", + "SCT_get0_log_id", + "SCT_get_timestamp", + "SCT_set_source", + "sk_SCT_num", + "sk_SCT_value", + "SCT_LIST_free", + ] + + +def cryptography_has_x509_store_ctx_get_issuer(): + return [ + "X509_STORE_get_get_issuer", + "X509_STORE_set_get_issuer", + ] + + +def cryptography_has_x25519(): + return [ + "EVP_PKEY_X25519", + "NID_X25519", + ] + + +def cryptography_has_evp_pkey_get_set_tls_encodedpoint(): + return [ + "EVP_PKEY_get1_tls_encodedpoint", + "EVP_PKEY_set1_tls_encodedpoint", + ] + + +def cryptography_has_fips(): + return [ + "FIPS_set_mode", + "FIPS_mode", + ] + + +def cryptography_has_ssl_sigalgs(): + return [ + "SSL_CTX_set1_sigalgs_list", + "SSL_get_sigalgs", + ] + + +def cryptography_has_psk(): + return [ + "SSL_CTX_use_psk_identity_hint", + "SSL_CTX_set_psk_server_callback", + "SSL_CTX_set_psk_client_callback", + ] + + +def cryptography_has_custom_ext(): + return [ + "SSL_CTX_add_client_custom_ext", + "SSL_CTX_add_server_custom_ext", + "SSL_extension_supported", + ] + + +def cryptography_has_openssl_cleanup(): + return [ + "OPENSSL_cleanup", + ] + + +# This is a mapping of +# {condition: function-returning-names-dependent-on-that-condition} so we can +# loop over them and delete unsupported names at runtime. It will be removed +# when cffi supports #if in cdef. We use functions instead of just a dict of +# lists so we can use coverage to measure which are used. +CONDITIONAL_NAMES = { + "Cryptography_HAS_EC2M": cryptography_has_ec2m, + "Cryptography_HAS_EC_1_0_2": cryptography_has_ec_1_0_2, + "Cryptography_HAS_SET_ECDH_AUTO": cryptography_has_set_ecdh_auto, + "Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR": ( + cryptography_has_rsa_r_pkcs_decoding_error + ), + "Cryptography_HAS_RSA_OAEP_MD": cryptography_has_rsa_oaep_md, + "Cryptography_HAS_RSA_OAEP_LABEL": cryptography_has_rsa_oaep_label, + "Cryptography_HAS_SSL3_METHOD": cryptography_has_ssl3_method, + "Cryptography_HAS_ALPN": cryptography_has_alpn, + "Cryptography_HAS_COMPRESSION": cryptography_has_compression, + "Cryptography_HAS_GET_SERVER_TMP_KEY": cryptography_has_get_server_tmp_key, + "Cryptography_HAS_102_VERIFICATION_ERROR_CODES": ( + cryptography_has_102_verification_error_codes + ), + "Cryptography_HAS_102_VERIFICATION_PARAMS": ( + cryptography_has_102_verification_params + ), + "Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST": ( + cryptography_has_x509_v_flag_trusted_first + ), + "Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN": ( + cryptography_has_x509_v_flag_partial_chain + ), + "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb, + "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st, + "Cryptography_HAS_TLS_ST": cryptography_has_tls_st, + "Cryptography_HAS_LOCKING_CALLBACKS": cryptography_has_locking_callbacks, + "Cryptography_HAS_SCRYPT": cryptography_has_scrypt, + "Cryptography_HAS_GENERIC_DTLS_METHOD": ( + cryptography_has_generic_dtls_method + ), + "Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx, + "Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions, + "Cryptography_HAS_SCT": cryptography_has_sct, + "Cryptography_HAS_X509_STORE_CTX_GET_ISSUER": ( + cryptography_has_x509_store_ctx_get_issuer + ), + "Cryptography_HAS_X25519": cryptography_has_x25519, + "Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint": ( + cryptography_has_evp_pkey_get_set_tls_encodedpoint + ), + "Cryptography_HAS_FIPS": cryptography_has_fips, + "Cryptography_HAS_SIGALGS": cryptography_has_ssl_sigalgs, + "Cryptography_HAS_PSK": cryptography_has_psk, + "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, + "Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup, +} diff --git a/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/binding.py b/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/binding.py new file mode 100644 index 0000000..81cf547 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/bindings/openssl/binding.py @@ -0,0 +1,157 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import collections +import threading +import types + +from cryptography import utils +from cryptography.exceptions import InternalError +from cryptography.hazmat.bindings._openssl import ffi, lib +from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES + +_OpenSSLErrorWithText = collections.namedtuple( + "_OpenSSLErrorWithText", ["code", "lib", "func", "reason", "reason_text"] +) + + +class _OpenSSLError(object): + def __init__(self, code, lib, func, reason): + self._code = code + self._lib = lib + self._func = func + self._reason = reason + + def _lib_reason_match(self, lib, reason): + return lib == self.lib and reason == self.reason + + code = utils.read_only_property("_code") + lib = utils.read_only_property("_lib") + func = utils.read_only_property("_func") + reason = utils.read_only_property("_reason") + + +def _consume_errors(lib): + errors = [] + while True: + code = lib.ERR_get_error() + if code == 0: + break + + err_lib = lib.ERR_GET_LIB(code) + err_func = lib.ERR_GET_FUNC(code) + err_reason = lib.ERR_GET_REASON(code) + + errors.append(_OpenSSLError(code, err_lib, err_func, err_reason)) + + return errors + + +def _openssl_assert(lib, ok): + if not ok: + errors = _consume_errors(lib) + errors_with_text = [] + for err in errors: + buf = ffi.new("char[]", 256) + lib.ERR_error_string_n(err.code, buf, len(buf)) + err_text_reason = ffi.string(buf) + + errors_with_text.append( + _OpenSSLErrorWithText( + err.code, err.lib, err.func, err.reason, err_text_reason + ) + ) + + raise InternalError( + "Unknown OpenSSL error. This error is commonly encountered when " + "another library is not cleaning up the OpenSSL error stack. If " + "you are using cryptography with another library that uses " + "OpenSSL try disabling it before reporting a bug. Otherwise " + "please file an issue at https://github.com/pyca/cryptography/" + "issues with information on how to reproduce " + "this. ({0!r})".format(errors_with_text), + errors_with_text + ) + + +def build_conditional_library(lib, conditional_names): + conditional_lib = types.ModuleType("lib") + conditional_lib._original_lib = lib + excluded_names = set() + for condition, names_cb in conditional_names.items(): + if not getattr(lib, condition): + excluded_names.update(names_cb()) + + for attr in dir(lib): + if attr not in excluded_names: + setattr(conditional_lib, attr, getattr(lib, attr)) + + return conditional_lib + + +class Binding(object): + """ + OpenSSL API wrapper. + """ + lib = None + ffi = ffi + _lib_loaded = False + _init_lock = threading.Lock() + _lock_init_lock = threading.Lock() + + def __init__(self): + self._ensure_ffi_initialized() + + @classmethod + def _register_osrandom_engine(cls): + # Clear any errors extant in the queue before we start. In many + # scenarios other things may be interacting with OpenSSL in the same + # process space and it has proven untenable to assume that they will + # reliably clear the error queue. Once we clear it here we will + # error on any subsequent unexpected item in the stack. + cls.lib.ERR_clear_error() + cls._osrandom_engine_id = cls.lib.Cryptography_osrandom_engine_id + cls._osrandom_engine_name = cls.lib.Cryptography_osrandom_engine_name + result = cls.lib.Cryptography_add_osrandom_engine() + _openssl_assert(cls.lib, result in (1, 2)) + + @classmethod + def _ensure_ffi_initialized(cls): + with cls._init_lock: + if not cls._lib_loaded: + cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES) + cls._lib_loaded = True + # initialize the SSL library + cls.lib.SSL_library_init() + # adds all ciphers/digests for EVP + cls.lib.OpenSSL_add_all_algorithms() + # loads error strings for libcrypto and libssl functions + cls.lib.SSL_load_error_strings() + cls._register_osrandom_engine() + + @classmethod + def init_static_locks(cls): + with cls._lock_init_lock: + cls._ensure_ffi_initialized() + # Use Python's implementation if available, importing _ssl triggers + # the setup for this. + __import__("_ssl") + + if cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL: + return + + # If nothing else has setup a locking callback already, we set up + # our own + res = lib.Cryptography_setup_ssl_threads() + _openssl_assert(cls.lib, res == 1) + + +# OpenSSL is not thread safe until the locks are initialized. We call this +# method in module scope so that it executes with the import lock. On +# Pythons < 3.4 this import lock is a global lock, which can prevent a race +# condition registering the OpenSSL locks. On Python 3.4+ the import lock +# is per module so this approach will not work. +Binding.init_static_locks() diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/__init__.py new file mode 100644 index 0000000..4b54088 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/__init__.py @@ -0,0 +1,5 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/__init__.py new file mode 100644 index 0000000..494a7a1 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/__init__.py @@ -0,0 +1,40 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + + +@six.add_metaclass(abc.ABCMeta) +class AsymmetricSignatureContext(object): + @abc.abstractmethod + def update(self, data): + """ + Processes the provided bytes and returns nothing. + """ + + @abc.abstractmethod + def finalize(self): + """ + Returns the signature as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class AsymmetricVerificationContext(object): + @abc.abstractmethod + def update(self, data): + """ + Processes the provided bytes and returns nothing. + """ + + @abc.abstractmethod + def verify(self): + """ + Raises an exception if the bytes provided to update do not match the + signature or the signature does not match the public key. + """ diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dh.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dh.py new file mode 100644 index 0000000..4fc9952 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dh.py @@ -0,0 +1,212 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography import utils + + +def generate_parameters(generator, key_size, backend): + return backend.generate_dh_parameters(generator, key_size) + + +class DHPrivateNumbers(object): + def __init__(self, x, public_numbers): + if not isinstance(x, six.integer_types): + raise TypeError("x must be an integer.") + + if not isinstance(public_numbers, DHPublicNumbers): + raise TypeError("public_numbers must be an instance of " + "DHPublicNumbers.") + + self._x = x + self._public_numbers = public_numbers + + def __eq__(self, other): + if not isinstance(other, DHPrivateNumbers): + return NotImplemented + + return ( + self._x == other._x and + self._public_numbers == other._public_numbers + ) + + def __ne__(self, other): + return not self == other + + def private_key(self, backend): + return backend.load_dh_private_numbers(self) + + public_numbers = utils.read_only_property("_public_numbers") + x = utils.read_only_property("_x") + + +class DHPublicNumbers(object): + def __init__(self, y, parameter_numbers): + if not isinstance(y, six.integer_types): + raise TypeError("y must be an integer.") + + if not isinstance(parameter_numbers, DHParameterNumbers): + raise TypeError( + "parameters must be an instance of DHParameterNumbers.") + + self._y = y + self._parameter_numbers = parameter_numbers + + def __eq__(self, other): + if not isinstance(other, DHPublicNumbers): + return NotImplemented + + return ( + self._y == other._y and + self._parameter_numbers == other._parameter_numbers + ) + + def __ne__(self, other): + return not self == other + + def public_key(self, backend): + return backend.load_dh_public_numbers(self) + + y = utils.read_only_property("_y") + parameter_numbers = utils.read_only_property("_parameter_numbers") + + +class DHParameterNumbers(object): + def __init__(self, p, g, q=None): + if ( + not isinstance(p, six.integer_types) or + not isinstance(g, six.integer_types) + ): + raise TypeError("p and g must be integers") + if q is not None and not isinstance(q, six.integer_types): + raise TypeError("q must be integer or None") + + if g < 2: + raise ValueError("DH generator must be 2 or greater") + + self._p = p + self._g = g + self._q = q + + def __eq__(self, other): + if not isinstance(other, DHParameterNumbers): + return NotImplemented + + return ( + self._p == other._p and + self._g == other._g and + self._q == other._q + ) + + def __ne__(self, other): + return not self == other + + def parameters(self, backend): + return backend.load_dh_parameter_numbers(self) + + p = utils.read_only_property("_p") + g = utils.read_only_property("_g") + q = utils.read_only_property("_q") + + +@six.add_metaclass(abc.ABCMeta) +class DHParameters(object): + @abc.abstractmethod + def generate_private_key(self): + """ + Generates and returns a DHPrivateKey. + """ + + @abc.abstractmethod + def parameter_bytes(self, encoding, format): + """ + Returns the parameters serialized as bytes. + """ + + @abc.abstractmethod + def parameter_numbers(self): + """ + Returns a DHParameterNumbers. + """ + + +DHParametersWithSerialization = DHParameters + + +@six.add_metaclass(abc.ABCMeta) +class DHPrivateKey(object): + @abc.abstractproperty + def key_size(self): + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def public_key(self): + """ + The DHPublicKey associated with this private key. + """ + + @abc.abstractmethod + def parameters(self): + """ + The DHParameters object associated with this private key. + """ + + @abc.abstractmethod + def exchange(self, peer_public_key): + """ + Given peer's DHPublicKey, carry out the key exchange and + return shared key as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DHPrivateKeyWithSerialization(DHPrivateKey): + @abc.abstractmethod + def private_numbers(self): + """ + Returns a DHPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes(self, encoding, format, encryption_algorithm): + """ + Returns the key serialized as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DHPublicKey(object): + @abc.abstractproperty + def key_size(self): + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def parameters(self): + """ + The DHParameters object associated with this public key. + """ + + @abc.abstractmethod + def public_numbers(self): + """ + Returns a DHPublicNumbers. + """ + + @abc.abstractmethod + def public_bytes(self, encoding, format): + """ + Returns the key serialized as bytes. + """ + + +DHPublicKeyWithSerialization = DHPublicKey diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dsa.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dsa.py new file mode 100644 index 0000000..e380a44 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -0,0 +1,254 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography import utils + + +@six.add_metaclass(abc.ABCMeta) +class DSAParameters(object): + @abc.abstractmethod + def generate_private_key(self): + """ + Generates and returns a DSAPrivateKey. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DSAParametersWithNumbers(DSAParameters): + @abc.abstractmethod + def parameter_numbers(self): + """ + Returns a DSAParameterNumbers. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DSAPrivateKey(object): + @abc.abstractproperty + def key_size(self): + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def public_key(self): + """ + The DSAPublicKey associated with this private key. + """ + + @abc.abstractmethod + def parameters(self): + """ + The DSAParameters object associated with this private key. + """ + + @abc.abstractmethod + def signer(self, signature_algorithm): + """ + Returns an AsymmetricSignatureContext used for signing data. + """ + + @abc.abstractmethod + def sign(self, data, algorithm): + """ + Signs the data + """ + + +@six.add_metaclass(abc.ABCMeta) +class DSAPrivateKeyWithSerialization(DSAPrivateKey): + @abc.abstractmethod + def private_numbers(self): + """ + Returns a DSAPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes(self, encoding, format, encryption_algorithm): + """ + Returns the key serialized as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class DSAPublicKey(object): + @abc.abstractproperty + def key_size(self): + """ + The bit length of the prime modulus. + """ + + @abc.abstractmethod + def parameters(self): + """ + The DSAParameters object associated with this public key. + """ + + @abc.abstractmethod + def verifier(self, signature, signature_algorithm): + """ + Returns an AsymmetricVerificationContext used for signing data. + """ + + @abc.abstractmethod + def public_numbers(self): + """ + Returns a DSAPublicNumbers. + """ + + @abc.abstractmethod + def public_bytes(self, encoding, format): + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify(self, signature, data, algorithm): + """ + Verifies the signature of the data. + """ + + +DSAPublicKeyWithSerialization = DSAPublicKey + + +def generate_parameters(key_size, backend): + return backend.generate_dsa_parameters(key_size) + + +def generate_private_key(key_size, backend): + return backend.generate_dsa_private_key_and_parameters(key_size) + + +def _check_dsa_parameters(parameters): + if parameters.p.bit_length() not in [1024, 2048, 3072]: + raise ValueError("p must be exactly 1024, 2048, or 3072 bits long") + if parameters.q.bit_length() not in [160, 224, 256]: + raise ValueError("q must be exactly 160, 224, or 256 bits long") + + if not (1 < parameters.g < parameters.p): + raise ValueError("g, p don't satisfy 1 < g < p.") + + +def _check_dsa_private_numbers(numbers): + parameters = numbers.public_numbers.parameter_numbers + _check_dsa_parameters(parameters) + if numbers.x <= 0 or numbers.x >= parameters.q: + raise ValueError("x must be > 0 and < q.") + + if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p): + raise ValueError("y must be equal to (g ** x % p).") + + +class DSAParameterNumbers(object): + def __init__(self, p, q, g): + if ( + not isinstance(p, six.integer_types) or + not isinstance(q, six.integer_types) or + not isinstance(g, six.integer_types) + ): + raise TypeError( + "DSAParameterNumbers p, q, and g arguments must be integers." + ) + + self._p = p + self._q = q + self._g = g + + p = utils.read_only_property("_p") + q = utils.read_only_property("_q") + g = utils.read_only_property("_g") + + def parameters(self, backend): + return backend.load_dsa_parameter_numbers(self) + + def __eq__(self, other): + if not isinstance(other, DSAParameterNumbers): + return NotImplemented + + return self.p == other.p and self.q == other.q and self.g == other.g + + def __ne__(self, other): + return not self == other + + def __repr__(self): + return ( + "".format( + self=self + ) + ) + + +class DSAPublicNumbers(object): + def __init__(self, y, parameter_numbers): + if not isinstance(y, six.integer_types): + raise TypeError("DSAPublicNumbers y argument must be an integer.") + + if not isinstance(parameter_numbers, DSAParameterNumbers): + raise TypeError( + "parameter_numbers must be a DSAParameterNumbers instance." + ) + + self._y = y + self._parameter_numbers = parameter_numbers + + y = utils.read_only_property("_y") + parameter_numbers = utils.read_only_property("_parameter_numbers") + + def public_key(self, backend): + return backend.load_dsa_public_numbers(self) + + def __eq__(self, other): + if not isinstance(other, DSAPublicNumbers): + return NotImplemented + + return ( + self.y == other.y and + self.parameter_numbers == other.parameter_numbers + ) + + def __ne__(self, other): + return not self == other + + def __repr__(self): + return ( + "".format(self=self) + ) + + +class DSAPrivateNumbers(object): + def __init__(self, x, public_numbers): + if not isinstance(x, six.integer_types): + raise TypeError("DSAPrivateNumbers x argument must be an integer.") + + if not isinstance(public_numbers, DSAPublicNumbers): + raise TypeError( + "public_numbers must be a DSAPublicNumbers instance." + ) + self._public_numbers = public_numbers + self._x = x + + x = utils.read_only_property("_x") + public_numbers = utils.read_only_property("_public_numbers") + + def private_key(self, backend): + return backend.load_dsa_private_numbers(self) + + def __eq__(self, other): + if not isinstance(other, DSAPrivateNumbers): + return NotImplemented + + return ( + self.x == other.x and self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/ec.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/ec.py new file mode 100644 index 0000000..6cbfcab --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/ec.py @@ -0,0 +1,411 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography import utils + + +@six.add_metaclass(abc.ABCMeta) +class EllipticCurve(object): + @abc.abstractproperty + def name(self): + """ + The name of the curve. e.g. secp256r1. + """ + + @abc.abstractproperty + def key_size(self): + """ + Bit size of a secret scalar for the curve. + """ + + +@six.add_metaclass(abc.ABCMeta) +class EllipticCurveSignatureAlgorithm(object): + @abc.abstractproperty + def algorithm(self): + """ + The digest algorithm used with this signature. + """ + + +@six.add_metaclass(abc.ABCMeta) +class EllipticCurvePrivateKey(object): + @abc.abstractmethod + def signer(self, signature_algorithm): + """ + Returns an AsymmetricSignatureContext used for signing data. + """ + + @abc.abstractmethod + def exchange(self, algorithm, peer_public_key): + """ + Performs a key exchange operation using the provided algorithm with the + provided peer's public key. + """ + + @abc.abstractmethod + def public_key(self): + """ + The EllipticCurvePublicKey for this private key. + """ + + @abc.abstractproperty + def curve(self): + """ + The EllipticCurve that this key is on. + """ + + @abc.abstractproperty + def key_size(self): + """ + Bit size of a secret scalar for the curve. + """ + + @abc.abstractproperty + def sign(self, data, signature_algorithm): + """ + Signs the data + """ + + +@six.add_metaclass(abc.ABCMeta) +class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey): + @abc.abstractmethod + def private_numbers(self): + """ + Returns an EllipticCurvePrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes(self, encoding, format, encryption_algorithm): + """ + Returns the key serialized as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class EllipticCurvePublicKey(object): + @abc.abstractmethod + def verifier(self, signature, signature_algorithm): + """ + Returns an AsymmetricVerificationContext used for signing data. + """ + + @abc.abstractproperty + def curve(self): + """ + The EllipticCurve that this key is on. + """ + + @abc.abstractproperty + def key_size(self): + """ + Bit size of a secret scalar for the curve. + """ + + @abc.abstractmethod + def public_numbers(self): + """ + Returns an EllipticCurvePublicNumbers. + """ + + @abc.abstractmethod + def public_bytes(self, encoding, format): + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify(self, signature, data, signature_algorithm): + """ + Verifies the signature of the data. + """ + + +EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey + + +@utils.register_interface(EllipticCurve) +class SECT571R1(object): + name = "sect571r1" + key_size = 570 + + +@utils.register_interface(EllipticCurve) +class SECT409R1(object): + name = "sect409r1" + key_size = 409 + + +@utils.register_interface(EllipticCurve) +class SECT283R1(object): + name = "sect283r1" + key_size = 283 + + +@utils.register_interface(EllipticCurve) +class SECT233R1(object): + name = "sect233r1" + key_size = 233 + + +@utils.register_interface(EllipticCurve) +class SECT163R2(object): + name = "sect163r2" + key_size = 163 + + +@utils.register_interface(EllipticCurve) +class SECT571K1(object): + name = "sect571k1" + key_size = 571 + + +@utils.register_interface(EllipticCurve) +class SECT409K1(object): + name = "sect409k1" + key_size = 409 + + +@utils.register_interface(EllipticCurve) +class SECT283K1(object): + name = "sect283k1" + key_size = 283 + + +@utils.register_interface(EllipticCurve) +class SECT233K1(object): + name = "sect233k1" + key_size = 233 + + +@utils.register_interface(EllipticCurve) +class SECT163K1(object): + name = "sect163k1" + key_size = 163 + + +@utils.register_interface(EllipticCurve) +class SECP521R1(object): + name = "secp521r1" + key_size = 521 + + +@utils.register_interface(EllipticCurve) +class SECP384R1(object): + name = "secp384r1" + key_size = 384 + + +@utils.register_interface(EllipticCurve) +class SECP256R1(object): + name = "secp256r1" + key_size = 256 + + +@utils.register_interface(EllipticCurve) +class SECP256K1(object): + name = "secp256k1" + key_size = 256 + + +@utils.register_interface(EllipticCurve) +class SECP224R1(object): + name = "secp224r1" + key_size = 224 + + +@utils.register_interface(EllipticCurve) +class SECP192R1(object): + name = "secp192r1" + key_size = 192 + + +@utils.register_interface(EllipticCurve) +class BrainpoolP256R1(object): + name = "brainpoolP256r1" + key_size = 256 + + +@utils.register_interface(EllipticCurve) +class BrainpoolP384R1(object): + name = "brainpoolP384r1" + key_size = 384 + + +@utils.register_interface(EllipticCurve) +class BrainpoolP512R1(object): + name = "brainpoolP512r1" + key_size = 512 + + +_CURVE_TYPES = { + "prime192v1": SECP192R1, + "prime256v1": SECP256R1, + + "secp192r1": SECP192R1, + "secp224r1": SECP224R1, + "secp256r1": SECP256R1, + "secp384r1": SECP384R1, + "secp521r1": SECP521R1, + "secp256k1": SECP256K1, + + "sect163k1": SECT163K1, + "sect233k1": SECT233K1, + "sect283k1": SECT283K1, + "sect409k1": SECT409K1, + "sect571k1": SECT571K1, + + "sect163r2": SECT163R2, + "sect233r1": SECT233R1, + "sect283r1": SECT283R1, + "sect409r1": SECT409R1, + "sect571r1": SECT571R1, + + "brainpoolP256r1": BrainpoolP256R1, + "brainpoolP384r1": BrainpoolP384R1, + "brainpoolP512r1": BrainpoolP512R1, +} + + +@utils.register_interface(EllipticCurveSignatureAlgorithm) +class ECDSA(object): + def __init__(self, algorithm): + self._algorithm = algorithm + + algorithm = utils.read_only_property("_algorithm") + + +def generate_private_key(curve, backend): + return backend.generate_elliptic_curve_private_key(curve) + + +def derive_private_key(private_value, curve, backend): + if not isinstance(private_value, six.integer_types): + raise TypeError("private_value must be an integer type.") + + if private_value <= 0: + raise ValueError("private_value must be a positive integer.") + + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must provide the EllipticCurve interface.") + + return backend.derive_elliptic_curve_private_key(private_value, curve) + + +class EllipticCurvePublicNumbers(object): + def __init__(self, x, y, curve): + if ( + not isinstance(x, six.integer_types) or + not isinstance(y, six.integer_types) + ): + raise TypeError("x and y must be integers.") + + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must provide the EllipticCurve interface.") + + self._y = y + self._x = x + self._curve = curve + + def public_key(self, backend): + return backend.load_elliptic_curve_public_numbers(self) + + def encode_point(self): + # key_size is in bits. Convert to bytes and round up + byte_length = (self.curve.key_size + 7) // 8 + return ( + b'\x04' + utils.int_to_bytes(self.x, byte_length) + + utils.int_to_bytes(self.y, byte_length) + ) + + @classmethod + def from_encoded_point(cls, curve, data): + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must be an EllipticCurve instance") + + if data.startswith(b'\x04'): + # key_size is in bits. Convert to bytes and round up + byte_length = (curve.key_size + 7) // 8 + if len(data) == 2 * byte_length + 1: + x = utils.int_from_bytes(data[1:byte_length + 1], 'big') + y = utils.int_from_bytes(data[byte_length + 1:], 'big') + return cls(x, y, curve) + else: + raise ValueError('Invalid elliptic curve point data length') + else: + raise ValueError('Unsupported elliptic curve point type') + + curve = utils.read_only_property("_curve") + x = utils.read_only_property("_x") + y = utils.read_only_property("_y") + + def __eq__(self, other): + if not isinstance(other, EllipticCurvePublicNumbers): + return NotImplemented + + return ( + self.x == other.x and + self.y == other.y and + self.curve.name == other.curve.name and + self.curve.key_size == other.curve.key_size + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.x, self.y, self.curve.name, self.curve.key_size)) + + def __repr__(self): + return ( + "".format(self) + ) + + +class EllipticCurvePrivateNumbers(object): + def __init__(self, private_value, public_numbers): + if not isinstance(private_value, six.integer_types): + raise TypeError("private_value must be an integer.") + + if not isinstance(public_numbers, EllipticCurvePublicNumbers): + raise TypeError( + "public_numbers must be an EllipticCurvePublicNumbers " + "instance." + ) + + self._private_value = private_value + self._public_numbers = public_numbers + + def private_key(self, backend): + return backend.load_elliptic_curve_private_numbers(self) + + private_value = utils.read_only_property("_private_value") + public_numbers = utils.read_only_property("_public_numbers") + + def __eq__(self, other): + if not isinstance(other, EllipticCurvePrivateNumbers): + return NotImplemented + + return ( + self.private_value == other.private_value and + self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.private_value, self.public_numbers)) + + +class ECDH(object): + pass diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/padding.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/padding.py new file mode 100644 index 0000000..a37c3f9 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/padding.py @@ -0,0 +1,79 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +import math + +import six + +from cryptography import utils +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import rsa + + +@six.add_metaclass(abc.ABCMeta) +class AsymmetricPadding(object): + @abc.abstractproperty + def name(self): + """ + A string naming this padding (e.g. "PSS", "PKCS1"). + """ + + +@utils.register_interface(AsymmetricPadding) +class PKCS1v15(object): + name = "EMSA-PKCS1-v1_5" + + +@utils.register_interface(AsymmetricPadding) +class PSS(object): + MAX_LENGTH = object() + name = "EMSA-PSS" + + def __init__(self, mgf, salt_length): + self._mgf = mgf + + if (not isinstance(salt_length, six.integer_types) and + salt_length is not self.MAX_LENGTH): + raise TypeError("salt_length must be an integer.") + + if salt_length is not self.MAX_LENGTH and salt_length < 0: + raise ValueError("salt_length must be zero or greater.") + + self._salt_length = salt_length + + +@utils.register_interface(AsymmetricPadding) +class OAEP(object): + name = "EME-OAEP" + + def __init__(self, mgf, algorithm, label): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + + self._mgf = mgf + self._algorithm = algorithm + self._label = label + + +class MGF1(object): + MAX_LENGTH = object() + + def __init__(self, algorithm): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + + self._algorithm = algorithm + + +def calculate_max_pss_salt_length(key, hash_algorithm): + if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): + raise TypeError("key must be an RSA public or private key") + # bit length - 1 per RFC 3447 + emlen = int(math.ceil((key.key_size - 1) / 8.0)) + salt_length = emlen - hash_algorithm.digest_size - 2 + assert salt_length >= 0 + return salt_length diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/rsa.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/rsa.py new file mode 100644 index 0000000..27db671 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -0,0 +1,368 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +try: + # Only available in math in 3.5+ + from math import gcd +except ImportError: + from fractions import gcd + +import six + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.hazmat.backends.interfaces import RSABackend + + +@six.add_metaclass(abc.ABCMeta) +class RSAPrivateKey(object): + @abc.abstractmethod + def signer(self, padding, algorithm): + """ + Returns an AsymmetricSignatureContext used for signing data. + """ + + @abc.abstractmethod + def decrypt(self, ciphertext, padding): + """ + Decrypts the provided ciphertext. + """ + + @abc.abstractproperty + def key_size(self): + """ + The bit length of the public modulus. + """ + + @abc.abstractmethod + def public_key(self): + """ + The RSAPublicKey associated with this private key. + """ + + @abc.abstractmethod + def sign(self, data, padding, algorithm): + """ + Signs the data. + """ + + +@six.add_metaclass(abc.ABCMeta) +class RSAPrivateKeyWithSerialization(RSAPrivateKey): + @abc.abstractmethod + def private_numbers(self): + """ + Returns an RSAPrivateNumbers. + """ + + @abc.abstractmethod + def private_bytes(self, encoding, format, encryption_algorithm): + """ + Returns the key serialized as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class RSAPublicKey(object): + @abc.abstractmethod + def verifier(self, signature, padding, algorithm): + """ + Returns an AsymmetricVerificationContext used for verifying signatures. + """ + + @abc.abstractmethod + def encrypt(self, plaintext, padding): + """ + Encrypts the given plaintext. + """ + + @abc.abstractproperty + def key_size(self): + """ + The bit length of the public modulus. + """ + + @abc.abstractmethod + def public_numbers(self): + """ + Returns an RSAPublicNumbers + """ + + @abc.abstractmethod + def public_bytes(self, encoding, format): + """ + Returns the key serialized as bytes. + """ + + @abc.abstractmethod + def verify(self, signature, data, padding, algorithm): + """ + Verifies the signature of the data. + """ + + +RSAPublicKeyWithSerialization = RSAPublicKey + + +def generate_private_key(public_exponent, key_size, backend): + if not isinstance(backend, RSABackend): + raise UnsupportedAlgorithm( + "Backend object does not implement RSABackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + _verify_rsa_parameters(public_exponent, key_size) + return backend.generate_rsa_private_key(public_exponent, key_size) + + +def _verify_rsa_parameters(public_exponent, key_size): + if public_exponent < 3: + raise ValueError("public_exponent must be >= 3.") + + if public_exponent & 1 == 0: + raise ValueError("public_exponent must be odd.") + + if key_size < 512: + raise ValueError("key_size must be at least 512-bits.") + + +def _check_private_key_components(p, q, private_exponent, dmp1, dmq1, iqmp, + public_exponent, modulus): + if modulus < 3: + raise ValueError("modulus must be >= 3.") + + if p >= modulus: + raise ValueError("p must be < modulus.") + + if q >= modulus: + raise ValueError("q must be < modulus.") + + if dmp1 >= modulus: + raise ValueError("dmp1 must be < modulus.") + + if dmq1 >= modulus: + raise ValueError("dmq1 must be < modulus.") + + if iqmp >= modulus: + raise ValueError("iqmp must be < modulus.") + + if private_exponent >= modulus: + raise ValueError("private_exponent must be < modulus.") + + if public_exponent < 3 or public_exponent >= modulus: + raise ValueError("public_exponent must be >= 3 and < modulus.") + + if public_exponent & 1 == 0: + raise ValueError("public_exponent must be odd.") + + if dmp1 & 1 == 0: + raise ValueError("dmp1 must be odd.") + + if dmq1 & 1 == 0: + raise ValueError("dmq1 must be odd.") + + if p * q != modulus: + raise ValueError("p*q must equal modulus.") + + +def _check_public_key_components(e, n): + if n < 3: + raise ValueError("n must be >= 3.") + + if e < 3 or e >= n: + raise ValueError("e must be >= 3 and < n.") + + if e & 1 == 0: + raise ValueError("e must be odd.") + + +def _modinv(e, m): + """ + Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1 + """ + x1, y1, x2, y2 = 1, 0, 0, 1 + a, b = e, m + while b > 0: + q, r = divmod(a, b) + xn, yn = x1 - q * x2, y1 - q * y2 + a, b, x1, y1, x2, y2 = b, r, x2, y2, xn, yn + return x1 % m + + +def rsa_crt_iqmp(p, q): + """ + Compute the CRT (q ** -1) % p value from RSA primes p and q. + """ + return _modinv(q, p) + + +def rsa_crt_dmp1(private_exponent, p): + """ + Compute the CRT private_exponent % (p - 1) value from the RSA + private_exponent (d) and p. + """ + return private_exponent % (p - 1) + + +def rsa_crt_dmq1(private_exponent, q): + """ + Compute the CRT private_exponent % (q - 1) value from the RSA + private_exponent (d) and q. + """ + return private_exponent % (q - 1) + + +# Controls the number of iterations rsa_recover_prime_factors will perform +# to obtain the prime factors. Each iteration increments by 2 so the actual +# maximum attempts is half this number. +_MAX_RECOVERY_ATTEMPTS = 1000 + + +def rsa_recover_prime_factors(n, e, d): + """ + Compute factors p and q from the private exponent d. We assume that n has + no more than two factors. This function is adapted from code in PyCrypto. + """ + # See 8.2.2(i) in Handbook of Applied Cryptography. + ktot = d * e - 1 + # The quantity d*e-1 is a multiple of phi(n), even, + # and can be represented as t*2^s. + t = ktot + while t % 2 == 0: + t = t // 2 + # Cycle through all multiplicative inverses in Zn. + # The algorithm is non-deterministic, but there is a 50% chance + # any candidate a leads to successful factoring. + # See "Digitalized Signatures and Public Key Functions as Intractable + # as Factorization", M. Rabin, 1979 + spotted = False + a = 2 + while not spotted and a < _MAX_RECOVERY_ATTEMPTS: + k = t + # Cycle through all values a^{t*2^i}=a^k + while k < ktot: + cand = pow(a, k, n) + # Check if a^k is a non-trivial root of unity (mod n) + if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: + # We have found a number such that (cand-1)(cand+1)=0 (mod n). + # Either of the terms divides n. + p = gcd(cand + 1, n) + spotted = True + break + k *= 2 + # This value was not any good... let's try another! + a += 2 + if not spotted: + raise ValueError("Unable to compute factors p and q from exponent d.") + # Found ! + q, r = divmod(n, p) + assert r == 0 + p, q = sorted((p, q), reverse=True) + return (p, q) + + +class RSAPrivateNumbers(object): + def __init__(self, p, q, d, dmp1, dmq1, iqmp, + public_numbers): + if ( + not isinstance(p, six.integer_types) or + not isinstance(q, six.integer_types) or + not isinstance(d, six.integer_types) or + not isinstance(dmp1, six.integer_types) or + not isinstance(dmq1, six.integer_types) or + not isinstance(iqmp, six.integer_types) + ): + raise TypeError( + "RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must" + " all be an integers." + ) + + if not isinstance(public_numbers, RSAPublicNumbers): + raise TypeError( + "RSAPrivateNumbers public_numbers must be an RSAPublicNumbers" + " instance." + ) + + self._p = p + self._q = q + self._d = d + self._dmp1 = dmp1 + self._dmq1 = dmq1 + self._iqmp = iqmp + self._public_numbers = public_numbers + + p = utils.read_only_property("_p") + q = utils.read_only_property("_q") + d = utils.read_only_property("_d") + dmp1 = utils.read_only_property("_dmp1") + dmq1 = utils.read_only_property("_dmq1") + iqmp = utils.read_only_property("_iqmp") + public_numbers = utils.read_only_property("_public_numbers") + + def private_key(self, backend): + return backend.load_rsa_private_numbers(self) + + def __eq__(self, other): + if not isinstance(other, RSAPrivateNumbers): + return NotImplemented + + return ( + self.p == other.p and + self.q == other.q and + self.d == other.d and + self.dmp1 == other.dmp1 and + self.dmq1 == other.dmq1 and + self.iqmp == other.iqmp and + self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(( + self.p, + self.q, + self.d, + self.dmp1, + self.dmq1, + self.iqmp, + self.public_numbers, + )) + + +class RSAPublicNumbers(object): + def __init__(self, e, n): + if ( + not isinstance(e, six.integer_types) or + not isinstance(n, six.integer_types) + ): + raise TypeError("RSAPublicNumbers arguments must be integers.") + + self._e = e + self._n = n + + e = utils.read_only_property("_e") + n = utils.read_only_property("_n") + + def public_key(self, backend): + return backend.load_rsa_public_numbers(self) + + def __repr__(self): + return "".format(self) + + def __eq__(self, other): + if not isinstance(other, RSAPublicNumbers): + return NotImplemented + + return self.e == other.e and self.n == other.n + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.e, self.n)) diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/utils.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/utils.py new file mode 100644 index 0000000..ef1e7eb --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/utils.py @@ -0,0 +1,60 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import warnings + +from asn1crypto.algos import DSASignature + +import six + +from cryptography import utils +from cryptography.hazmat.primitives import hashes + + +def decode_rfc6979_signature(signature): + warnings.warn( + "decode_rfc6979_signature is deprecated and will " + "be removed in a future version, use decode_dss_signature instead.", + utils.PersistentlyDeprecated, + stacklevel=2 + ) + return decode_dss_signature(signature) + + +def decode_dss_signature(signature): + data = DSASignature.load(signature, strict=True).native + return data['r'], data['s'] + + +def encode_rfc6979_signature(r, s): + warnings.warn( + "encode_rfc6979_signature is deprecated and will " + "be removed in a future version, use encode_dss_signature instead.", + utils.PersistentlyDeprecated, + stacklevel=2 + ) + return encode_dss_signature(r, s) + + +def encode_dss_signature(r, s): + if ( + not isinstance(r, six.integer_types) or + not isinstance(s, six.integer_types) + ): + raise ValueError("Both r and s must be integers") + + return DSASignature({'r': r, 's': s}).dump() + + +class Prehashed(object): + def __init__(self, algorithm): + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of HashAlgorithm.") + + self._algorithm = algorithm + self._digest_size = algorithm.digest_size + + digest_size = utils.read_only_property("_digest_size") diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/x25519.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/x25519.py new file mode 100644 index 0000000..5c4652a --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/asymmetric/x25519.py @@ -0,0 +1,54 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons + + +@six.add_metaclass(abc.ABCMeta) +class X25519PublicKey(object): + @classmethod + def from_public_bytes(cls, data): + from cryptography.hazmat.backends.openssl.backend import backend + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + return backend.x25519_load_public_bytes(data) + + @abc.abstractmethod + def public_bytes(self): + pass + + +@six.add_metaclass(abc.ABCMeta) +class X25519PrivateKey(object): + @classmethod + def generate(cls): + from cryptography.hazmat.backends.openssl.backend import backend + if not backend.x25519_supported(): + raise UnsupportedAlgorithm( + "X25519 is not supported by this version of OpenSSL.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + return backend.x25519_generate_key() + + @classmethod + def _from_private_bytes(cls, data): + from cryptography.hazmat.backends.openssl.backend import backend + return backend.x25519_load_private_bytes(data) + + @abc.abstractmethod + def public_key(self): + pass + + @abc.abstractmethod + def exchange(self, peer_public_key): + pass diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/__init__.py new file mode 100644 index 0000000..171b1c6 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/__init__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography.hazmat.primitives.ciphers.base import ( + AEADCipherContext, AEADDecryptionContext, AEADEncryptionContext, + BlockCipherAlgorithm, Cipher, CipherAlgorithm, CipherContext +) + + +__all__ = [ + "Cipher", + "CipherAlgorithm", + "BlockCipherAlgorithm", + "CipherContext", + "AEADCipherContext", + "AEADDecryptionContext", + "AEADEncryptionContext", +] diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/aead.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/aead.py new file mode 100644 index 0000000..e519765 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/aead.py @@ -0,0 +1,188 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import os + +from cryptography import exceptions, utils +from cryptography.hazmat.backends.openssl import aead +from cryptography.hazmat.backends.openssl.backend import backend + + +class ChaCha20Poly1305(object): + _MAX_SIZE = 2 ** 32 + + def __init__(self, key): + if not backend.aead_cipher_supported(self): + raise exceptions.UnsupportedAlgorithm( + "ChaCha20Poly1305 is not supported by this version of OpenSSL", + exceptions._Reasons.UNSUPPORTED_CIPHER + ) + utils._check_bytes("key", key) + + if len(key) != 32: + raise ValueError("ChaCha20Poly1305 key must be 32 bytes.") + + self._key = key + + @classmethod + def generate_key(cls): + return os.urandom(32) + + def encrypt(self, nonce, data, associated_data): + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + + self._check_params(nonce, data, associated_data) + return aead._encrypt( + backend, self, nonce, data, associated_data, 16 + ) + + def decrypt(self, nonce, data, associated_data): + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt( + backend, self, nonce, data, associated_data, 16 + ) + + def _check_params(self, nonce, data, associated_data): + utils._check_bytes("nonce", nonce) + utils._check_bytes("data", data) + utils._check_bytes("associated_data", associated_data) + if len(nonce) != 12: + raise ValueError("Nonce must be 12 bytes") + + +class AESCCM(object): + _MAX_SIZE = 2 ** 32 + + def __init__(self, key, tag_length=16): + utils._check_bytes("key", key) + if len(key) not in (16, 24, 32): + raise ValueError("AESCCM key must be 128, 192, or 256 bits.") + + self._key = key + if not isinstance(tag_length, int): + raise TypeError("tag_length must be an integer") + + if tag_length not in (4, 6, 8, 12, 14, 16): + raise ValueError("Invalid tag_length") + + self._tag_length = tag_length + + if not backend.aead_cipher_supported(self): + raise exceptions.UnsupportedAlgorithm( + "AESCCM is not supported by this version of OpenSSL", + exceptions._Reasons.UNSUPPORTED_CIPHER + ) + + @classmethod + def generate_key(cls, bit_length): + if not isinstance(bit_length, int): + raise TypeError("bit_length must be an integer") + + if bit_length not in (128, 192, 256): + raise ValueError("bit_length must be 128, 192, or 256") + + return os.urandom(bit_length // 8) + + def encrypt(self, nonce, data, associated_data): + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + + self._check_params(nonce, data, associated_data) + self._validate_lengths(nonce, len(data)) + return aead._encrypt( + backend, self, nonce, data, associated_data, self._tag_length + ) + + def decrypt(self, nonce, data, associated_data): + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt( + backend, self, nonce, data, associated_data, self._tag_length + ) + + def _validate_lengths(self, nonce, data_len): + # For information about computing this, see + # https://tools.ietf.org/html/rfc3610#section-2.1 + l_val = 15 - len(nonce) + if 2 ** (8 * l_val) < data_len: + raise ValueError("Nonce too long for data") + + def _check_params(self, nonce, data, associated_data): + utils._check_bytes("nonce", nonce) + utils._check_bytes("data", data) + utils._check_bytes("associated_data", associated_data) + if not 7 <= len(nonce) <= 13: + raise ValueError("Nonce must be between 7 and 13 bytes") + + +class AESGCM(object): + _MAX_SIZE = 2 ** 32 + + def __init__(self, key): + utils._check_bytes("key", key) + if len(key) not in (16, 24, 32): + raise ValueError("AESGCM key must be 128, 192, or 256 bits.") + + self._key = key + + @classmethod + def generate_key(cls, bit_length): + if not isinstance(bit_length, int): + raise TypeError("bit_length must be an integer") + + if bit_length not in (128, 192, 256): + raise ValueError("bit_length must be 128, 192, or 256") + + return os.urandom(bit_length // 8) + + def encrypt(self, nonce, data, associated_data): + if associated_data is None: + associated_data = b"" + + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + + self._check_params(nonce, data, associated_data) + return aead._encrypt( + backend, self, nonce, data, associated_data, 16 + ) + + def decrypt(self, nonce, data, associated_data): + if associated_data is None: + associated_data = b"" + + self._check_params(nonce, data, associated_data) + return aead._decrypt( + backend, self, nonce, data, associated_data, 16 + ) + + def _check_params(self, nonce, data, associated_data): + utils._check_bytes("nonce", nonce) + utils._check_bytes("data", data) + utils._check_bytes("associated_data", associated_data) + if len(nonce) == 0: + raise ValueError("Nonce must be at least 1 byte") diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/algorithms.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/algorithms.py new file mode 100644 index 0000000..68a9e33 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -0,0 +1,168 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.hazmat.primitives.ciphers import ( + BlockCipherAlgorithm, CipherAlgorithm +) +from cryptography.hazmat.primitives.ciphers.modes import ModeWithNonce + + +def _verify_key_size(algorithm, key): + # Verify that the key is instance of bytes + utils._check_bytes("key", key) + + # Verify that the key size matches the expected key size + if len(key) * 8 not in algorithm.key_sizes: + raise ValueError("Invalid key size ({0}) for {1}.".format( + len(key) * 8, algorithm.name + )) + return key + + +@utils.register_interface(BlockCipherAlgorithm) +@utils.register_interface(CipherAlgorithm) +class AES(object): + name = "AES" + block_size = 128 + # 512 added to support AES-256-XTS, which uses 512-bit keys + key_sizes = frozenset([128, 192, 256, 512]) + + def __init__(self, key): + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(BlockCipherAlgorithm) +@utils.register_interface(CipherAlgorithm) +class Camellia(object): + name = "camellia" + block_size = 128 + key_sizes = frozenset([128, 192, 256]) + + def __init__(self, key): + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(BlockCipherAlgorithm) +@utils.register_interface(CipherAlgorithm) +class TripleDES(object): + name = "3DES" + block_size = 64 + key_sizes = frozenset([64, 128, 192]) + + def __init__(self, key): + if len(key) == 8: + key += key + key + elif len(key) == 16: + key += key[:8] + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(BlockCipherAlgorithm) +@utils.register_interface(CipherAlgorithm) +class Blowfish(object): + name = "Blowfish" + block_size = 64 + key_sizes = frozenset(range(32, 449, 8)) + + def __init__(self, key): + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(BlockCipherAlgorithm) +@utils.register_interface(CipherAlgorithm) +class CAST5(object): + name = "CAST5" + block_size = 64 + key_sizes = frozenset(range(40, 129, 8)) + + def __init__(self, key): + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(CipherAlgorithm) +class ARC4(object): + name = "RC4" + key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256]) + + def __init__(self, key): + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(CipherAlgorithm) +class IDEA(object): + name = "IDEA" + block_size = 64 + key_sizes = frozenset([128]) + + def __init__(self, key): + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(BlockCipherAlgorithm) +@utils.register_interface(CipherAlgorithm) +class SEED(object): + name = "SEED" + block_size = 128 + key_sizes = frozenset([128]) + + def __init__(self, key): + self.key = _verify_key_size(self, key) + + @property + def key_size(self): + return len(self.key) * 8 + + +@utils.register_interface(CipherAlgorithm) +@utils.register_interface(ModeWithNonce) +class ChaCha20(object): + name = "ChaCha20" + key_sizes = frozenset([256]) + + def __init__(self, key, nonce): + self.key = _verify_key_size(self, key) + if not isinstance(nonce, bytes): + raise TypeError("nonce must be bytes") + + if len(nonce) != 16: + raise ValueError("nonce must be 128-bits (16 bytes)") + + self._nonce = nonce + + nonce = utils.read_only_property("_nonce") + + @property + def key_size(self): + return len(self.key) * 8 diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/base.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/base.py new file mode 100644 index 0000000..f857041 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/base.py @@ -0,0 +1,235 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, AlreadyUpdated, NotYetFinalized, UnsupportedAlgorithm, + _Reasons +) +from cryptography.hazmat.backends.interfaces import CipherBackend +from cryptography.hazmat.primitives.ciphers import modes + + +@six.add_metaclass(abc.ABCMeta) +class CipherAlgorithm(object): + @abc.abstractproperty + def name(self): + """ + A string naming this mode (e.g. "AES", "Camellia"). + """ + + @abc.abstractproperty + def key_size(self): + """ + The size of the key being used as an integer in bits (e.g. 128, 256). + """ + + +@six.add_metaclass(abc.ABCMeta) +class BlockCipherAlgorithm(object): + @abc.abstractproperty + def block_size(self): + """ + The size of a block as an integer in bits (e.g. 64, 128). + """ + + +@six.add_metaclass(abc.ABCMeta) +class CipherContext(object): + @abc.abstractmethod + def update(self, data): + """ + Processes the provided bytes through the cipher and returns the results + as bytes. + """ + + @abc.abstractmethod + def update_into(self, data, buf): + """ + Processes the provided bytes and writes the resulting data into the + provided buffer. Returns the number of bytes written. + """ + + @abc.abstractmethod + def finalize(self): + """ + Returns the results of processing the final block as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class AEADCipherContext(object): + @abc.abstractmethod + def authenticate_additional_data(self, data): + """ + Authenticates the provided bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class AEADDecryptionContext(object): + @abc.abstractmethod + def finalize_with_tag(self, tag): + """ + Returns the results of processing the final block as bytes and allows + delayed passing of the authentication tag. + """ + + +@six.add_metaclass(abc.ABCMeta) +class AEADEncryptionContext(object): + @abc.abstractproperty + def tag(self): + """ + Returns tag bytes. This is only available after encryption is + finalized. + """ + + +class Cipher(object): + def __init__(self, algorithm, mode, backend): + if not isinstance(backend, CipherBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement CipherBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + if not isinstance(algorithm, CipherAlgorithm): + raise TypeError("Expected interface of CipherAlgorithm.") + + if mode is not None: + mode.validate_for_algorithm(algorithm) + + self.algorithm = algorithm + self.mode = mode + self._backend = backend + + def encryptor(self): + if isinstance(self.mode, modes.ModeWithAuthenticationTag): + if self.mode.tag is not None: + raise ValueError( + "Authentication tag must be None when encrypting." + ) + ctx = self._backend.create_symmetric_encryption_ctx( + self.algorithm, self.mode + ) + return self._wrap_ctx(ctx, encrypt=True) + + def decryptor(self): + ctx = self._backend.create_symmetric_decryption_ctx( + self.algorithm, self.mode + ) + return self._wrap_ctx(ctx, encrypt=False) + + def _wrap_ctx(self, ctx, encrypt): + if isinstance(self.mode, modes.ModeWithAuthenticationTag): + if encrypt: + return _AEADEncryptionContext(ctx) + else: + return _AEADCipherContext(ctx) + else: + return _CipherContext(ctx) + + +@utils.register_interface(CipherContext) +class _CipherContext(object): + def __init__(self, ctx): + self._ctx = ctx + + def update(self, data): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return self._ctx.update(data) + + def update_into(self, data, buf): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return self._ctx.update_into(data, buf) + + def finalize(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize() + self._ctx = None + return data + + +@utils.register_interface(AEADCipherContext) +@utils.register_interface(CipherContext) +@utils.register_interface(AEADDecryptionContext) +class _AEADCipherContext(object): + def __init__(self, ctx): + self._ctx = ctx + self._bytes_processed = 0 + self._aad_bytes_processed = 0 + self._tag = None + self._updated = False + + def _check_limit(self, data_size): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + self._updated = True + self._bytes_processed += data_size + if self._bytes_processed > self._ctx._mode._MAX_ENCRYPTED_BYTES: + raise ValueError( + "{0} has a maximum encrypted byte limit of {1}".format( + self._ctx._mode.name, self._ctx._mode._MAX_ENCRYPTED_BYTES + ) + ) + + def update(self, data): + self._check_limit(len(data)) + return self._ctx.update(data) + + def update_into(self, data, buf): + self._check_limit(len(data)) + return self._ctx.update_into(data, buf) + + def finalize(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize() + self._tag = self._ctx.tag + self._ctx = None + return data + + def finalize_with_tag(self, tag): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + data = self._ctx.finalize_with_tag(tag) + self._tag = self._ctx.tag + self._ctx = None + return data + + def authenticate_additional_data(self, data): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + if self._updated: + raise AlreadyUpdated("Update has been called on this context.") + + self._aad_bytes_processed += len(data) + if self._aad_bytes_processed > self._ctx._mode._MAX_AAD_BYTES: + raise ValueError( + "{0} has a maximum AAD byte limit of {1}".format( + self._ctx._mode.name, self._ctx._mode._MAX_AAD_BYTES + ) + ) + + self._ctx.authenticate_additional_data(data) + + +@utils.register_interface(AEADEncryptionContext) +class _AEADEncryptionContext(_AEADCipherContext): + @property + def tag(self): + if self._ctx is not None: + raise NotYetFinalized("You must finalize encryption before " + "getting the tag.") + return self._tag diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/modes.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/modes.py new file mode 100644 index 0000000..e82c1a8 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/ciphers/modes.py @@ -0,0 +1,231 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography import utils + + +@six.add_metaclass(abc.ABCMeta) +class Mode(object): + @abc.abstractproperty + def name(self): + """ + A string naming this mode (e.g. "ECB", "CBC"). + """ + + @abc.abstractmethod + def validate_for_algorithm(self, algorithm): + """ + Checks that all the necessary invariants of this (mode, algorithm) + combination are met. + """ + + +@six.add_metaclass(abc.ABCMeta) +class ModeWithInitializationVector(object): + @abc.abstractproperty + def initialization_vector(self): + """ + The value of the initialization vector for this mode as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class ModeWithTweak(object): + @abc.abstractproperty + def tweak(self): + """ + The value of the tweak for this mode as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class ModeWithNonce(object): + @abc.abstractproperty + def nonce(self): + """ + The value of the nonce for this mode as bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class ModeWithAuthenticationTag(object): + @abc.abstractproperty + def tag(self): + """ + The value of the tag supplied to the constructor of this mode. + """ + + +def _check_aes_key_length(self, algorithm): + if algorithm.key_size > 256 and algorithm.name == "AES": + raise ValueError( + "Only 128, 192, and 256 bit keys are allowed for this AES mode" + ) + + +def _check_iv_length(self, algorithm): + if len(self.initialization_vector) * 8 != algorithm.block_size: + raise ValueError("Invalid IV size ({0}) for {1}.".format( + len(self.initialization_vector), self.name + )) + + +def _check_iv_and_key_length(self, algorithm): + _check_aes_key_length(self, algorithm) + _check_iv_length(self, algorithm) + + +@utils.register_interface(Mode) +@utils.register_interface(ModeWithInitializationVector) +class CBC(object): + name = "CBC" + + def __init__(self, initialization_vector): + if not isinstance(initialization_vector, bytes): + raise TypeError("initialization_vector must be bytes") + + self._initialization_vector = initialization_vector + + initialization_vector = utils.read_only_property("_initialization_vector") + validate_for_algorithm = _check_iv_and_key_length + + +@utils.register_interface(Mode) +@utils.register_interface(ModeWithTweak) +class XTS(object): + name = "XTS" + + def __init__(self, tweak): + if not isinstance(tweak, bytes): + raise TypeError("tweak must be bytes") + + if len(tweak) != 16: + raise ValueError("tweak must be 128-bits (16 bytes)") + + self._tweak = tweak + + tweak = utils.read_only_property("_tweak") + + def validate_for_algorithm(self, algorithm): + if algorithm.key_size not in (256, 512): + raise ValueError( + "The XTS specification requires a 256-bit key for AES-128-XTS" + " and 512-bit key for AES-256-XTS" + ) + + +@utils.register_interface(Mode) +class ECB(object): + name = "ECB" + + validate_for_algorithm = _check_aes_key_length + + +@utils.register_interface(Mode) +@utils.register_interface(ModeWithInitializationVector) +class OFB(object): + name = "OFB" + + def __init__(self, initialization_vector): + if not isinstance(initialization_vector, bytes): + raise TypeError("initialization_vector must be bytes") + + self._initialization_vector = initialization_vector + + initialization_vector = utils.read_only_property("_initialization_vector") + validate_for_algorithm = _check_iv_and_key_length + + +@utils.register_interface(Mode) +@utils.register_interface(ModeWithInitializationVector) +class CFB(object): + name = "CFB" + + def __init__(self, initialization_vector): + if not isinstance(initialization_vector, bytes): + raise TypeError("initialization_vector must be bytes") + + self._initialization_vector = initialization_vector + + initialization_vector = utils.read_only_property("_initialization_vector") + validate_for_algorithm = _check_iv_and_key_length + + +@utils.register_interface(Mode) +@utils.register_interface(ModeWithInitializationVector) +class CFB8(object): + name = "CFB8" + + def __init__(self, initialization_vector): + if not isinstance(initialization_vector, bytes): + raise TypeError("initialization_vector must be bytes") + + self._initialization_vector = initialization_vector + + initialization_vector = utils.read_only_property("_initialization_vector") + validate_for_algorithm = _check_iv_and_key_length + + +@utils.register_interface(Mode) +@utils.register_interface(ModeWithNonce) +class CTR(object): + name = "CTR" + + def __init__(self, nonce): + if not isinstance(nonce, bytes): + raise TypeError("nonce must be bytes") + + self._nonce = nonce + + nonce = utils.read_only_property("_nonce") + + def validate_for_algorithm(self, algorithm): + _check_aes_key_length(self, algorithm) + if len(self.nonce) * 8 != algorithm.block_size: + raise ValueError("Invalid nonce size ({0}) for {1}.".format( + len(self.nonce), self.name + )) + + +@utils.register_interface(Mode) +@utils.register_interface(ModeWithInitializationVector) +@utils.register_interface(ModeWithAuthenticationTag) +class GCM(object): + name = "GCM" + _MAX_ENCRYPTED_BYTES = (2 ** 39 - 256) // 8 + _MAX_AAD_BYTES = (2 ** 64) // 8 + + def __init__(self, initialization_vector, tag=None, min_tag_length=16): + # len(initialization_vector) must in [1, 2 ** 64), but it's impossible + # to actually construct a bytes object that large, so we don't check + # for it + if not isinstance(initialization_vector, bytes): + raise TypeError("initialization_vector must be bytes") + if len(initialization_vector) == 0: + raise ValueError("initialization_vector must be at least 1 byte") + self._initialization_vector = initialization_vector + if tag is not None: + if not isinstance(tag, bytes): + raise TypeError("tag must be bytes or None") + if min_tag_length < 4: + raise ValueError("min_tag_length must be >= 4") + if len(tag) < min_tag_length: + raise ValueError( + "Authentication tag must be {0} bytes or longer.".format( + min_tag_length) + ) + self._tag = tag + self._min_tag_length = min_tag_length + + tag = utils.read_only_property("_tag") + initialization_vector = utils.read_only_property("_initialization_vector") + + def validate_for_algorithm(self, algorithm): + _check_aes_key_length(self, algorithm) diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/cmac.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/cmac.py new file mode 100644 index 0000000..77537f0 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/cmac.py @@ -0,0 +1,66 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import CMACBackend +from cryptography.hazmat.primitives import ciphers, mac + + +@utils.register_interface(mac.MACContext) +class CMAC(object): + def __init__(self, algorithm, backend, ctx=None): + if not isinstance(backend, CMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement CMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + if not isinstance(algorithm, ciphers.BlockCipherAlgorithm): + raise TypeError( + "Expected instance of BlockCipherAlgorithm." + ) + self._algorithm = algorithm + + self._backend = backend + if ctx is None: + self._ctx = self._backend.create_cmac_ctx(self._algorithm) + else: + self._ctx = ctx + + def update(self, data): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") + self._ctx.update(data) + + def finalize(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + digest = self._ctx.finalize() + self._ctx = None + return digest + + def verify(self, signature): + if not isinstance(signature, bytes): + raise TypeError("signature must be bytes.") + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + + ctx, self._ctx = self._ctx, None + ctx.verify(signature) + + def copy(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return CMAC( + self._algorithm, + backend=self._backend, + ctx=self._ctx.copy() + ) diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/constant_time.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/constant_time.py new file mode 100644 index 0000000..0e987ea --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/constant_time.py @@ -0,0 +1,35 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import hmac +import warnings + +from cryptography import utils +from cryptography.hazmat.bindings._constant_time import lib + + +if hasattr(hmac, "compare_digest"): + def bytes_eq(a, b): + if not isinstance(a, bytes) or not isinstance(b, bytes): + raise TypeError("a and b must be bytes.") + + return hmac.compare_digest(a, b) + +else: + warnings.warn( + "Support for your Python version is deprecated. The next version of " + "cryptography will remove support. Please upgrade to a 2.7.x " + "release that supports hmac.compare_digest as soon as possible.", + utils.DeprecatedIn23, + ) + + def bytes_eq(a, b): + if not isinstance(a, bytes) or not isinstance(b, bytes): + raise TypeError("a and b must be bytes.") + + return lib.Cryptography_constant_time_bytes_eq( + a, len(a), b, len(b) + ) == 1 diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/hashes.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/hashes.py new file mode 100644 index 0000000..3f3aadd --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/hashes.py @@ -0,0 +1,185 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HashBackend + + +@six.add_metaclass(abc.ABCMeta) +class HashAlgorithm(object): + @abc.abstractproperty + def name(self): + """ + A string naming this algorithm (e.g. "sha256", "md5"). + """ + + @abc.abstractproperty + def digest_size(self): + """ + The size of the resulting digest in bytes. + """ + + +@six.add_metaclass(abc.ABCMeta) +class HashContext(object): + @abc.abstractproperty + def algorithm(self): + """ + A HashAlgorithm that will be used by this context. + """ + + @abc.abstractmethod + def update(self, data): + """ + Processes the provided bytes through the hash. + """ + + @abc.abstractmethod + def finalize(self): + """ + Finalizes the hash context and returns the hash digest as bytes. + """ + + @abc.abstractmethod + def copy(self): + """ + Return a HashContext that is a copy of the current context. + """ + + +@utils.register_interface(HashContext) +class Hash(object): + def __init__(self, algorithm, backend, ctx=None): + if not isinstance(backend, HashBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HashBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + if not isinstance(algorithm, HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + self._algorithm = algorithm + + self._backend = backend + + if ctx is None: + self._ctx = self._backend.create_hash_ctx(self.algorithm) + else: + self._ctx = ctx + + algorithm = utils.read_only_property("_algorithm") + + def update(self, data): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") + self._ctx.update(data) + + def copy(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return Hash( + self.algorithm, backend=self._backend, ctx=self._ctx.copy() + ) + + def finalize(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + digest = self._ctx.finalize() + self._ctx = None + return digest + + +@utils.register_interface(HashAlgorithm) +class SHA1(object): + name = "sha1" + digest_size = 20 + block_size = 64 + + +@utils.register_interface(HashAlgorithm) +class SHA224(object): + name = "sha224" + digest_size = 28 + block_size = 64 + + +@utils.register_interface(HashAlgorithm) +class SHA256(object): + name = "sha256" + digest_size = 32 + block_size = 64 + + +@utils.register_interface(HashAlgorithm) +class SHA384(object): + name = "sha384" + digest_size = 48 + block_size = 128 + + +@utils.register_interface(HashAlgorithm) +class SHA512(object): + name = "sha512" + digest_size = 64 + block_size = 128 + + +@utils.register_interface(HashAlgorithm) +class MD5(object): + name = "md5" + digest_size = 16 + block_size = 64 + + +@utils.register_interface(HashAlgorithm) +class BLAKE2b(object): + name = "blake2b" + _max_digest_size = 64 + _min_digest_size = 1 + block_size = 128 + + def __init__(self, digest_size): + if ( + digest_size > self._max_digest_size or + digest_size < self._min_digest_size + ): + raise ValueError("Digest size must be {0}-{1}".format( + self._min_digest_size, self._max_digest_size) + ) + + self._digest_size = digest_size + + digest_size = utils.read_only_property("_digest_size") + + +@utils.register_interface(HashAlgorithm) +class BLAKE2s(object): + name = "blake2s" + block_size = 64 + _max_digest_size = 32 + _min_digest_size = 1 + + def __init__(self, digest_size): + if ( + digest_size > self._max_digest_size or + digest_size < self._min_digest_size + ): + raise ValueError("Digest size must be {0}-{1}".format( + self._min_digest_size, self._max_digest_size) + ) + + self._digest_size = digest_size + + digest_size = utils.read_only_property("_digest_size") diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/hmac.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/hmac.py new file mode 100644 index 0000000..2e9a4e2 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/hmac.py @@ -0,0 +1,69 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.primitives import hashes, mac + + +@utils.register_interface(mac.MACContext) +@utils.register_interface(hashes.HashContext) +class HMAC(object): + def __init__(self, key, algorithm, backend, ctx=None): + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + self._algorithm = algorithm + + self._backend = backend + self._key = key + if ctx is None: + self._ctx = self._backend.create_hmac_ctx(key, self.algorithm) + else: + self._ctx = ctx + + algorithm = utils.read_only_property("_algorithm") + + def update(self, data): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") + self._ctx.update(data) + + def copy(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + return HMAC( + self._key, + self.algorithm, + backend=self._backend, + ctx=self._ctx.copy() + ) + + def finalize(self): + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + digest = self._ctx.finalize() + self._ctx = None + return digest + + def verify(self, signature): + if not isinstance(signature, bytes): + raise TypeError("signature must be bytes.") + if self._ctx is None: + raise AlreadyFinalized("Context was already finalized.") + + ctx, self._ctx = self._ctx, None + ctx.verify(signature) diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/__init__.py new file mode 100644 index 0000000..2d0724e --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/__init__.py @@ -0,0 +1,26 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + + +@six.add_metaclass(abc.ABCMeta) +class KeyDerivationFunction(object): + @abc.abstractmethod + def derive(self, key_material): + """ + Deterministically generates and returns a new key based on the existing + key material. + """ + + @abc.abstractmethod + def verify(self, key_material, expected_key): + """ + Checks whether the key generated by the key material matches the + expected derived key. Raises an exception if they do not match. + """ diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/concatkdf.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/concatkdf.py new file mode 100644 index 0000000..c6399e4 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -0,0 +1,125 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import struct + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.backends.interfaces import HashBackend +from cryptography.hazmat.primitives import constant_time, hashes, hmac +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +def _int_to_u32be(n): + return struct.pack('>I', n) + + +def _common_args_checks(algorithm, length, otherinfo): + max_length = algorithm.digest_size * (2 ** 32 - 1) + if length > max_length: + raise ValueError( + "Can not derive keys larger than {0} bits.".format( + max_length + )) + if not (otherinfo is None or isinstance(otherinfo, bytes)): + raise TypeError("otherinfo must be bytes.") + + +def _concatkdf_derive(key_material, length, auxfn, otherinfo): + if not isinstance(key_material, bytes): + raise TypeError("key_material must be bytes.") + + output = [b""] + outlen = 0 + counter = 1 + + while (length > outlen): + h = auxfn() + h.update(_int_to_u32be(counter)) + h.update(key_material) + h.update(otherinfo) + output.append(h.finalize()) + outlen += len(output[-1]) + counter += 1 + + return b"".join(output)[:length] + + +@utils.register_interface(KeyDerivationFunction) +class ConcatKDFHash(object): + def __init__(self, algorithm, length, otherinfo, backend): + + _common_args_checks(algorithm, length, otherinfo) + self._algorithm = algorithm + self._length = length + self._otherinfo = otherinfo + if self._otherinfo is None: + self._otherinfo = b"" + + if not isinstance(backend, HashBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HashBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + self._backend = backend + self._used = False + + def _hash(self): + return hashes.Hash(self._algorithm, self._backend) + + def derive(self, key_material): + if self._used: + raise AlreadyFinalized + self._used = True + return _concatkdf_derive(key_material, self._length, + self._hash, self._otherinfo) + + def verify(self, key_material, expected_key): + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +@utils.register_interface(KeyDerivationFunction) +class ConcatKDFHMAC(object): + def __init__(self, algorithm, length, salt, otherinfo, backend): + + _common_args_checks(algorithm, length, otherinfo) + self._algorithm = algorithm + self._length = length + self._otherinfo = otherinfo + if self._otherinfo is None: + self._otherinfo = b"" + + if not (salt is None or isinstance(salt, bytes)): + raise TypeError("salt must be bytes.") + if salt is None: + salt = b"\x00" * algorithm.block_size + self._salt = salt + + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + self._backend = backend + self._used = False + + def _hmac(self): + return hmac.HMAC(self._salt, self._algorithm, self._backend) + + def derive(self, key_material): + if self._used: + raise AlreadyFinalized + self._used = True + return _concatkdf_derive(key_material, self._length, + self._hmac, self._otherinfo) + + def verify(self, key_material, expected_key): + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/hkdf.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/hkdf.py new file mode 100644 index 0000000..917b4e9 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/hkdf.py @@ -0,0 +1,116 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import six + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.primitives import constant_time, hmac +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +@utils.register_interface(KeyDerivationFunction) +class HKDF(object): + def __init__(self, algorithm, length, salt, info, backend): + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + self._algorithm = algorithm + + if not (salt is None or isinstance(salt, bytes)): + raise TypeError("salt must be bytes.") + + if salt is None: + salt = b"\x00" * self._algorithm.digest_size + + self._salt = salt + + self._backend = backend + + self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend) + + def _extract(self, key_material): + h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend) + h.update(key_material) + return h.finalize() + + def derive(self, key_material): + if not isinstance(key_material, bytes): + raise TypeError("key_material must be bytes.") + + return self._hkdf_expand.derive(self._extract(key_material)) + + def verify(self, key_material, expected_key): + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey + + +@utils.register_interface(KeyDerivationFunction) +class HKDFExpand(object): + def __init__(self, algorithm, length, info, backend): + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + self._algorithm = algorithm + + self._backend = backend + + max_length = 255 * algorithm.digest_size + + if length > max_length: + raise ValueError( + "Can not derive keys larger than {0} octets.".format( + max_length + )) + + self._length = length + + if not (info is None or isinstance(info, bytes)): + raise TypeError("info must be bytes.") + + if info is None: + info = b"" + + self._info = info + + self._used = False + + def _expand(self, key_material): + output = [b""] + counter = 1 + + while self._algorithm.digest_size * (len(output) - 1) < self._length: + h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) + h.update(output[-1]) + h.update(self._info) + h.update(six.int2byte(counter)) + output.append(h.finalize()) + counter += 1 + + return b"".join(output)[:self._length] + + def derive(self, key_material): + if not isinstance(key_material, bytes): + raise TypeError("key_material must be bytes.") + + if self._used: + raise AlreadyFinalized + + self._used = True + return self._expand(key_material) + + def verify(self, key_material, expected_key): + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/kbkdf.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/kbkdf.py new file mode 100644 index 0000000..14de56e --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/kbkdf.py @@ -0,0 +1,148 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from enum import Enum + +from six.moves import range + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.primitives import constant_time, hashes, hmac +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +class Mode(Enum): + CounterMode = "ctr" + + +class CounterLocation(Enum): + BeforeFixed = "before_fixed" + AfterFixed = "after_fixed" + + +@utils.register_interface(KeyDerivationFunction) +class KBKDFHMAC(object): + def __init__(self, algorithm, mode, length, rlen, llen, + location, label, context, fixed, backend): + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + if not isinstance(algorithm, hashes.HashAlgorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hash algorithm.", + _Reasons.UNSUPPORTED_HASH + ) + + if not backend.hmac_supported(algorithm): + raise UnsupportedAlgorithm( + "Algorithm supplied is not a supported hmac algorithm.", + _Reasons.UNSUPPORTED_HASH + ) + + if not isinstance(mode, Mode): + raise TypeError("mode must be of type Mode") + + if not isinstance(location, CounterLocation): + raise TypeError("location must be of type CounterLocation") + + if (label or context) and fixed: + raise ValueError("When supplying fixed data, " + "label and context are ignored.") + + if rlen is None or not self._valid_byte_length(rlen): + raise ValueError("rlen must be between 1 and 4") + + if llen is None and fixed is None: + raise ValueError("Please specify an llen") + + if llen is not None and not isinstance(llen, int): + raise TypeError("llen must be an integer") + + if label is None: + label = b'' + + if context is None: + context = b'' + + if (not isinstance(label, bytes) or + not isinstance(context, bytes)): + raise TypeError('label and context must be of type bytes') + + self._algorithm = algorithm + self._mode = mode + self._length = length + self._rlen = rlen + self._llen = llen + self._location = location + self._label = label + self._context = context + self._backend = backend + self._used = False + self._fixed_data = fixed + + def _valid_byte_length(self, value): + if not isinstance(value, int): + raise TypeError('value must be of type int') + + value_bin = utils.int_to_bytes(1, value) + if not 1 <= len(value_bin) <= 4: + return False + return True + + def derive(self, key_material): + if self._used: + raise AlreadyFinalized + + if not isinstance(key_material, bytes): + raise TypeError('key_material must be bytes') + self._used = True + + # inverse floor division (equivalent to ceiling) + rounds = -(-self._length // self._algorithm.digest_size) + + output = [b''] + + # For counter mode, the number of iterations shall not be + # larger than 2^r-1, where r <= 32 is the binary length of the counter + # This ensures that the counter values used as an input to the + # PRF will not repeat during a particular call to the KDF function. + r_bin = utils.int_to_bytes(1, self._rlen) + if rounds > pow(2, len(r_bin) * 8) - 1: + raise ValueError('There are too many iterations.') + + for i in range(1, rounds + 1): + h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) + + counter = utils.int_to_bytes(i, self._rlen) + if self._location == CounterLocation.BeforeFixed: + h.update(counter) + + h.update(self._generate_fixed_input()) + + if self._location == CounterLocation.AfterFixed: + h.update(counter) + + output.append(h.finalize()) + + return b''.join(output)[:self._length] + + def _generate_fixed_input(self): + if self._fixed_data and isinstance(self._fixed_data, bytes): + return self._fixed_data + + l_val = utils.int_to_bytes(self._length * 8, self._llen) + + return b"".join([self._label, b"\x00", self._context, l_val]) + + def verify(self, key_material, expected_key): + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/pbkdf2.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/pbkdf2.py new file mode 100644 index 0000000..f8ce7a3 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/pbkdf2.py @@ -0,0 +1,58 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +@utils.register_interface(KeyDerivationFunction) +class PBKDF2HMAC(object): + def __init__(self, algorithm, length, salt, iterations, backend): + if not isinstance(backend, PBKDF2HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement PBKDF2HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + if not backend.pbkdf2_hmac_supported(algorithm): + raise UnsupportedAlgorithm( + "{0} is not supported for PBKDF2 by this backend.".format( + algorithm.name), + _Reasons.UNSUPPORTED_HASH + ) + self._used = False + self._algorithm = algorithm + self._length = length + if not isinstance(salt, bytes): + raise TypeError("salt must be bytes.") + self._salt = salt + self._iterations = iterations + self._backend = backend + + def derive(self, key_material): + if self._used: + raise AlreadyFinalized("PBKDF2 instances can only be used once.") + self._used = True + + if not isinstance(key_material, bytes): + raise TypeError("key_material must be bytes.") + return self._backend.derive_pbkdf2_hmac( + self._algorithm, + self._length, + self._salt, + self._iterations, + key_material + ) + + def verify(self, key_material, expected_key): + derived_key = self.derive(key_material) + if not constant_time.bytes_eq(derived_key, expected_key): + raise InvalidKey("Keys do not match.") diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/scrypt.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/scrypt.py new file mode 100644 index 0000000..77dcf9a --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/scrypt.py @@ -0,0 +1,66 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import sys + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import ScryptBackend +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +# This is used by the scrypt tests to skip tests that require more memory +# than the MEM_LIMIT +_MEM_LIMIT = sys.maxsize // 2 + + +@utils.register_interface(KeyDerivationFunction) +class Scrypt(object): + def __init__(self, salt, length, n, r, p, backend): + if not isinstance(backend, ScryptBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement ScryptBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + self._length = length + if not isinstance(salt, bytes): + raise TypeError("salt must be bytes.") + + if n < 2 or (n & (n - 1)) != 0: + raise ValueError("n must be greater than 1 and be a power of 2.") + + if r < 1: + raise ValueError("r must be greater than or equal to 1.") + + if p < 1: + raise ValueError("p must be greater than or equal to 1.") + + self._used = False + self._salt = salt + self._n = n + self._r = r + self._p = p + self._backend = backend + + def derive(self, key_material): + if self._used: + raise AlreadyFinalized("Scrypt instances can only be used once.") + self._used = True + + if not isinstance(key_material, bytes): + raise TypeError("key_material must be bytes.") + return self._backend.derive_scrypt( + key_material, self._salt, self._length, self._n, self._r, self._p + ) + + def verify(self, key_material, expected_key): + derived_key = self.derive(key_material) + if not constant_time.bytes_eq(derived_key, expected_key): + raise InvalidKey("Keys do not match.") diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/x963kdf.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/x963kdf.py new file mode 100644 index 0000000..83789b3 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -0,0 +1,70 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import struct + +from cryptography import utils +from cryptography.exceptions import ( + AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HashBackend +from cryptography.hazmat.primitives import constant_time, hashes +from cryptography.hazmat.primitives.kdf import KeyDerivationFunction + + +def _int_to_u32be(n): + return struct.pack('>I', n) + + +@utils.register_interface(KeyDerivationFunction) +class X963KDF(object): + def __init__(self, algorithm, length, sharedinfo, backend): + + max_len = algorithm.digest_size * (2 ** 32 - 1) + if length > max_len: + raise ValueError( + "Can not derive keys larger than {0} bits.".format(max_len)) + if not (sharedinfo is None or isinstance(sharedinfo, bytes)): + raise TypeError("sharedinfo must be bytes.") + self._algorithm = algorithm + self._length = length + self._sharedinfo = sharedinfo + + if not isinstance(backend, HashBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HashBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + self._backend = backend + self._used = False + + def derive(self, key_material): + if self._used: + raise AlreadyFinalized + self._used = True + + if not isinstance(key_material, bytes): + raise TypeError("key_material must be bytes.") + + output = [b""] + outlen = 0 + counter = 1 + + while self._length > outlen: + h = hashes.Hash(self._algorithm, self._backend) + h.update(key_material) + h.update(_int_to_u32be(counter)) + if self._sharedinfo is not None: + h.update(self._sharedinfo) + output.append(h.finalize()) + outlen += len(output[-1]) + counter += 1 + + return b"".join(output)[:self._length] + + def verify(self, key_material, expected_key): + if not constant_time.bytes_eq(self.derive(key_material), expected_key): + raise InvalidKey diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/keywrap.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/keywrap.py new file mode 100644 index 0000000..f55c519 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/keywrap.py @@ -0,0 +1,154 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import struct + +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import ECB +from cryptography.hazmat.primitives.constant_time import bytes_eq + + +def _wrap_core(wrapping_key, a, r, backend): + # RFC 3394 Key Wrap - 2.2.1 (index method) + encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() + n = len(r) + for j in range(6): + for i in range(n): + # every encryption operation is a discrete 16 byte chunk (because + # AES has a 128-bit block size) and since we're using ECB it is + # safe to reuse the encryptor for the entire operation + b = encryptor.update(a + r[i]) + # pack/unpack are safe as these are always 64-bit chunks + a = struct.pack( + ">Q", struct.unpack(">Q", b[:8])[0] ^ ((n * j) + i + 1) + ) + r[i] = b[-8:] + + assert encryptor.finalize() == b"" + + return a + b"".join(r) + + +def aes_key_wrap(wrapping_key, key_to_wrap, backend): + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + if len(key_to_wrap) < 16: + raise ValueError("The key to wrap must be at least 16 bytes") + + if len(key_to_wrap) % 8 != 0: + raise ValueError("The key to wrap must be a multiple of 8 bytes") + + a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)] + return _wrap_core(wrapping_key, a, r, backend) + + +def _unwrap_core(wrapping_key, a, r, backend): + # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) + decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() + n = len(r) + for j in reversed(range(6)): + for i in reversed(range(n)): + # pack/unpack are safe as these are always 64-bit chunks + atr = struct.pack( + ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1) + ) + r[i] + # every decryption operation is a discrete 16 byte chunk so + # it is safe to reuse the decryptor for the entire operation + b = decryptor.update(atr) + a = b[:8] + r[i] = b[-8:] + + assert decryptor.finalize() == b"" + return a, r + + +def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend): + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap)) + # pad the key to wrap if necessary + pad = (8 - (len(key_to_wrap) % 8)) % 8 + key_to_wrap = key_to_wrap + b"\x00" * pad + if len(key_to_wrap) == 8: + # RFC 5649 - 4.1 - exactly 8 octets after padding + encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() + b = encryptor.update(aiv + key_to_wrap) + assert encryptor.finalize() == b"" + return b + else: + r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)] + return _wrap_core(wrapping_key, aiv, r, backend) + + +def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend): + if len(wrapped_key) < 16: + raise InvalidUnwrap("Must be at least 16 bytes") + + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + if len(wrapped_key) == 16: + # RFC 5649 - 4.2 - exactly two 64-bit blocks + decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() + b = decryptor.update(wrapped_key) + assert decryptor.finalize() == b"" + a = b[:8] + data = b[8:] + n = 1 + else: + r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)] + encrypted_aiv = r.pop(0) + n = len(r) + a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend) + data = b"".join(r) + + # 1) Check that MSB(32,A) = A65959A6. + # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n. If so, let + # MLI = LSB(32,A). + # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of + # the output data are zero. + (mli,) = struct.unpack(">I", a[4:]) + b = (8 * n) - mli + if ( + not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not + 8 * (n - 1) < mli <= 8 * n or ( + b != 0 and not bytes_eq(data[-b:], b"\x00" * b) + ) + ): + raise InvalidUnwrap() + + if b == 0: + return data + else: + return data[:-b] + + +def aes_key_unwrap(wrapping_key, wrapped_key, backend): + if len(wrapped_key) < 24: + raise InvalidUnwrap("Must be at least 24 bytes") + + if len(wrapped_key) % 8 != 0: + raise InvalidUnwrap("The wrapped key must be a multiple of 8 bytes") + + if len(wrapping_key) not in [16, 24, 32]: + raise ValueError("The wrapping key must be a valid AES key length") + + aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" + r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)] + a = r.pop(0) + a, r = _unwrap_core(wrapping_key, a, r, backend) + if not bytes_eq(a, aiv): + raise InvalidUnwrap() + + return b"".join(r) + + +class InvalidUnwrap(Exception): + pass diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/mac.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/mac.py new file mode 100644 index 0000000..4c95190 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/mac.py @@ -0,0 +1,37 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + + +@six.add_metaclass(abc.ABCMeta) +class MACContext(object): + @abc.abstractmethod + def update(self, data): + """ + Processes the provided bytes. + """ + + @abc.abstractmethod + def finalize(self): + """ + Returns the message authentication code as bytes. + """ + + @abc.abstractmethod + def copy(self): + """ + Return a MACContext that is a copy of the current context. + """ + + @abc.abstractmethod + def verify(self, signature): + """ + Checks if the generated message authentication code matches the + signature. + """ diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/padding.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/padding.py new file mode 100644 index 0000000..a081976 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/padding.py @@ -0,0 +1,202 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc + +import six + +from cryptography import utils +from cryptography.exceptions import AlreadyFinalized +from cryptography.hazmat.bindings._padding import lib + + +@six.add_metaclass(abc.ABCMeta) +class PaddingContext(object): + @abc.abstractmethod + def update(self, data): + """ + Pads the provided bytes and returns any available data as bytes. + """ + + @abc.abstractmethod + def finalize(self): + """ + Finalize the padding, returns bytes. + """ + + +def _byte_padding_check(block_size): + if not (0 <= block_size <= 2040): + raise ValueError("block_size must be in range(0, 2041).") + + if block_size % 8 != 0: + raise ValueError("block_size must be a multiple of 8.") + + +def _byte_padding_update(buffer_, data, block_size): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") + + buffer_ += data + + finished_blocks = len(buffer_) // (block_size // 8) + + result = buffer_[:finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8):] + + return buffer_, result + + +def _byte_padding_pad(buffer_, block_size, paddingfn): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + pad_size = block_size // 8 - len(buffer_) + return buffer_ + paddingfn(pad_size) + + +def _byte_unpadding_update(buffer_, data, block_size): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") + + buffer_ += data + + finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) + + result = buffer_[:finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8):] + + return buffer_, result + + +def _byte_unpadding_check(buffer_, block_size, checkfn): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if len(buffer_) != block_size // 8: + raise ValueError("Invalid padding bytes.") + + valid = checkfn(buffer_, block_size // 8) + + if not valid: + raise ValueError("Invalid padding bytes.") + + pad_size = six.indexbytes(buffer_, -1) + return buffer_[:-pad_size] + + +class PKCS7(object): + def __init__(self, block_size): + _byte_padding_check(block_size) + self.block_size = block_size + + def padder(self): + return _PKCS7PaddingContext(self.block_size) + + def unpadder(self): + return _PKCS7UnpaddingContext(self.block_size) + + +@utils.register_interface(PaddingContext) +class _PKCS7PaddingContext(object): + def __init__(self, block_size): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data): + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size) + return result + + def _padding(self, size): + return six.int2byte(size) * size + + def finalize(self): + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding) + self._buffer = None + return result + + +@utils.register_interface(PaddingContext) +class _PKCS7UnpaddingContext(object): + def __init__(self, block_size): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data): + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size) + return result + + def finalize(self): + result = _byte_unpadding_check( + self._buffer, self.block_size, + lib.Cryptography_check_pkcs7_padding) + self._buffer = None + return result + + +class ANSIX923(object): + def __init__(self, block_size): + _byte_padding_check(block_size) + self.block_size = block_size + + def padder(self): + return _ANSIX923PaddingContext(self.block_size) + + def unpadder(self): + return _ANSIX923UnpaddingContext(self.block_size) + + +@utils.register_interface(PaddingContext) +class _ANSIX923PaddingContext(object): + def __init__(self, block_size): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data): + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size) + return result + + def _padding(self, size): + return six.int2byte(0) * (size - 1) + six.int2byte(size) + + def finalize(self): + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding) + self._buffer = None + return result + + +@utils.register_interface(PaddingContext) +class _ANSIX923UnpaddingContext(object): + def __init__(self, block_size): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + + def update(self, data): + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size) + return result + + def finalize(self): + result = _byte_unpadding_check( + self._buffer, self.block_size, + lib.Cryptography_check_ansix923_padding) + self._buffer = None + return result diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/serialization.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/serialization.py new file mode 100644 index 0000000..bd09e6e --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/serialization.py @@ -0,0 +1,209 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +import base64 +import struct +from enum import Enum + +import six + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa + + +def load_pem_private_key(data, password, backend): + return backend.load_pem_private_key(data, password) + + +def load_pem_public_key(data, backend): + return backend.load_pem_public_key(data) + + +def load_pem_parameters(data, backend): + return backend.load_pem_parameters(data) + + +def load_der_private_key(data, password, backend): + return backend.load_der_private_key(data, password) + + +def load_der_public_key(data, backend): + return backend.load_der_public_key(data) + + +def load_der_parameters(data, backend): + return backend.load_der_parameters(data) + + +def load_ssh_public_key(data, backend): + key_parts = data.split(b' ', 2) + + if len(key_parts) < 2: + raise ValueError( + 'Key is not in the proper format or contains extra data.') + + key_type = key_parts[0] + + if key_type == b'ssh-rsa': + loader = _load_ssh_rsa_public_key + elif key_type == b'ssh-dss': + loader = _load_ssh_dss_public_key + elif key_type in [ + b'ecdsa-sha2-nistp256', b'ecdsa-sha2-nistp384', b'ecdsa-sha2-nistp521', + ]: + loader = _load_ssh_ecdsa_public_key + else: + raise UnsupportedAlgorithm('Key type is not supported.') + + key_body = key_parts[1] + + try: + decoded_data = base64.b64decode(key_body) + except TypeError: + raise ValueError('Key is not in the proper format.') + + inner_key_type, rest = _ssh_read_next_string(decoded_data) + + if inner_key_type != key_type: + raise ValueError( + 'Key header and key body contain different key type values.' + ) + + return loader(key_type, rest, backend) + + +def _load_ssh_rsa_public_key(key_type, decoded_data, backend): + e, rest = _ssh_read_next_mpint(decoded_data) + n, rest = _ssh_read_next_mpint(rest) + + if rest: + raise ValueError('Key body contains extra bytes.') + + return rsa.RSAPublicNumbers(e, n).public_key(backend) + + +def _load_ssh_dss_public_key(key_type, decoded_data, backend): + p, rest = _ssh_read_next_mpint(decoded_data) + q, rest = _ssh_read_next_mpint(rest) + g, rest = _ssh_read_next_mpint(rest) + y, rest = _ssh_read_next_mpint(rest) + + if rest: + raise ValueError('Key body contains extra bytes.') + + parameter_numbers = dsa.DSAParameterNumbers(p, q, g) + public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) + + return public_numbers.public_key(backend) + + +def _load_ssh_ecdsa_public_key(expected_key_type, decoded_data, backend): + curve_name, rest = _ssh_read_next_string(decoded_data) + data, rest = _ssh_read_next_string(rest) + + if expected_key_type != b"ecdsa-sha2-" + curve_name: + raise ValueError( + 'Key header and key body contain different key type values.' + ) + + if rest: + raise ValueError('Key body contains extra bytes.') + + curve = { + b"nistp256": ec.SECP256R1, + b"nistp384": ec.SECP384R1, + b"nistp521": ec.SECP521R1, + }[curve_name]() + + if six.indexbytes(data, 0) != 4: + raise NotImplementedError( + "Compressed elliptic curve points are not supported" + ) + + numbers = ec.EllipticCurvePublicNumbers.from_encoded_point(curve, data) + return numbers.public_key(backend) + + +def _ssh_read_next_string(data): + """ + Retrieves the next RFC 4251 string value from the data. + + While the RFC calls these strings, in Python they are bytes objects. + """ + if len(data) < 4: + raise ValueError("Key is not in the proper format") + + str_len, = struct.unpack('>I', data[:4]) + if len(data) < str_len + 4: + raise ValueError("Key is not in the proper format") + + return data[4:4 + str_len], data[4 + str_len:] + + +def _ssh_read_next_mpint(data): + """ + Reads the next mpint from the data. + + Currently, all mpints are interpreted as unsigned. + """ + mpint_data, rest = _ssh_read_next_string(data) + + return ( + utils.int_from_bytes(mpint_data, byteorder='big', signed=False), rest + ) + + +def _ssh_write_string(data): + return struct.pack(">I", len(data)) + data + + +def _ssh_write_mpint(value): + data = utils.int_to_bytes(value) + if six.indexbytes(data, 0) & 0x80: + data = b"\x00" + data + return _ssh_write_string(data) + + +class Encoding(Enum): + PEM = "PEM" + DER = "DER" + OpenSSH = "OpenSSH" + + +class PrivateFormat(Enum): + PKCS8 = "PKCS8" + TraditionalOpenSSL = "TraditionalOpenSSL" + + +class PublicFormat(Enum): + SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" + PKCS1 = "Raw PKCS#1" + OpenSSH = "OpenSSH" + + +class ParameterFormat(Enum): + PKCS3 = "PKCS3" + + +@six.add_metaclass(abc.ABCMeta) +class KeySerializationEncryption(object): + pass + + +@utils.register_interface(KeySerializationEncryption) +class BestAvailableEncryption(object): + def __init__(self, password): + if not isinstance(password, bytes) or len(password) == 0: + raise ValueError("Password must be 1 or more bytes.") + + self.password = password + + +@utils.register_interface(KeySerializationEncryption) +class NoEncryption(object): + pass diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/__init__.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/__init__.py new file mode 100644 index 0000000..e71f9e6 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/__init__.py @@ -0,0 +1,9 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + + +class InvalidToken(Exception): + pass diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/hotp.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/hotp.py new file mode 100644 index 0000000..4ad1bdc --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/hotp.py @@ -0,0 +1,68 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import struct + +import six + +from cryptography.exceptions import ( + UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.primitives import constant_time, hmac +from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 +from cryptography.hazmat.primitives.twofactor import InvalidToken +from cryptography.hazmat.primitives.twofactor.utils import _generate_uri + + +class HOTP(object): + def __init__(self, key, length, algorithm, backend, + enforce_key_length=True): + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + if len(key) < 16 and enforce_key_length is True: + raise ValueError("Key length has to be at least 128 bits.") + + if not isinstance(length, six.integer_types): + raise TypeError("Length parameter must be an integer type.") + + if length < 6 or length > 8: + raise ValueError("Length of HOTP has to be between 6 to 8.") + + if not isinstance(algorithm, (SHA1, SHA256, SHA512)): + raise TypeError("Algorithm must be SHA1, SHA256 or SHA512.") + + self._key = key + self._length = length + self._algorithm = algorithm + self._backend = backend + + def generate(self, counter): + truncated_value = self._dynamic_truncate(counter) + hotp = truncated_value % (10 ** self._length) + return "{0:0{1}}".format(hotp, self._length).encode() + + def verify(self, hotp, counter): + if not constant_time.bytes_eq(self.generate(counter), hotp): + raise InvalidToken("Supplied HOTP value does not match.") + + def _dynamic_truncate(self, counter): + ctx = hmac.HMAC(self._key, self._algorithm, self._backend) + ctx.update(struct.pack(">Q", counter)) + hmac_value = ctx.finalize() + + offset = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111 + p = hmac_value[offset:offset + 4] + return struct.unpack(">I", p)[0] & 0x7fffffff + + def get_provisioning_uri(self, account_name, counter, issuer): + return _generate_uri(self, "hotp", account_name, issuer, [ + ("counter", int(counter)), + ]) diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/totp.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/totp.py new file mode 100644 index 0000000..499f282 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/totp.py @@ -0,0 +1,40 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography.exceptions import ( + UnsupportedAlgorithm, _Reasons +) +from cryptography.hazmat.backends.interfaces import HMACBackend +from cryptography.hazmat.primitives import constant_time +from cryptography.hazmat.primitives.twofactor import InvalidToken +from cryptography.hazmat.primitives.twofactor.hotp import HOTP +from cryptography.hazmat.primitives.twofactor.utils import _generate_uri + + +class TOTP(object): + def __init__(self, key, length, algorithm, time_step, backend, + enforce_key_length=True): + if not isinstance(backend, HMACBackend): + raise UnsupportedAlgorithm( + "Backend object does not implement HMACBackend.", + _Reasons.BACKEND_MISSING_INTERFACE + ) + + self._time_step = time_step + self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) + + def generate(self, time): + counter = int(time / self._time_step) + return self._hotp.generate(counter) + + def verify(self, totp, time): + if not constant_time.bytes_eq(self.generate(time), totp): + raise InvalidToken("Supplied TOTP value does not match.") + + def get_provisioning_uri(self, account_name, issuer): + return _generate_uri(self._hotp, "totp", account_name, issuer, [ + ("period", int(self._time_step)), + ]) diff --git a/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/utils.py b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/utils.py new file mode 100644 index 0000000..0ed8c4c --- /dev/null +++ b/server/www/packages/packages-common/cryptography/hazmat/primitives/twofactor/utils.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import base64 + +from six.moves.urllib.parse import quote, urlencode + + +def _generate_uri(hotp, type_name, account_name, issuer, extra_parameters): + parameters = [ + ("digits", hotp._length), + ("secret", base64.b32encode(hotp._key)), + ("algorithm", hotp._algorithm.name.upper()), + ] + + if issuer is not None: + parameters.append(("issuer", issuer)) + + parameters.extend(extra_parameters) + + uriparts = { + "type": type_name, + "label": ("%s:%s" % (quote(issuer), quote(account_name)) if issuer + else quote(account_name)), + "parameters": urlencode(parameters), + } + return "otpauth://{type}/{label}?{parameters}".format(**uriparts) diff --git a/server/www/packages/packages-common/cryptography/utils.py b/server/www/packages/packages-common/cryptography/utils.py new file mode 100644 index 0000000..3d45a77 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/utils.py @@ -0,0 +1,165 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +import binascii +import inspect +import sys +import warnings + + +# We use a UserWarning subclass, instead of DeprecationWarning, because CPython +# decided deprecation warnings should be invisble by default. +class CryptographyDeprecationWarning(UserWarning): + pass + + +# Several APIs were deprecated with no specific end-of-life date because of the +# ubiquity of their use. They should not be removed until we agree on when that +# cycle ends. +PersistentlyDeprecated = CryptographyDeprecationWarning +DeprecatedIn21 = CryptographyDeprecationWarning +DeprecatedIn23 = CryptographyDeprecationWarning + + +def _check_bytes(name, value): + if not isinstance(value, bytes): + raise TypeError("{0} must be bytes".format(name)) + + +def read_only_property(name): + return property(lambda self: getattr(self, name)) + + +def register_interface(iface): + def register_decorator(klass): + verify_interface(iface, klass) + iface.register(klass) + return klass + return register_decorator + + +def register_interface_if(predicate, iface): + def register_decorator(klass): + if predicate: + verify_interface(iface, klass) + iface.register(klass) + return klass + return register_decorator + + +if hasattr(int, "from_bytes"): + int_from_bytes = int.from_bytes +else: + def int_from_bytes(data, byteorder, signed=False): + assert byteorder == 'big' + assert not signed + + return int(binascii.hexlify(data), 16) + + +if hasattr(int, "to_bytes"): + def int_to_bytes(integer, length=None): + return integer.to_bytes( + length or (integer.bit_length() + 7) // 8 or 1, 'big' + ) +else: + def int_to_bytes(integer, length=None): + hex_string = '%x' % integer + if length is None: + n = len(hex_string) + else: + n = length * 2 + return binascii.unhexlify(hex_string.zfill(n + (n & 1))) + + +class InterfaceNotImplemented(Exception): + pass + + +if hasattr(inspect, "signature"): + signature = inspect.signature +else: + signature = inspect.getargspec + + +def verify_interface(iface, klass): + for method in iface.__abstractmethods__: + if not hasattr(klass, method): + raise InterfaceNotImplemented( + "{0} is missing a {1!r} method".format(klass, method) + ) + if isinstance(getattr(iface, method), abc.abstractproperty): + # Can't properly verify these yet. + continue + sig = signature(getattr(iface, method)) + actual = signature(getattr(klass, method)) + if sig != actual: + raise InterfaceNotImplemented( + "{0}.{1}'s signature differs from the expected. Expected: " + "{2!r}. Received: {3!r}".format( + klass, method, sig, actual + ) + ) + + +# No longer needed as of 2.2, but retained because we have external consumers +# who use it. +def bit_length(x): + return x.bit_length() + + +class _DeprecatedValue(object): + def __init__(self, value, message, warning_class): + self.value = value + self.message = message + self.warning_class = warning_class + + +class _ModuleWithDeprecations(object): + def __init__(self, module): + self.__dict__["_module"] = module + + def __getattr__(self, attr): + obj = getattr(self._module, attr) + if isinstance(obj, _DeprecatedValue): + warnings.warn(obj.message, obj.warning_class, stacklevel=2) + obj = obj.value + return obj + + def __setattr__(self, attr, value): + setattr(self._module, attr, value) + + def __delattr__(self, attr): + obj = getattr(self._module, attr) + if isinstance(obj, _DeprecatedValue): + warnings.warn(obj.message, obj.warning_class, stacklevel=2) + + delattr(self._module, attr) + + def __dir__(self): + return ["_module"] + dir(self._module) + + +def deprecated(value, module_name, message, warning_class): + module = sys.modules[module_name] + if not isinstance(module, _ModuleWithDeprecations): + sys.modules[module_name] = _ModuleWithDeprecations(module) + return _DeprecatedValue(value, message, warning_class) + + +def cached_property(func): + cached_name = "_cached_{0}".format(func) + sentinel = object() + + def inner(instance): + cache = getattr(instance, cached_name, sentinel) + if cache is not sentinel: + return cache + result = func(instance) + setattr(instance, cached_name, result) + return result + return property(inner) diff --git a/server/www/packages/packages-common/cryptography/x509/__init__.py b/server/www/packages/packages-common/cryptography/x509/__init__.py new file mode 100644 index 0000000..d2f9b04 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/x509/__init__.py @@ -0,0 +1,185 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography.x509 import certificate_transparency +from cryptography.x509.base import ( + Certificate, CertificateBuilder, CertificateRevocationList, + CertificateRevocationListBuilder, + CertificateSigningRequest, CertificateSigningRequestBuilder, + InvalidVersion, RevokedCertificate, RevokedCertificateBuilder, + Version, load_der_x509_certificate, load_der_x509_crl, load_der_x509_csr, + load_pem_x509_certificate, load_pem_x509_crl, load_pem_x509_csr, + random_serial_number, +) +from cryptography.x509.extensions import ( + AccessDescription, AuthorityInformationAccess, + AuthorityKeyIdentifier, BasicConstraints, CRLDistributionPoints, + CRLNumber, CRLReason, CertificateIssuer, CertificatePolicies, + DeltaCRLIndicator, DistributionPoint, DuplicateExtension, ExtendedKeyUsage, + Extension, ExtensionNotFound, ExtensionType, Extensions, FreshestCRL, + GeneralNames, InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName, + KeyUsage, NameConstraints, NoticeReference, OCSPNoCheck, PolicyConstraints, + PolicyInformation, PrecertificateSignedCertificateTimestamps, ReasonFlags, + SubjectAlternativeName, SubjectKeyIdentifier, TLSFeature, TLSFeatureType, + UnrecognizedExtension, UserNotice +) +from cryptography.x509.general_name import ( + DNSName, DirectoryName, GeneralName, IPAddress, OtherName, RFC822Name, + RegisteredID, UniformResourceIdentifier, UnsupportedGeneralNameType, + _GENERAL_NAMES +) +from cryptography.x509.name import ( + Name, NameAttribute, RelativeDistinguishedName +) +from cryptography.x509.oid import ( + AuthorityInformationAccessOID, CRLEntryExtensionOID, + CertificatePoliciesOID, ExtendedKeyUsageOID, ExtensionOID, NameOID, + ObjectIdentifier, SignatureAlgorithmOID, _SIG_OIDS_TO_HASH +) + + +OID_AUTHORITY_INFORMATION_ACCESS = ExtensionOID.AUTHORITY_INFORMATION_ACCESS +OID_AUTHORITY_KEY_IDENTIFIER = ExtensionOID.AUTHORITY_KEY_IDENTIFIER +OID_BASIC_CONSTRAINTS = ExtensionOID.BASIC_CONSTRAINTS +OID_CERTIFICATE_POLICIES = ExtensionOID.CERTIFICATE_POLICIES +OID_CRL_DISTRIBUTION_POINTS = ExtensionOID.CRL_DISTRIBUTION_POINTS +OID_EXTENDED_KEY_USAGE = ExtensionOID.EXTENDED_KEY_USAGE +OID_FRESHEST_CRL = ExtensionOID.FRESHEST_CRL +OID_INHIBIT_ANY_POLICY = ExtensionOID.INHIBIT_ANY_POLICY +OID_ISSUER_ALTERNATIVE_NAME = ExtensionOID.ISSUER_ALTERNATIVE_NAME +OID_KEY_USAGE = ExtensionOID.KEY_USAGE +OID_NAME_CONSTRAINTS = ExtensionOID.NAME_CONSTRAINTS +OID_OCSP_NO_CHECK = ExtensionOID.OCSP_NO_CHECK +OID_POLICY_CONSTRAINTS = ExtensionOID.POLICY_CONSTRAINTS +OID_POLICY_MAPPINGS = ExtensionOID.POLICY_MAPPINGS +OID_SUBJECT_ALTERNATIVE_NAME = ExtensionOID.SUBJECT_ALTERNATIVE_NAME +OID_SUBJECT_DIRECTORY_ATTRIBUTES = ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES +OID_SUBJECT_INFORMATION_ACCESS = ExtensionOID.SUBJECT_INFORMATION_ACCESS +OID_SUBJECT_KEY_IDENTIFIER = ExtensionOID.SUBJECT_KEY_IDENTIFIER + +OID_DSA_WITH_SHA1 = SignatureAlgorithmOID.DSA_WITH_SHA1 +OID_DSA_WITH_SHA224 = SignatureAlgorithmOID.DSA_WITH_SHA224 +OID_DSA_WITH_SHA256 = SignatureAlgorithmOID.DSA_WITH_SHA256 +OID_ECDSA_WITH_SHA1 = SignatureAlgorithmOID.ECDSA_WITH_SHA1 +OID_ECDSA_WITH_SHA224 = SignatureAlgorithmOID.ECDSA_WITH_SHA224 +OID_ECDSA_WITH_SHA256 = SignatureAlgorithmOID.ECDSA_WITH_SHA256 +OID_ECDSA_WITH_SHA384 = SignatureAlgorithmOID.ECDSA_WITH_SHA384 +OID_ECDSA_WITH_SHA512 = SignatureAlgorithmOID.ECDSA_WITH_SHA512 +OID_RSA_WITH_MD5 = SignatureAlgorithmOID.RSA_WITH_MD5 +OID_RSA_WITH_SHA1 = SignatureAlgorithmOID.RSA_WITH_SHA1 +OID_RSA_WITH_SHA224 = SignatureAlgorithmOID.RSA_WITH_SHA224 +OID_RSA_WITH_SHA256 = SignatureAlgorithmOID.RSA_WITH_SHA256 +OID_RSA_WITH_SHA384 = SignatureAlgorithmOID.RSA_WITH_SHA384 +OID_RSA_WITH_SHA512 = SignatureAlgorithmOID.RSA_WITH_SHA512 +OID_RSASSA_PSS = SignatureAlgorithmOID.RSASSA_PSS + +OID_COMMON_NAME = NameOID.COMMON_NAME +OID_COUNTRY_NAME = NameOID.COUNTRY_NAME +OID_DOMAIN_COMPONENT = NameOID.DOMAIN_COMPONENT +OID_DN_QUALIFIER = NameOID.DN_QUALIFIER +OID_EMAIL_ADDRESS = NameOID.EMAIL_ADDRESS +OID_GENERATION_QUALIFIER = NameOID.GENERATION_QUALIFIER +OID_GIVEN_NAME = NameOID.GIVEN_NAME +OID_LOCALITY_NAME = NameOID.LOCALITY_NAME +OID_ORGANIZATIONAL_UNIT_NAME = NameOID.ORGANIZATIONAL_UNIT_NAME +OID_ORGANIZATION_NAME = NameOID.ORGANIZATION_NAME +OID_PSEUDONYM = NameOID.PSEUDONYM +OID_SERIAL_NUMBER = NameOID.SERIAL_NUMBER +OID_STATE_OR_PROVINCE_NAME = NameOID.STATE_OR_PROVINCE_NAME +OID_SURNAME = NameOID.SURNAME +OID_TITLE = NameOID.TITLE + +OID_CLIENT_AUTH = ExtendedKeyUsageOID.CLIENT_AUTH +OID_CODE_SIGNING = ExtendedKeyUsageOID.CODE_SIGNING +OID_EMAIL_PROTECTION = ExtendedKeyUsageOID.EMAIL_PROTECTION +OID_OCSP_SIGNING = ExtendedKeyUsageOID.OCSP_SIGNING +OID_SERVER_AUTH = ExtendedKeyUsageOID.SERVER_AUTH +OID_TIME_STAMPING = ExtendedKeyUsageOID.TIME_STAMPING + +OID_ANY_POLICY = CertificatePoliciesOID.ANY_POLICY +OID_CPS_QUALIFIER = CertificatePoliciesOID.CPS_QUALIFIER +OID_CPS_USER_NOTICE = CertificatePoliciesOID.CPS_USER_NOTICE + +OID_CERTIFICATE_ISSUER = CRLEntryExtensionOID.CERTIFICATE_ISSUER +OID_CRL_REASON = CRLEntryExtensionOID.CRL_REASON +OID_INVALIDITY_DATE = CRLEntryExtensionOID.INVALIDITY_DATE + +OID_CA_ISSUERS = AuthorityInformationAccessOID.CA_ISSUERS +OID_OCSP = AuthorityInformationAccessOID.OCSP + +__all__ = [ + "certificate_transparency", + "load_pem_x509_certificate", + "load_der_x509_certificate", + "load_pem_x509_csr", + "load_der_x509_csr", + "load_pem_x509_crl", + "load_der_x509_crl", + "random_serial_number", + "InvalidVersion", + "DeltaCRLIndicator", + "DuplicateExtension", + "ExtensionNotFound", + "UnsupportedGeneralNameType", + "NameAttribute", + "Name", + "RelativeDistinguishedName", + "ObjectIdentifier", + "ExtensionType", + "Extensions", + "Extension", + "ExtendedKeyUsage", + "FreshestCRL", + "TLSFeature", + "TLSFeatureType", + "OCSPNoCheck", + "BasicConstraints", + "CRLNumber", + "KeyUsage", + "AuthorityInformationAccess", + "AccessDescription", + "CertificatePolicies", + "PolicyInformation", + "UserNotice", + "NoticeReference", + "SubjectKeyIdentifier", + "NameConstraints", + "CRLDistributionPoints", + "DistributionPoint", + "ReasonFlags", + "InhibitAnyPolicy", + "SubjectAlternativeName", + "IssuerAlternativeName", + "AuthorityKeyIdentifier", + "GeneralNames", + "GeneralName", + "RFC822Name", + "DNSName", + "UniformResourceIdentifier", + "RegisteredID", + "DirectoryName", + "IPAddress", + "OtherName", + "Certificate", + "CertificateRevocationList", + "CertificateRevocationListBuilder", + "CertificateSigningRequest", + "RevokedCertificate", + "RevokedCertificateBuilder", + "CertificateSigningRequestBuilder", + "CertificateBuilder", + "Version", + "_SIG_OIDS_TO_HASH", + "OID_CA_ISSUERS", + "OID_OCSP", + "_GENERAL_NAMES", + "CertificateIssuer", + "CRLReason", + "InvalidityDate", + "UnrecognizedExtension", + "PolicyConstraints", + "PrecertificateSignedCertificateTimestamps", +] diff --git a/server/www/packages/packages-common/cryptography/x509/base.py b/server/www/packages/packages-common/cryptography/x509/base.py new file mode 100644 index 0000000..b14499c --- /dev/null +++ b/server/www/packages/packages-common/cryptography/x509/base.py @@ -0,0 +1,743 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +import datetime +import os +from enum import Enum + +import six + +from cryptography import utils +from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa +from cryptography.x509.extensions import Extension, ExtensionType +from cryptography.x509.name import Name + + +_UNIX_EPOCH = datetime.datetime(1970, 1, 1) + + +def _convert_to_naive_utc_time(time): + """Normalizes a datetime to a naive datetime in UTC. + + time -- datetime to normalize. Assumed to be in UTC if not timezone + aware. + """ + if time.tzinfo is not None: + offset = time.utcoffset() + offset = offset if offset else datetime.timedelta() + return time.replace(tzinfo=None) - offset + else: + return time + + +class Version(Enum): + v1 = 0 + v3 = 2 + + +def load_pem_x509_certificate(data, backend): + return backend.load_pem_x509_certificate(data) + + +def load_der_x509_certificate(data, backend): + return backend.load_der_x509_certificate(data) + + +def load_pem_x509_csr(data, backend): + return backend.load_pem_x509_csr(data) + + +def load_der_x509_csr(data, backend): + return backend.load_der_x509_csr(data) + + +def load_pem_x509_crl(data, backend): + return backend.load_pem_x509_crl(data) + + +def load_der_x509_crl(data, backend): + return backend.load_der_x509_crl(data) + + +class InvalidVersion(Exception): + def __init__(self, msg, parsed_version): + super(InvalidVersion, self).__init__(msg) + self.parsed_version = parsed_version + + +@six.add_metaclass(abc.ABCMeta) +class Certificate(object): + @abc.abstractmethod + def fingerprint(self, algorithm): + """ + Returns bytes using digest passed. + """ + + @abc.abstractproperty + def serial_number(self): + """ + Returns certificate serial number + """ + + @abc.abstractproperty + def version(self): + """ + Returns the certificate version + """ + + @abc.abstractmethod + def public_key(self): + """ + Returns the public key + """ + + @abc.abstractproperty + def not_valid_before(self): + """ + Not before time (represented as UTC datetime) + """ + + @abc.abstractproperty + def not_valid_after(self): + """ + Not after time (represented as UTC datetime) + """ + + @abc.abstractproperty + def issuer(self): + """ + Returns the issuer name object. + """ + + @abc.abstractproperty + def subject(self): + """ + Returns the subject name object. + """ + + @abc.abstractproperty + def signature_hash_algorithm(self): + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @abc.abstractproperty + def signature_algorithm_oid(self): + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @abc.abstractproperty + def extensions(self): + """ + Returns an Extensions object. + """ + + @abc.abstractproperty + def signature(self): + """ + Returns the signature bytes. + """ + + @abc.abstractproperty + def tbs_certificate_bytes(self): + """ + Returns the tbsCertificate payload bytes as defined in RFC 5280. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Checks equality. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Checks not equal. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Computes a hash. + """ + + @abc.abstractmethod + def public_bytes(self, encoding): + """ + Serializes the certificate to PEM or DER format. + """ + + +@six.add_metaclass(abc.ABCMeta) +class CertificateRevocationList(object): + @abc.abstractmethod + def public_bytes(self, encoding): + """ + Serializes the CRL to PEM or DER format. + """ + + @abc.abstractmethod + def fingerprint(self, algorithm): + """ + Returns bytes using digest passed. + """ + + @abc.abstractmethod + def get_revoked_certificate_by_serial_number(self, serial_number): + """ + Returns an instance of RevokedCertificate or None if the serial_number + is not in the CRL. + """ + + @abc.abstractproperty + def signature_hash_algorithm(self): + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @abc.abstractproperty + def signature_algorithm_oid(self): + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @abc.abstractproperty + def issuer(self): + """ + Returns the X509Name with the issuer of this CRL. + """ + + @abc.abstractproperty + def next_update(self): + """ + Returns the date of next update for this CRL. + """ + + @abc.abstractproperty + def last_update(self): + """ + Returns the date of last update for this CRL. + """ + + @abc.abstractproperty + def extensions(self): + """ + Returns an Extensions object containing a list of CRL extensions. + """ + + @abc.abstractproperty + def signature(self): + """ + Returns the signature bytes. + """ + + @abc.abstractproperty + def tbs_certlist_bytes(self): + """ + Returns the tbsCertList payload bytes as defined in RFC 5280. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Checks equality. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Checks not equal. + """ + + @abc.abstractmethod + def is_signature_valid(self, public_key): + """ + Verifies signature of revocation list against given public key. + """ + + +@six.add_metaclass(abc.ABCMeta) +class CertificateSigningRequest(object): + @abc.abstractmethod + def __eq__(self, other): + """ + Checks equality. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Checks not equal. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Computes a hash. + """ + + @abc.abstractmethod + def public_key(self): + """ + Returns the public key + """ + + @abc.abstractproperty + def subject(self): + """ + Returns the subject name object. + """ + + @abc.abstractproperty + def signature_hash_algorithm(self): + """ + Returns a HashAlgorithm corresponding to the type of the digest signed + in the certificate. + """ + + @abc.abstractproperty + def signature_algorithm_oid(self): + """ + Returns the ObjectIdentifier of the signature algorithm. + """ + + @abc.abstractproperty + def extensions(self): + """ + Returns the extensions in the signing request. + """ + + @abc.abstractmethod + def public_bytes(self, encoding): + """ + Encodes the request to PEM or DER format. + """ + + @abc.abstractproperty + def signature(self): + """ + Returns the signature bytes. + """ + + @abc.abstractproperty + def tbs_certrequest_bytes(self): + """ + Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC + 2986. + """ + + @abc.abstractproperty + def is_signature_valid(self): + """ + Verifies signature of signing request. + """ + + +@six.add_metaclass(abc.ABCMeta) +class RevokedCertificate(object): + @abc.abstractproperty + def serial_number(self): + """ + Returns the serial number of the revoked certificate. + """ + + @abc.abstractproperty + def revocation_date(self): + """ + Returns the date of when this certificate was revoked. + """ + + @abc.abstractproperty + def extensions(self): + """ + Returns an Extensions object containing a list of Revoked extensions. + """ + + +class CertificateSigningRequestBuilder(object): + def __init__(self, subject_name=None, extensions=[]): + """ + Creates an empty X.509 certificate request (v1). + """ + self._subject_name = subject_name + self._extensions = extensions + + def subject_name(self, name): + """ + Sets the certificate requestor's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError('Expecting x509.Name object.') + if self._subject_name is not None: + raise ValueError('The subject name may only be set once.') + return CertificateSigningRequestBuilder(name, self._extensions) + + def add_extension(self, extension, critical): + """ + Adds an X.509 extension to the certificate request. + """ + if not isinstance(extension, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extension.oid, critical, extension) + + # TODO: This is quadratic in the number of extensions + for e in self._extensions: + if e.oid == extension.oid: + raise ValueError('This extension has already been set.') + return CertificateSigningRequestBuilder( + self._subject_name, self._extensions + [extension] + ) + + def sign(self, private_key, algorithm, backend): + """ + Signs the request using the requestor's private key. + """ + if self._subject_name is None: + raise ValueError("A CertificateSigningRequest must have a subject") + return backend.create_x509_csr(self, private_key, algorithm) + + +class CertificateBuilder(object): + def __init__(self, issuer_name=None, subject_name=None, + public_key=None, serial_number=None, not_valid_before=None, + not_valid_after=None, extensions=[]): + self._version = Version.v3 + self._issuer_name = issuer_name + self._subject_name = subject_name + self._public_key = public_key + self._serial_number = serial_number + self._not_valid_before = not_valid_before + self._not_valid_after = not_valid_after + self._extensions = extensions + + def issuer_name(self, name): + """ + Sets the CA's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError('Expecting x509.Name object.') + if self._issuer_name is not None: + raise ValueError('The issuer name may only be set once.') + return CertificateBuilder( + name, self._subject_name, self._public_key, + self._serial_number, self._not_valid_before, + self._not_valid_after, self._extensions + ) + + def subject_name(self, name): + """ + Sets the requestor's distinguished name. + """ + if not isinstance(name, Name): + raise TypeError('Expecting x509.Name object.') + if self._subject_name is not None: + raise ValueError('The subject name may only be set once.') + return CertificateBuilder( + self._issuer_name, name, self._public_key, + self._serial_number, self._not_valid_before, + self._not_valid_after, self._extensions + ) + + def public_key(self, key): + """ + Sets the requestor's public key (as found in the signing request). + """ + if not isinstance(key, (dsa.DSAPublicKey, rsa.RSAPublicKey, + ec.EllipticCurvePublicKey)): + raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,' + ' or EllipticCurvePublicKey.') + if self._public_key is not None: + raise ValueError('The public key may only be set once.') + return CertificateBuilder( + self._issuer_name, self._subject_name, key, + self._serial_number, self._not_valid_before, + self._not_valid_after, self._extensions + ) + + def serial_number(self, number): + """ + Sets the certificate serial number. + """ + if not isinstance(number, six.integer_types): + raise TypeError('Serial number must be of integral type.') + if self._serial_number is not None: + raise ValueError('The serial number may only be set once.') + if number <= 0: + raise ValueError('The serial number should be positive.') + + # ASN.1 integers are always signed, so most significant bit must be + # zero. + if number.bit_length() >= 160: # As defined in RFC 5280 + raise ValueError('The serial number should not be more than 159 ' + 'bits.') + return CertificateBuilder( + self._issuer_name, self._subject_name, + self._public_key, number, self._not_valid_before, + self._not_valid_after, self._extensions + ) + + def not_valid_before(self, time): + """ + Sets the certificate activation time. + """ + if not isinstance(time, datetime.datetime): + raise TypeError('Expecting datetime object.') + if self._not_valid_before is not None: + raise ValueError('The not valid before may only be set once.') + time = _convert_to_naive_utc_time(time) + if time <= _UNIX_EPOCH: + raise ValueError('The not valid before date must be after the unix' + ' epoch (1970 January 1).') + if self._not_valid_after is not None and time > self._not_valid_after: + raise ValueError( + 'The not valid before date must be before the not valid after ' + 'date.' + ) + return CertificateBuilder( + self._issuer_name, self._subject_name, + self._public_key, self._serial_number, time, + self._not_valid_after, self._extensions + ) + + def not_valid_after(self, time): + """ + Sets the certificate expiration time. + """ + if not isinstance(time, datetime.datetime): + raise TypeError('Expecting datetime object.') + if self._not_valid_after is not None: + raise ValueError('The not valid after may only be set once.') + time = _convert_to_naive_utc_time(time) + if time <= _UNIX_EPOCH: + raise ValueError('The not valid after date must be after the unix' + ' epoch (1970 January 1).') + if (self._not_valid_before is not None and + time < self._not_valid_before): + raise ValueError( + 'The not valid after date must be after the not valid before ' + 'date.' + ) + return CertificateBuilder( + self._issuer_name, self._subject_name, + self._public_key, self._serial_number, self._not_valid_before, + time, self._extensions + ) + + def add_extension(self, extension, critical): + """ + Adds an X.509 extension to the certificate. + """ + if not isinstance(extension, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extension.oid, critical, extension) + + # TODO: This is quadratic in the number of extensions + for e in self._extensions: + if e.oid == extension.oid: + raise ValueError('This extension has already been set.') + + return CertificateBuilder( + self._issuer_name, self._subject_name, + self._public_key, self._serial_number, self._not_valid_before, + self._not_valid_after, self._extensions + [extension] + ) + + def sign(self, private_key, algorithm, backend): + """ + Signs the certificate using the CA's private key. + """ + if self._subject_name is None: + raise ValueError("A certificate must have a subject name") + + if self._issuer_name is None: + raise ValueError("A certificate must have an issuer name") + + if self._serial_number is None: + raise ValueError("A certificate must have a serial number") + + if self._not_valid_before is None: + raise ValueError("A certificate must have a not valid before time") + + if self._not_valid_after is None: + raise ValueError("A certificate must have a not valid after time") + + if self._public_key is None: + raise ValueError("A certificate must have a public key") + + return backend.create_x509_certificate(self, private_key, algorithm) + + +class CertificateRevocationListBuilder(object): + def __init__(self, issuer_name=None, last_update=None, next_update=None, + extensions=[], revoked_certificates=[]): + self._issuer_name = issuer_name + self._last_update = last_update + self._next_update = next_update + self._extensions = extensions + self._revoked_certificates = revoked_certificates + + def issuer_name(self, issuer_name): + if not isinstance(issuer_name, Name): + raise TypeError('Expecting x509.Name object.') + if self._issuer_name is not None: + raise ValueError('The issuer name may only be set once.') + return CertificateRevocationListBuilder( + issuer_name, self._last_update, self._next_update, + self._extensions, self._revoked_certificates + ) + + def last_update(self, last_update): + if not isinstance(last_update, datetime.datetime): + raise TypeError('Expecting datetime object.') + if self._last_update is not None: + raise ValueError('Last update may only be set once.') + last_update = _convert_to_naive_utc_time(last_update) + if last_update <= _UNIX_EPOCH: + raise ValueError('The last update date must be after the unix' + ' epoch (1970 January 1).') + if self._next_update is not None and last_update > self._next_update: + raise ValueError( + 'The last update date must be before the next update date.' + ) + return CertificateRevocationListBuilder( + self._issuer_name, last_update, self._next_update, + self._extensions, self._revoked_certificates + ) + + def next_update(self, next_update): + if not isinstance(next_update, datetime.datetime): + raise TypeError('Expecting datetime object.') + if self._next_update is not None: + raise ValueError('Last update may only be set once.') + next_update = _convert_to_naive_utc_time(next_update) + if next_update <= _UNIX_EPOCH: + raise ValueError('The last update date must be after the unix' + ' epoch (1970 January 1).') + if self._last_update is not None and next_update < self._last_update: + raise ValueError( + 'The next update date must be after the last update date.' + ) + return CertificateRevocationListBuilder( + self._issuer_name, self._last_update, next_update, + self._extensions, self._revoked_certificates + ) + + def add_extension(self, extension, critical): + """ + Adds an X.509 extension to the certificate revocation list. + """ + if not isinstance(extension, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extension.oid, critical, extension) + + # TODO: This is quadratic in the number of extensions + for e in self._extensions: + if e.oid == extension.oid: + raise ValueError('This extension has already been set.') + return CertificateRevocationListBuilder( + self._issuer_name, self._last_update, self._next_update, + self._extensions + [extension], self._revoked_certificates + ) + + def add_revoked_certificate(self, revoked_certificate): + """ + Adds a revoked certificate to the CRL. + """ + if not isinstance(revoked_certificate, RevokedCertificate): + raise TypeError("Must be an instance of RevokedCertificate") + + return CertificateRevocationListBuilder( + self._issuer_name, self._last_update, + self._next_update, self._extensions, + self._revoked_certificates + [revoked_certificate] + ) + + def sign(self, private_key, algorithm, backend): + if self._issuer_name is None: + raise ValueError("A CRL must have an issuer name") + + if self._last_update is None: + raise ValueError("A CRL must have a last update time") + + if self._next_update is None: + raise ValueError("A CRL must have a next update time") + + return backend.create_x509_crl(self, private_key, algorithm) + + +class RevokedCertificateBuilder(object): + def __init__(self, serial_number=None, revocation_date=None, + extensions=[]): + self._serial_number = serial_number + self._revocation_date = revocation_date + self._extensions = extensions + + def serial_number(self, number): + if not isinstance(number, six.integer_types): + raise TypeError('Serial number must be of integral type.') + if self._serial_number is not None: + raise ValueError('The serial number may only be set once.') + if number <= 0: + raise ValueError('The serial number should be positive') + + # ASN.1 integers are always signed, so most significant bit must be + # zero. + if number.bit_length() >= 160: # As defined in RFC 5280 + raise ValueError('The serial number should not be more than 159 ' + 'bits.') + return RevokedCertificateBuilder( + number, self._revocation_date, self._extensions + ) + + def revocation_date(self, time): + if not isinstance(time, datetime.datetime): + raise TypeError('Expecting datetime object.') + if self._revocation_date is not None: + raise ValueError('The revocation date may only be set once.') + time = _convert_to_naive_utc_time(time) + if time <= _UNIX_EPOCH: + raise ValueError('The revocation date must be after the unix' + ' epoch (1970 January 1).') + return RevokedCertificateBuilder( + self._serial_number, time, self._extensions + ) + + def add_extension(self, extension, critical): + if not isinstance(extension, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extension.oid, critical, extension) + + # TODO: This is quadratic in the number of extensions + for e in self._extensions: + if e.oid == extension.oid: + raise ValueError('This extension has already been set.') + return RevokedCertificateBuilder( + self._serial_number, self._revocation_date, + self._extensions + [extension] + ) + + def build(self, backend): + if self._serial_number is None: + raise ValueError("A revoked certificate must have a serial number") + if self._revocation_date is None: + raise ValueError( + "A revoked certificate must have a revocation date" + ) + + return backend.create_x509_revoked_certificate(self) + + +def random_serial_number(): + return utils.int_from_bytes(os.urandom(20), "big") >> 1 diff --git a/server/www/packages/packages-common/cryptography/x509/certificate_transparency.py b/server/www/packages/packages-common/cryptography/x509/certificate_transparency.py new file mode 100644 index 0000000..d00fe81 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/x509/certificate_transparency.py @@ -0,0 +1,46 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +from enum import Enum + +import six + + +class LogEntryType(Enum): + X509_CERTIFICATE = 0 + PRE_CERTIFICATE = 1 + + +class Version(Enum): + v1 = 0 + + +@six.add_metaclass(abc.ABCMeta) +class SignedCertificateTimestamp(object): + @abc.abstractproperty + def version(self): + """ + Returns the SCT version. + """ + + @abc.abstractproperty + def log_id(self): + """ + Returns an identifier indicating which log this SCT is for. + """ + + @abc.abstractproperty + def timestamp(self): + """ + Returns the timestamp for this SCT. + """ + + @abc.abstractproperty + def entry_type(self): + """ + Returns whether this is an SCT for a certificate or pre-certificate. + """ diff --git a/server/www/packages/packages-common/cryptography/x509/extensions.py b/server/www/packages/packages-common/cryptography/x509/extensions.py new file mode 100644 index 0000000..eb4b927 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/x509/extensions.py @@ -0,0 +1,1429 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +import datetime +import hashlib +import ipaddress +from enum import Enum + +from asn1crypto.keys import PublicKeyInfo + +import six + +from cryptography import utils +from cryptography.hazmat.primitives import constant_time, serialization +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey +from cryptography.x509.certificate_transparency import ( + SignedCertificateTimestamp +) +from cryptography.x509.general_name import GeneralName, IPAddress, OtherName +from cryptography.x509.name import RelativeDistinguishedName +from cryptography.x509.oid import ( + CRLEntryExtensionOID, ExtensionOID, ObjectIdentifier +) + + +def _key_identifier_from_public_key(public_key): + if isinstance(public_key, RSAPublicKey): + data = public_key.public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.PKCS1, + ) + elif isinstance(public_key, EllipticCurvePublicKey): + data = public_key.public_numbers().encode_point() + else: + # This is a very slow way to do this. + serialized = public_key.public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.SubjectPublicKeyInfo + ) + + data = six.binary_type(PublicKeyInfo.load(serialized)['public_key']) + + return hashlib.sha1(data).digest() + + +class DuplicateExtension(Exception): + def __init__(self, msg, oid): + super(DuplicateExtension, self).__init__(msg) + self.oid = oid + + +class ExtensionNotFound(Exception): + def __init__(self, msg, oid): + super(ExtensionNotFound, self).__init__(msg) + self.oid = oid + + +@six.add_metaclass(abc.ABCMeta) +class ExtensionType(object): + @abc.abstractproperty + def oid(self): + """ + Returns the oid associated with the given extension type. + """ + + +class Extensions(object): + def __init__(self, extensions): + self._extensions = extensions + + def get_extension_for_oid(self, oid): + for ext in self: + if ext.oid == oid: + return ext + + raise ExtensionNotFound("No {0} extension was found".format(oid), oid) + + def get_extension_for_class(self, extclass): + if extclass is UnrecognizedExtension: + raise TypeError( + "UnrecognizedExtension can't be used with " + "get_extension_for_class because more than one instance of the" + " class may be present." + ) + + for ext in self: + if isinstance(ext.value, extclass): + return ext + + raise ExtensionNotFound( + "No {0} extension was found".format(extclass), extclass.oid + ) + + def __iter__(self): + return iter(self._extensions) + + def __len__(self): + return len(self._extensions) + + def __getitem__(self, idx): + return self._extensions[idx] + + def __repr__(self): + return ( + "".format(self._extensions) + ) + + +@utils.register_interface(ExtensionType) +class CRLNumber(object): + oid = ExtensionOID.CRL_NUMBER + + def __init__(self, crl_number): + if not isinstance(crl_number, six.integer_types): + raise TypeError("crl_number must be an integer") + + self._crl_number = crl_number + + def __eq__(self, other): + if not isinstance(other, CRLNumber): + return NotImplemented + + return self.crl_number == other.crl_number + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.crl_number) + + def __repr__(self): + return "".format(self.crl_number) + + crl_number = utils.read_only_property("_crl_number") + + +@utils.register_interface(ExtensionType) +class AuthorityKeyIdentifier(object): + oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER + + def __init__(self, key_identifier, authority_cert_issuer, + authority_cert_serial_number): + if (authority_cert_issuer is None) != ( + authority_cert_serial_number is None + ): + raise ValueError( + "authority_cert_issuer and authority_cert_serial_number " + "must both be present or both None" + ) + + if authority_cert_issuer is not None: + authority_cert_issuer = list(authority_cert_issuer) + if not all( + isinstance(x, GeneralName) for x in authority_cert_issuer + ): + raise TypeError( + "authority_cert_issuer must be a list of GeneralName " + "objects" + ) + + if authority_cert_serial_number is not None and not isinstance( + authority_cert_serial_number, six.integer_types + ): + raise TypeError( + "authority_cert_serial_number must be an integer" + ) + + self._key_identifier = key_identifier + self._authority_cert_issuer = authority_cert_issuer + self._authority_cert_serial_number = authority_cert_serial_number + + @classmethod + def from_issuer_public_key(cls, public_key): + digest = _key_identifier_from_public_key(public_key) + return cls( + key_identifier=digest, + authority_cert_issuer=None, + authority_cert_serial_number=None + ) + + @classmethod + def from_issuer_subject_key_identifier(cls, ski): + return cls( + key_identifier=ski.value.digest, + authority_cert_issuer=None, + authority_cert_serial_number=None + ) + + def __repr__(self): + return ( + "".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, AuthorityKeyIdentifier): + return NotImplemented + + return ( + self.key_identifier == other.key_identifier and + self.authority_cert_issuer == other.authority_cert_issuer and + self.authority_cert_serial_number == + other.authority_cert_serial_number + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + if self.authority_cert_issuer is None: + aci = None + else: + aci = tuple(self.authority_cert_issuer) + return hash(( + self.key_identifier, aci, self.authority_cert_serial_number + )) + + key_identifier = utils.read_only_property("_key_identifier") + authority_cert_issuer = utils.read_only_property("_authority_cert_issuer") + authority_cert_serial_number = utils.read_only_property( + "_authority_cert_serial_number" + ) + + +@utils.register_interface(ExtensionType) +class SubjectKeyIdentifier(object): + oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER + + def __init__(self, digest): + self._digest = digest + + @classmethod + def from_public_key(cls, public_key): + return cls(_key_identifier_from_public_key(public_key)) + + digest = utils.read_only_property("_digest") + + def __repr__(self): + return "".format(self.digest) + + def __eq__(self, other): + if not isinstance(other, SubjectKeyIdentifier): + return NotImplemented + + return constant_time.bytes_eq(self.digest, other.digest) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.digest) + + +@utils.register_interface(ExtensionType) +class AuthorityInformationAccess(object): + oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS + + def __init__(self, descriptions): + descriptions = list(descriptions) + if not all(isinstance(x, AccessDescription) for x in descriptions): + raise TypeError( + "Every item in the descriptions list must be an " + "AccessDescription" + ) + + self._descriptions = descriptions + + def __iter__(self): + return iter(self._descriptions) + + def __len__(self): + return len(self._descriptions) + + def __repr__(self): + return "".format(self._descriptions) + + def __eq__(self, other): + if not isinstance(other, AuthorityInformationAccess): + return NotImplemented + + return self._descriptions == other._descriptions + + def __ne__(self, other): + return not self == other + + def __getitem__(self, idx): + return self._descriptions[idx] + + def __hash__(self): + return hash(tuple(self._descriptions)) + + +class AccessDescription(object): + def __init__(self, access_method, access_location): + if not isinstance(access_method, ObjectIdentifier): + raise TypeError("access_method must be an ObjectIdentifier") + + if not isinstance(access_location, GeneralName): + raise TypeError("access_location must be a GeneralName") + + self._access_method = access_method + self._access_location = access_location + + def __repr__(self): + return ( + "".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, AccessDescription): + return NotImplemented + + return ( + self.access_method == other.access_method and + self.access_location == other.access_location + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.access_method, self.access_location)) + + access_method = utils.read_only_property("_access_method") + access_location = utils.read_only_property("_access_location") + + +@utils.register_interface(ExtensionType) +class BasicConstraints(object): + oid = ExtensionOID.BASIC_CONSTRAINTS + + def __init__(self, ca, path_length): + if not isinstance(ca, bool): + raise TypeError("ca must be a boolean value") + + if path_length is not None and not ca: + raise ValueError("path_length must be None when ca is False") + + if ( + path_length is not None and + (not isinstance(path_length, six.integer_types) or path_length < 0) + ): + raise TypeError( + "path_length must be a non-negative integer or None" + ) + + self._ca = ca + self._path_length = path_length + + ca = utils.read_only_property("_ca") + path_length = utils.read_only_property("_path_length") + + def __repr__(self): + return ("").format(self) + + def __eq__(self, other): + if not isinstance(other, BasicConstraints): + return NotImplemented + + return self.ca == other.ca and self.path_length == other.path_length + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.ca, self.path_length)) + + +@utils.register_interface(ExtensionType) +class DeltaCRLIndicator(object): + oid = ExtensionOID.DELTA_CRL_INDICATOR + + def __init__(self, crl_number): + if not isinstance(crl_number, six.integer_types): + raise TypeError("crl_number must be an integer") + + self._crl_number = crl_number + + crl_number = utils.read_only_property("_crl_number") + + def __eq__(self, other): + if not isinstance(other, DeltaCRLIndicator): + return NotImplemented + + return self.crl_number == other.crl_number + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.crl_number) + + def __repr__(self): + return "".format(self) + + +@utils.register_interface(ExtensionType) +class CRLDistributionPoints(object): + oid = ExtensionOID.CRL_DISTRIBUTION_POINTS + + def __init__(self, distribution_points): + distribution_points = list(distribution_points) + if not all( + isinstance(x, DistributionPoint) for x in distribution_points + ): + raise TypeError( + "distribution_points must be a list of DistributionPoint " + "objects" + ) + + self._distribution_points = distribution_points + + def __iter__(self): + return iter(self._distribution_points) + + def __len__(self): + return len(self._distribution_points) + + def __repr__(self): + return "".format(self._distribution_points) + + def __eq__(self, other): + if not isinstance(other, CRLDistributionPoints): + return NotImplemented + + return self._distribution_points == other._distribution_points + + def __ne__(self, other): + return not self == other + + def __getitem__(self, idx): + return self._distribution_points[idx] + + def __hash__(self): + return hash(tuple(self._distribution_points)) + + +@utils.register_interface(ExtensionType) +class FreshestCRL(object): + oid = ExtensionOID.FRESHEST_CRL + + def __init__(self, distribution_points): + distribution_points = list(distribution_points) + if not all( + isinstance(x, DistributionPoint) for x in distribution_points + ): + raise TypeError( + "distribution_points must be a list of DistributionPoint " + "objects" + ) + + self._distribution_points = distribution_points + + def __iter__(self): + return iter(self._distribution_points) + + def __len__(self): + return len(self._distribution_points) + + def __repr__(self): + return "".format(self._distribution_points) + + def __eq__(self, other): + if not isinstance(other, FreshestCRL): + return NotImplemented + + return self._distribution_points == other._distribution_points + + def __ne__(self, other): + return not self == other + + def __getitem__(self, idx): + return self._distribution_points[idx] + + def __hash__(self): + return hash(tuple(self._distribution_points)) + + +class DistributionPoint(object): + def __init__(self, full_name, relative_name, reasons, crl_issuer): + if full_name and relative_name: + raise ValueError( + "You cannot provide both full_name and relative_name, at " + "least one must be None." + ) + + if full_name: + full_name = list(full_name) + if not all(isinstance(x, GeneralName) for x in full_name): + raise TypeError( + "full_name must be a list of GeneralName objects" + ) + + if relative_name: + if not isinstance(relative_name, RelativeDistinguishedName): + raise TypeError( + "relative_name must be a RelativeDistinguishedName" + ) + + if crl_issuer: + crl_issuer = list(crl_issuer) + if not all(isinstance(x, GeneralName) for x in crl_issuer): + raise TypeError( + "crl_issuer must be None or a list of general names" + ) + + if reasons and (not isinstance(reasons, frozenset) or not all( + isinstance(x, ReasonFlags) for x in reasons + )): + raise TypeError("reasons must be None or frozenset of ReasonFlags") + + if reasons and ( + ReasonFlags.unspecified in reasons or + ReasonFlags.remove_from_crl in reasons + ): + raise ValueError( + "unspecified and remove_from_crl are not valid reasons in a " + "DistributionPoint" + ) + + if reasons and not crl_issuer and not (full_name or relative_name): + raise ValueError( + "You must supply crl_issuer, full_name, or relative_name when " + "reasons is not None" + ) + + self._full_name = full_name + self._relative_name = relative_name + self._reasons = reasons + self._crl_issuer = crl_issuer + + def __repr__(self): + return ( + "".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, DistributionPoint): + return NotImplemented + + return ( + self.full_name == other.full_name and + self.relative_name == other.relative_name and + self.reasons == other.reasons and + self.crl_issuer == other.crl_issuer + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + if self.full_name is not None: + fn = tuple(self.full_name) + else: + fn = None + + if self.crl_issuer is not None: + crl_issuer = tuple(self.crl_issuer) + else: + crl_issuer = None + + return hash((fn, self.relative_name, self.reasons, crl_issuer)) + + full_name = utils.read_only_property("_full_name") + relative_name = utils.read_only_property("_relative_name") + reasons = utils.read_only_property("_reasons") + crl_issuer = utils.read_only_property("_crl_issuer") + + +class ReasonFlags(Enum): + unspecified = "unspecified" + key_compromise = "keyCompromise" + ca_compromise = "cACompromise" + affiliation_changed = "affiliationChanged" + superseded = "superseded" + cessation_of_operation = "cessationOfOperation" + certificate_hold = "certificateHold" + privilege_withdrawn = "privilegeWithdrawn" + aa_compromise = "aACompromise" + remove_from_crl = "removeFromCRL" + + +@utils.register_interface(ExtensionType) +class PolicyConstraints(object): + oid = ExtensionOID.POLICY_CONSTRAINTS + + def __init__(self, require_explicit_policy, inhibit_policy_mapping): + if require_explicit_policy is not None and not isinstance( + require_explicit_policy, six.integer_types + ): + raise TypeError( + "require_explicit_policy must be a non-negative integer or " + "None" + ) + + if inhibit_policy_mapping is not None and not isinstance( + inhibit_policy_mapping, six.integer_types + ): + raise TypeError( + "inhibit_policy_mapping must be a non-negative integer or None" + ) + + if inhibit_policy_mapping is None and require_explicit_policy is None: + raise ValueError( + "At least one of require_explicit_policy and " + "inhibit_policy_mapping must not be None" + ) + + self._require_explicit_policy = require_explicit_policy + self._inhibit_policy_mapping = inhibit_policy_mapping + + def __repr__(self): + return ( + u"".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, PolicyConstraints): + return NotImplemented + + return ( + self.require_explicit_policy == other.require_explicit_policy and + self.inhibit_policy_mapping == other.inhibit_policy_mapping + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash( + (self.require_explicit_policy, self.inhibit_policy_mapping) + ) + + require_explicit_policy = utils.read_only_property( + "_require_explicit_policy" + ) + inhibit_policy_mapping = utils.read_only_property( + "_inhibit_policy_mapping" + ) + + +@utils.register_interface(ExtensionType) +class CertificatePolicies(object): + oid = ExtensionOID.CERTIFICATE_POLICIES + + def __init__(self, policies): + policies = list(policies) + if not all(isinstance(x, PolicyInformation) for x in policies): + raise TypeError( + "Every item in the policies list must be a " + "PolicyInformation" + ) + + self._policies = policies + + def __iter__(self): + return iter(self._policies) + + def __len__(self): + return len(self._policies) + + def __repr__(self): + return "".format(self._policies) + + def __eq__(self, other): + if not isinstance(other, CertificatePolicies): + return NotImplemented + + return self._policies == other._policies + + def __ne__(self, other): + return not self == other + + def __getitem__(self, idx): + return self._policies[idx] + + def __hash__(self): + return hash(tuple(self._policies)) + + +class PolicyInformation(object): + def __init__(self, policy_identifier, policy_qualifiers): + if not isinstance(policy_identifier, ObjectIdentifier): + raise TypeError("policy_identifier must be an ObjectIdentifier") + + self._policy_identifier = policy_identifier + + if policy_qualifiers: + policy_qualifiers = list(policy_qualifiers) + if not all( + isinstance(x, (six.text_type, UserNotice)) + for x in policy_qualifiers + ): + raise TypeError( + "policy_qualifiers must be a list of strings and/or " + "UserNotice objects or None" + ) + + self._policy_qualifiers = policy_qualifiers + + def __repr__(self): + return ( + "".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, PolicyInformation): + return NotImplemented + + return ( + self.policy_identifier == other.policy_identifier and + self.policy_qualifiers == other.policy_qualifiers + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + if self.policy_qualifiers is not None: + pq = tuple(self.policy_qualifiers) + else: + pq = None + + return hash((self.policy_identifier, pq)) + + policy_identifier = utils.read_only_property("_policy_identifier") + policy_qualifiers = utils.read_only_property("_policy_qualifiers") + + +class UserNotice(object): + def __init__(self, notice_reference, explicit_text): + if notice_reference and not isinstance( + notice_reference, NoticeReference + ): + raise TypeError( + "notice_reference must be None or a NoticeReference" + ) + + self._notice_reference = notice_reference + self._explicit_text = explicit_text + + def __repr__(self): + return ( + "".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, UserNotice): + return NotImplemented + + return ( + self.notice_reference == other.notice_reference and + self.explicit_text == other.explicit_text + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.notice_reference, self.explicit_text)) + + notice_reference = utils.read_only_property("_notice_reference") + explicit_text = utils.read_only_property("_explicit_text") + + +class NoticeReference(object): + def __init__(self, organization, notice_numbers): + self._organization = organization + notice_numbers = list(notice_numbers) + if not all(isinstance(x, int) for x in notice_numbers): + raise TypeError( + "notice_numbers must be a list of integers" + ) + + self._notice_numbers = notice_numbers + + def __repr__(self): + return ( + "".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, NoticeReference): + return NotImplemented + + return ( + self.organization == other.organization and + self.notice_numbers == other.notice_numbers + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.organization, tuple(self.notice_numbers))) + + organization = utils.read_only_property("_organization") + notice_numbers = utils.read_only_property("_notice_numbers") + + +@utils.register_interface(ExtensionType) +class ExtendedKeyUsage(object): + oid = ExtensionOID.EXTENDED_KEY_USAGE + + def __init__(self, usages): + usages = list(usages) + if not all(isinstance(x, ObjectIdentifier) for x in usages): + raise TypeError( + "Every item in the usages list must be an ObjectIdentifier" + ) + + self._usages = usages + + def __iter__(self): + return iter(self._usages) + + def __len__(self): + return len(self._usages) + + def __repr__(self): + return "".format(self._usages) + + def __eq__(self, other): + if not isinstance(other, ExtendedKeyUsage): + return NotImplemented + + return self._usages == other._usages + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(tuple(self._usages)) + + +@utils.register_interface(ExtensionType) +class OCSPNoCheck(object): + oid = ExtensionOID.OCSP_NO_CHECK + + +@utils.register_interface(ExtensionType) +class TLSFeature(object): + oid = ExtensionOID.TLS_FEATURE + + def __init__(self, features): + features = list(features) + if ( + not all(isinstance(x, TLSFeatureType) for x in features) or + len(features) == 0 + ): + raise TypeError( + "features must be a list of elements from the TLSFeatureType " + "enum" + ) + + self._features = features + + def __iter__(self): + return iter(self._features) + + def __len__(self): + return len(self._features) + + def __repr__(self): + return "".format(self) + + def __eq__(self, other): + if not isinstance(other, TLSFeature): + return NotImplemented + + return self._features == other._features + + def __getitem__(self, idx): + return self._features[idx] + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(tuple(self._features)) + + +class TLSFeatureType(Enum): + # status_request is defined in RFC 6066 and is used for what is commonly + # called OCSP Must-Staple when present in the TLS Feature extension in an + # X.509 certificate. + status_request = 5 + # status_request_v2 is defined in RFC 6961 and allows multiple OCSP + # responses to be provided. It is not currently in use by clients or + # servers. + status_request_v2 = 17 + + +_TLS_FEATURE_TYPE_TO_ENUM = dict((x.value, x) for x in TLSFeatureType) + + +@utils.register_interface(ExtensionType) +class InhibitAnyPolicy(object): + oid = ExtensionOID.INHIBIT_ANY_POLICY + + def __init__(self, skip_certs): + if not isinstance(skip_certs, six.integer_types): + raise TypeError("skip_certs must be an integer") + + if skip_certs < 0: + raise ValueError("skip_certs must be a non-negative integer") + + self._skip_certs = skip_certs + + def __repr__(self): + return "".format(self) + + def __eq__(self, other): + if not isinstance(other, InhibitAnyPolicy): + return NotImplemented + + return self.skip_certs == other.skip_certs + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.skip_certs) + + skip_certs = utils.read_only_property("_skip_certs") + + +@utils.register_interface(ExtensionType) +class KeyUsage(object): + oid = ExtensionOID.KEY_USAGE + + def __init__(self, digital_signature, content_commitment, key_encipherment, + data_encipherment, key_agreement, key_cert_sign, crl_sign, + encipher_only, decipher_only): + if not key_agreement and (encipher_only or decipher_only): + raise ValueError( + "encipher_only and decipher_only can only be true when " + "key_agreement is true" + ) + + self._digital_signature = digital_signature + self._content_commitment = content_commitment + self._key_encipherment = key_encipherment + self._data_encipherment = data_encipherment + self._key_agreement = key_agreement + self._key_cert_sign = key_cert_sign + self._crl_sign = crl_sign + self._encipher_only = encipher_only + self._decipher_only = decipher_only + + digital_signature = utils.read_only_property("_digital_signature") + content_commitment = utils.read_only_property("_content_commitment") + key_encipherment = utils.read_only_property("_key_encipherment") + data_encipherment = utils.read_only_property("_data_encipherment") + key_agreement = utils.read_only_property("_key_agreement") + key_cert_sign = utils.read_only_property("_key_cert_sign") + crl_sign = utils.read_only_property("_crl_sign") + + @property + def encipher_only(self): + if not self.key_agreement: + raise ValueError( + "encipher_only is undefined unless key_agreement is true" + ) + else: + return self._encipher_only + + @property + def decipher_only(self): + if not self.key_agreement: + raise ValueError( + "decipher_only is undefined unless key_agreement is true" + ) + else: + return self._decipher_only + + def __repr__(self): + try: + encipher_only = self.encipher_only + decipher_only = self.decipher_only + except ValueError: + encipher_only = None + decipher_only = None + + return ("").format( + self, encipher_only, decipher_only) + + def __eq__(self, other): + if not isinstance(other, KeyUsage): + return NotImplemented + + return ( + self.digital_signature == other.digital_signature and + self.content_commitment == other.content_commitment and + self.key_encipherment == other.key_encipherment and + self.data_encipherment == other.data_encipherment and + self.key_agreement == other.key_agreement and + self.key_cert_sign == other.key_cert_sign and + self.crl_sign == other.crl_sign and + self._encipher_only == other._encipher_only and + self._decipher_only == other._decipher_only + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(( + self.digital_signature, self.content_commitment, + self.key_encipherment, self.data_encipherment, + self.key_agreement, self.key_cert_sign, + self.crl_sign, self._encipher_only, + self._decipher_only + )) + + +@utils.register_interface(ExtensionType) +class NameConstraints(object): + oid = ExtensionOID.NAME_CONSTRAINTS + + def __init__(self, permitted_subtrees, excluded_subtrees): + if permitted_subtrees is not None: + permitted_subtrees = list(permitted_subtrees) + if not all( + isinstance(x, GeneralName) for x in permitted_subtrees + ): + raise TypeError( + "permitted_subtrees must be a list of GeneralName objects " + "or None" + ) + + self._validate_ip_name(permitted_subtrees) + + if excluded_subtrees is not None: + excluded_subtrees = list(excluded_subtrees) + if not all( + isinstance(x, GeneralName) for x in excluded_subtrees + ): + raise TypeError( + "excluded_subtrees must be a list of GeneralName objects " + "or None" + ) + + self._validate_ip_name(excluded_subtrees) + + if permitted_subtrees is None and excluded_subtrees is None: + raise ValueError( + "At least one of permitted_subtrees and excluded_subtrees " + "must not be None" + ) + + self._permitted_subtrees = permitted_subtrees + self._excluded_subtrees = excluded_subtrees + + def __eq__(self, other): + if not isinstance(other, NameConstraints): + return NotImplemented + + return ( + self.excluded_subtrees == other.excluded_subtrees and + self.permitted_subtrees == other.permitted_subtrees + ) + + def __ne__(self, other): + return not self == other + + def _validate_ip_name(self, tree): + if any(isinstance(name, IPAddress) and not isinstance( + name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network) + ) for name in tree): + raise TypeError( + "IPAddress name constraints must be an IPv4Network or" + " IPv6Network object" + ) + + def __repr__(self): + return ( + u"".format(self) + ) + + def __hash__(self): + if self.permitted_subtrees is not None: + ps = tuple(self.permitted_subtrees) + else: + ps = None + + if self.excluded_subtrees is not None: + es = tuple(self.excluded_subtrees) + else: + es = None + + return hash((ps, es)) + + permitted_subtrees = utils.read_only_property("_permitted_subtrees") + excluded_subtrees = utils.read_only_property("_excluded_subtrees") + + +class Extension(object): + def __init__(self, oid, critical, value): + if not isinstance(oid, ObjectIdentifier): + raise TypeError( + "oid argument must be an ObjectIdentifier instance." + ) + + if not isinstance(critical, bool): + raise TypeError("critical must be a boolean value") + + self._oid = oid + self._critical = critical + self._value = value + + oid = utils.read_only_property("_oid") + critical = utils.read_only_property("_critical") + value = utils.read_only_property("_value") + + def __repr__(self): + return ("").format(self) + + def __eq__(self, other): + if not isinstance(other, Extension): + return NotImplemented + + return ( + self.oid == other.oid and + self.critical == other.critical and + self.value == other.value + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.oid, self.critical, self.value)) + + +class GeneralNames(object): + def __init__(self, general_names): + general_names = list(general_names) + if not all(isinstance(x, GeneralName) for x in general_names): + raise TypeError( + "Every item in the general_names list must be an " + "object conforming to the GeneralName interface" + ) + + self._general_names = general_names + + def __iter__(self): + return iter(self._general_names) + + def __len__(self): + return len(self._general_names) + + def get_values_for_type(self, type): + # Return the value of each GeneralName, except for OtherName instances + # which we return directly because it has two important properties not + # just one value. + objs = (i for i in self if isinstance(i, type)) + if type != OtherName: + objs = (i.value for i in objs) + return list(objs) + + def __repr__(self): + return "".format(self._general_names) + + def __eq__(self, other): + if not isinstance(other, GeneralNames): + return NotImplemented + + return self._general_names == other._general_names + + def __ne__(self, other): + return not self == other + + def __getitem__(self, idx): + return self._general_names[idx] + + def __hash__(self): + return hash(tuple(self._general_names)) + + +@utils.register_interface(ExtensionType) +class SubjectAlternativeName(object): + oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME + + def __init__(self, general_names): + self._general_names = GeneralNames(general_names) + + def __iter__(self): + return iter(self._general_names) + + def __len__(self): + return len(self._general_names) + + def get_values_for_type(self, type): + return self._general_names.get_values_for_type(type) + + def __repr__(self): + return "".format(self._general_names) + + def __eq__(self, other): + if not isinstance(other, SubjectAlternativeName): + return NotImplemented + + return self._general_names == other._general_names + + def __getitem__(self, idx): + return self._general_names[idx] + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self._general_names) + + +@utils.register_interface(ExtensionType) +class IssuerAlternativeName(object): + oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME + + def __init__(self, general_names): + self._general_names = GeneralNames(general_names) + + def __iter__(self): + return iter(self._general_names) + + def __len__(self): + return len(self._general_names) + + def get_values_for_type(self, type): + return self._general_names.get_values_for_type(type) + + def __repr__(self): + return "".format(self._general_names) + + def __eq__(self, other): + if not isinstance(other, IssuerAlternativeName): + return NotImplemented + + return self._general_names == other._general_names + + def __ne__(self, other): + return not self == other + + def __getitem__(self, idx): + return self._general_names[idx] + + def __hash__(self): + return hash(self._general_names) + + +@utils.register_interface(ExtensionType) +class CertificateIssuer(object): + oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER + + def __init__(self, general_names): + self._general_names = GeneralNames(general_names) + + def __iter__(self): + return iter(self._general_names) + + def __len__(self): + return len(self._general_names) + + def get_values_for_type(self, type): + return self._general_names.get_values_for_type(type) + + def __repr__(self): + return "".format(self._general_names) + + def __eq__(self, other): + if not isinstance(other, CertificateIssuer): + return NotImplemented + + return self._general_names == other._general_names + + def __ne__(self, other): + return not self == other + + def __getitem__(self, idx): + return self._general_names[idx] + + def __hash__(self): + return hash(self._general_names) + + +@utils.register_interface(ExtensionType) +class CRLReason(object): + oid = CRLEntryExtensionOID.CRL_REASON + + def __init__(self, reason): + if not isinstance(reason, ReasonFlags): + raise TypeError("reason must be an element from ReasonFlags") + + self._reason = reason + + def __repr__(self): + return "".format(self._reason) + + def __eq__(self, other): + if not isinstance(other, CRLReason): + return NotImplemented + + return self.reason == other.reason + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.reason) + + reason = utils.read_only_property("_reason") + + +@utils.register_interface(ExtensionType) +class InvalidityDate(object): + oid = CRLEntryExtensionOID.INVALIDITY_DATE + + def __init__(self, invalidity_date): + if not isinstance(invalidity_date, datetime.datetime): + raise TypeError("invalidity_date must be a datetime.datetime") + + self._invalidity_date = invalidity_date + + def __repr__(self): + return "".format( + self._invalidity_date + ) + + def __eq__(self, other): + if not isinstance(other, InvalidityDate): + return NotImplemented + + return self.invalidity_date == other.invalidity_date + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.invalidity_date) + + invalidity_date = utils.read_only_property("_invalidity_date") + + +@utils.register_interface(ExtensionType) +class PrecertificateSignedCertificateTimestamps(object): + oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS + + def __init__(self, signed_certificate_timestamps): + signed_certificate_timestamps = list(signed_certificate_timestamps) + if not all( + isinstance(sct, SignedCertificateTimestamp) + for sct in signed_certificate_timestamps + ): + raise TypeError( + "Every item in the signed_certificate_timestamps list must be " + "a SignedCertificateTimestamp" + ) + self._signed_certificate_timestamps = signed_certificate_timestamps + + def __iter__(self): + return iter(self._signed_certificate_timestamps) + + def __len__(self): + return len(self._signed_certificate_timestamps) + + def __getitem__(self, idx): + return self._signed_certificate_timestamps[idx] + + def __repr__(self): + return ( + "".format( + list(self) + ) + ) + + +@utils.register_interface(ExtensionType) +class UnrecognizedExtension(object): + def __init__(self, oid, value): + if not isinstance(oid, ObjectIdentifier): + raise TypeError("oid must be an ObjectIdentifier") + self._oid = oid + self._value = value + + oid = utils.read_only_property("_oid") + value = utils.read_only_property("_value") + + def __repr__(self): + return ( + "".format( + self + ) + ) + + def __eq__(self, other): + if not isinstance(other, UnrecognizedExtension): + return NotImplemented + + return self.oid == other.oid and self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.oid, self.value)) diff --git a/server/www/packages/packages-common/cryptography/x509/general_name.py b/server/www/packages/packages-common/cryptography/x509/general_name.py new file mode 100644 index 0000000..26f389a --- /dev/null +++ b/server/www/packages/packages-common/cryptography/x509/general_name.py @@ -0,0 +1,345 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import abc +import ipaddress +import warnings +from email.utils import parseaddr + +import idna + +import six +from six.moves import urllib_parse + +from cryptography import utils +from cryptography.x509.name import Name +from cryptography.x509.oid import ObjectIdentifier + + +_GENERAL_NAMES = { + 0: "otherName", + 1: "rfc822Name", + 2: "dNSName", + 3: "x400Address", + 4: "directoryName", + 5: "ediPartyName", + 6: "uniformResourceIdentifier", + 7: "iPAddress", + 8: "registeredID", +} + + +class UnsupportedGeneralNameType(Exception): + def __init__(self, msg, type): + super(UnsupportedGeneralNameType, self).__init__(msg) + self.type = type + + +@six.add_metaclass(abc.ABCMeta) +class GeneralName(object): + @abc.abstractproperty + def value(self): + """ + Return the value of the object + """ + + +@utils.register_interface(GeneralName) +class RFC822Name(object): + def __init__(self, value): + if isinstance(value, six.text_type): + try: + value.encode("ascii") + except UnicodeEncodeError: + value = self._idna_encode(value) + warnings.warn( + "RFC822Name values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "idna. Support for passing unicode strings (aka U-label) " + "will be removed in a future version.", + utils.DeprecatedIn21, + stacklevel=2, + ) + else: + raise TypeError("value must be string") + + name, address = parseaddr(value) + if name or not address: + # parseaddr has found a name (e.g. Name ) or the entire + # value is an empty string. + raise ValueError("Invalid rfc822name value") + + self._value = value + + value = utils.read_only_property("_value") + + @classmethod + def _init_without_validation(cls, value): + instance = cls.__new__(cls) + instance._value = value + return instance + + def _idna_encode(self, value): + _, address = parseaddr(value) + parts = address.split(u"@") + return parts[0] + "@" + idna.encode(parts[1]).decode("ascii") + + def __repr__(self): + return "".format(self.value) + + def __eq__(self, other): + if not isinstance(other, RFC822Name): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.value) + + +def _idna_encode(value): + # Retain prefixes '*.' for common/alt names and '.' for name constraints + for prefix in ['*.', '.']: + if value.startswith(prefix): + value = value[len(prefix):] + return prefix + idna.encode(value).decode("ascii") + return idna.encode(value).decode("ascii") + + +@utils.register_interface(GeneralName) +class DNSName(object): + def __init__(self, value): + if isinstance(value, six.text_type): + try: + value.encode("ascii") + except UnicodeEncodeError: + value = _idna_encode(value) + warnings.warn( + "DNSName values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "idna. Support for passing unicode strings (aka U-label) " + "will be removed in a future version.", + utils.DeprecatedIn21, + stacklevel=2, + ) + else: + raise TypeError("value must be string") + + self._value = value + + value = utils.read_only_property("_value") + + @classmethod + def _init_without_validation(cls, value): + instance = cls.__new__(cls) + instance._value = value + return instance + + def __repr__(self): + return "".format(self.value) + + def __eq__(self, other): + if not isinstance(other, DNSName): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.value) + + +@utils.register_interface(GeneralName) +class UniformResourceIdentifier(object): + def __init__(self, value): + if isinstance(value, six.text_type): + try: + value.encode("ascii") + except UnicodeEncodeError: + value = self._idna_encode(value) + warnings.warn( + "URI values should be passed as an A-label string. " + "This means unicode characters should be encoded via " + "idna. Support for passing unicode strings (aka U-label) " + " will be removed in a future version.", + utils.DeprecatedIn21, + stacklevel=2, + ) + else: + raise TypeError("value must be string") + + self._value = value + + value = utils.read_only_property("_value") + + @classmethod + def _init_without_validation(cls, value): + instance = cls.__new__(cls) + instance._value = value + return instance + + def _idna_encode(self, value): + parsed = urllib_parse.urlparse(value) + if parsed.port: + netloc = ( + idna.encode(parsed.hostname) + + ":{0}".format(parsed.port).encode("ascii") + ).decode("ascii") + else: + netloc = idna.encode(parsed.hostname).decode("ascii") + + # Note that building a URL in this fashion means it should be + # semantically indistinguishable from the original but is not + # guaranteed to be exactly the same. + return urllib_parse.urlunparse(( + parsed.scheme, + netloc, + parsed.path, + parsed.params, + parsed.query, + parsed.fragment + )) + + def __repr__(self): + return "".format(self.value) + + def __eq__(self, other): + if not isinstance(other, UniformResourceIdentifier): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.value) + + +@utils.register_interface(GeneralName) +class DirectoryName(object): + def __init__(self, value): + if not isinstance(value, Name): + raise TypeError("value must be a Name") + + self._value = value + + value = utils.read_only_property("_value") + + def __repr__(self): + return "".format(self.value) + + def __eq__(self, other): + if not isinstance(other, DirectoryName): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.value) + + +@utils.register_interface(GeneralName) +class RegisteredID(object): + def __init__(self, value): + if not isinstance(value, ObjectIdentifier): + raise TypeError("value must be an ObjectIdentifier") + + self._value = value + + value = utils.read_only_property("_value") + + def __repr__(self): + return "".format(self.value) + + def __eq__(self, other): + if not isinstance(other, RegisteredID): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.value) + + +@utils.register_interface(GeneralName) +class IPAddress(object): + def __init__(self, value): + if not isinstance( + value, + ( + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network + ) + ): + raise TypeError( + "value must be an instance of ipaddress.IPv4Address, " + "ipaddress.IPv6Address, ipaddress.IPv4Network, or " + "ipaddress.IPv6Network" + ) + + self._value = value + + value = utils.read_only_property("_value") + + def __repr__(self): + return "".format(self.value) + + def __eq__(self, other): + if not isinstance(other, IPAddress): + return NotImplemented + + return self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.value) + + +@utils.register_interface(GeneralName) +class OtherName(object): + def __init__(self, type_id, value): + if not isinstance(type_id, ObjectIdentifier): + raise TypeError("type_id must be an ObjectIdentifier") + if not isinstance(value, bytes): + raise TypeError("value must be a binary string") + + self._type_id = type_id + self._value = value + + type_id = utils.read_only_property("_type_id") + value = utils.read_only_property("_value") + + def __repr__(self): + return "".format( + self.type_id, self.value) + + def __eq__(self, other): + if not isinstance(other, OtherName): + return NotImplemented + + return self.type_id == other.type_id and self.value == other.value + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.type_id, self.value)) diff --git a/server/www/packages/packages-common/cryptography/x509/name.py b/server/www/packages/packages-common/cryptography/x509/name.py new file mode 100644 index 0000000..5548eda --- /dev/null +++ b/server/www/packages/packages-common/cryptography/x509/name.py @@ -0,0 +1,190 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from enum import Enum + +import six + +from cryptography import utils +from cryptography.x509.oid import NameOID, ObjectIdentifier + + +class _ASN1Type(Enum): + UTF8String = 12 + NumericString = 18 + PrintableString = 19 + T61String = 20 + IA5String = 22 + UTCTime = 23 + GeneralizedTime = 24 + VisibleString = 26 + UniversalString = 28 + BMPString = 30 + + +_ASN1_TYPE_TO_ENUM = dict((i.value, i) for i in _ASN1Type) +_SENTINEL = object() +_NAMEOID_DEFAULT_TYPE = { + NameOID.COUNTRY_NAME: _ASN1Type.PrintableString, + NameOID.JURISDICTION_COUNTRY_NAME: _ASN1Type.PrintableString, + NameOID.SERIAL_NUMBER: _ASN1Type.PrintableString, + NameOID.DN_QUALIFIER: _ASN1Type.PrintableString, + NameOID.EMAIL_ADDRESS: _ASN1Type.IA5String, + NameOID.DOMAIN_COMPONENT: _ASN1Type.IA5String, +} + + +class NameAttribute(object): + def __init__(self, oid, value, _type=_SENTINEL): + if not isinstance(oid, ObjectIdentifier): + raise TypeError( + "oid argument must be an ObjectIdentifier instance." + ) + + if not isinstance(value, six.text_type): + raise TypeError( + "value argument must be a text type." + ) + + if ( + oid == NameOID.COUNTRY_NAME or + oid == NameOID.JURISDICTION_COUNTRY_NAME + ): + if len(value.encode("utf8")) != 2: + raise ValueError( + "Country name must be a 2 character country code" + ) + + if len(value) == 0: + raise ValueError("Value cannot be an empty string") + + # The appropriate ASN1 string type varies by OID and is defined across + # multiple RFCs including 2459, 3280, and 5280. In general UTF8String + # is preferred (2459), but 3280 and 5280 specify several OIDs with + # alternate types. This means when we see the sentinel value we need + # to look up whether the OID has a non-UTF8 type. If it does, set it + # to that. Otherwise, UTF8! + if _type == _SENTINEL: + _type = _NAMEOID_DEFAULT_TYPE.get(oid, _ASN1Type.UTF8String) + + if not isinstance(_type, _ASN1Type): + raise TypeError("_type must be from the _ASN1Type enum") + + self._oid = oid + self._value = value + self._type = _type + + oid = utils.read_only_property("_oid") + value = utils.read_only_property("_value") + + def __eq__(self, other): + if not isinstance(other, NameAttribute): + return NotImplemented + + return ( + self.oid == other.oid and + self.value == other.value + ) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.oid, self.value)) + + def __repr__(self): + return "".format(self) + + +class RelativeDistinguishedName(object): + def __init__(self, attributes): + attributes = list(attributes) + if not attributes: + raise ValueError("a relative distinguished name cannot be empty") + if not all(isinstance(x, NameAttribute) for x in attributes): + raise TypeError("attributes must be an iterable of NameAttribute") + + # Keep list and frozenset to preserve attribute order where it matters + self._attributes = attributes + self._attribute_set = frozenset(attributes) + + if len(self._attribute_set) != len(attributes): + raise ValueError("duplicate attributes are not allowed") + + def get_attributes_for_oid(self, oid): + return [i for i in self if i.oid == oid] + + def __eq__(self, other): + if not isinstance(other, RelativeDistinguishedName): + return NotImplemented + + return self._attribute_set == other._attribute_set + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self._attribute_set) + + def __iter__(self): + return iter(self._attributes) + + def __len__(self): + return len(self._attributes) + + def __repr__(self): + return "".format(list(self)) + + +class Name(object): + def __init__(self, attributes): + attributes = list(attributes) + if all(isinstance(x, NameAttribute) for x in attributes): + self._attributes = [ + RelativeDistinguishedName([x]) for x in attributes + ] + elif all(isinstance(x, RelativeDistinguishedName) for x in attributes): + self._attributes = attributes + else: + raise TypeError( + "attributes must be a list of NameAttribute" + " or a list RelativeDistinguishedName" + ) + + def get_attributes_for_oid(self, oid): + return [i for i in self if i.oid == oid] + + @property + def rdns(self): + return self._attributes + + def public_bytes(self, backend): + return backend.x509_name_bytes(self) + + def __eq__(self, other): + if not isinstance(other, Name): + return NotImplemented + + return self._attributes == other._attributes + + def __ne__(self, other): + return not self == other + + def __hash__(self): + # TODO: this is relatively expensive, if this looks like a bottleneck + # for you, consider optimizing! + return hash(tuple(self._attributes)) + + def __iter__(self): + for rdn in self._attributes: + for ava in rdn: + yield ava + + def __len__(self): + return sum(len(rdn) for rdn in self._attributes) + + def __repr__(self): + return "".format(list(self)) diff --git a/server/www/packages/packages-common/cryptography/x509/oid.py b/server/www/packages/packages-common/cryptography/x509/oid.py new file mode 100644 index 0000000..90003d7 --- /dev/null +++ b/server/www/packages/packages-common/cryptography/x509/oid.py @@ -0,0 +1,271 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +from cryptography import utils +from cryptography.hazmat.primitives import hashes + + +class ObjectIdentifier(object): + def __init__(self, dotted_string): + self._dotted_string = dotted_string + + nodes = self._dotted_string.split(".") + intnodes = [] + + # There must be at least 2 nodes, the first node must be 0..2, and + # if less than 2, the second node cannot have a value outside the + # range 0..39. All nodes must be integers. + for node in nodes: + try: + intnodes.append(int(node, 0)) + except ValueError: + raise ValueError( + "Malformed OID: %s (non-integer nodes)" % ( + self._dotted_string)) + + if len(nodes) < 2: + raise ValueError( + "Malformed OID: %s (insufficient number of nodes)" % ( + self._dotted_string)) + + if intnodes[0] > 2: + raise ValueError( + "Malformed OID: %s (first node outside valid range)" % ( + self._dotted_string)) + + if intnodes[0] < 2 and intnodes[1] >= 40: + raise ValueError( + "Malformed OID: %s (second node outside valid range)" % ( + self._dotted_string)) + + def __eq__(self, other): + if not isinstance(other, ObjectIdentifier): + return NotImplemented + + return self.dotted_string == other.dotted_string + + def __ne__(self, other): + return not self == other + + def __repr__(self): + return "".format( + self.dotted_string, + self._name + ) + + def __hash__(self): + return hash(self.dotted_string) + + @property + def _name(self): + return _OID_NAMES.get(self, "Unknown OID") + + dotted_string = utils.read_only_property("_dotted_string") + + +class ExtensionOID(object): + SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9") + SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14") + KEY_USAGE = ObjectIdentifier("2.5.29.15") + SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17") + ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18") + BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") + NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30") + CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31") + CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32") + POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33") + AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35") + POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36") + EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37") + FRESHEST_CRL = ObjectIdentifier("2.5.29.46") + INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54") + AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1") + SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11") + OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5") + TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24") + CRL_NUMBER = ObjectIdentifier("2.5.29.20") + DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27") + PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ( + ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2") + ) + + +class CRLEntryExtensionOID(object): + CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29") + CRL_REASON = ObjectIdentifier("2.5.29.21") + INVALIDITY_DATE = ObjectIdentifier("2.5.29.24") + + +class NameOID(object): + COMMON_NAME = ObjectIdentifier("2.5.4.3") + COUNTRY_NAME = ObjectIdentifier("2.5.4.6") + LOCALITY_NAME = ObjectIdentifier("2.5.4.7") + STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8") + STREET_ADDRESS = ObjectIdentifier("2.5.4.9") + ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10") + ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11") + SERIAL_NUMBER = ObjectIdentifier("2.5.4.5") + SURNAME = ObjectIdentifier("2.5.4.4") + GIVEN_NAME = ObjectIdentifier("2.5.4.42") + TITLE = ObjectIdentifier("2.5.4.12") + GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44") + X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45") + DN_QUALIFIER = ObjectIdentifier("2.5.4.46") + PSEUDONYM = ObjectIdentifier("2.5.4.65") + USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1") + DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") + EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") + JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") + JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") + JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( + "1.3.6.1.4.1.311.60.2.1.2" + ) + BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") + POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16") + POSTAL_CODE = ObjectIdentifier("2.5.4.17") + + +class SignatureAlgorithmOID(object): + RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") + RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") + # This is an alternate OID for RSA with SHA1 that is occasionally seen + _RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29") + RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") + RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") + RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") + RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") + RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") + ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1") + ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") + ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") + ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") + ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") + DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") + DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") + DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") + + +_SIG_OIDS_TO_HASH = { + SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), + SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), + SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), + SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), + SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), + SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256() +} + + +class ExtendedKeyUsageOID(object): + SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1") + CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2") + CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3") + EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") + TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") + OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") + ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") + + +class AuthorityInformationAccessOID(object): + CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2") + OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1") + + +class CertificatePoliciesOID(object): + CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1") + CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2") + ANY_POLICY = ObjectIdentifier("2.5.29.32.0") + + +_OID_NAMES = { + NameOID.COMMON_NAME: "commonName", + NameOID.COUNTRY_NAME: "countryName", + NameOID.LOCALITY_NAME: "localityName", + NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName", + NameOID.STREET_ADDRESS: "streetAddress", + NameOID.ORGANIZATION_NAME: "organizationName", + NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName", + NameOID.SERIAL_NUMBER: "serialNumber", + NameOID.SURNAME: "surname", + NameOID.GIVEN_NAME: "givenName", + NameOID.TITLE: "title", + NameOID.GENERATION_QUALIFIER: "generationQualifier", + NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier", + NameOID.DN_QUALIFIER: "dnQualifier", + NameOID.PSEUDONYM: "pseudonym", + NameOID.USER_ID: "userID", + NameOID.DOMAIN_COMPONENT: "domainComponent", + NameOID.EMAIL_ADDRESS: "emailAddress", + NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", + NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", + NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( + "jurisdictionStateOrProvinceName" + ), + NameOID.BUSINESS_CATEGORY: "businessCategory", + NameOID.POSTAL_ADDRESS: "postalAddress", + NameOID.POSTAL_CODE: "postalCode", + + SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption", + SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption", + SignatureAlgorithmOID.RSASSA_PSS: "RSASSA-PSS", + SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1", + SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224", + SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256", + SignatureAlgorithmOID.ECDSA_WITH_SHA384: "ecdsa-with-SHA384", + SignatureAlgorithmOID.ECDSA_WITH_SHA512: "ecdsa-with-SHA512", + SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1", + SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224", + SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256", + ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", + ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", + ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", + ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", + ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", + ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", + ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", + ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", + ExtensionOID.KEY_USAGE: "keyUsage", + ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName", + ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName", + ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints", + ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( + "signedCertificateTimestampList" + ), + CRLEntryExtensionOID.CRL_REASON: "cRLReason", + CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate", + CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer", + ExtensionOID.NAME_CONSTRAINTS: "nameConstraints", + ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints", + ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies", + ExtensionOID.POLICY_MAPPINGS: "policyMappings", + ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authorityKeyIdentifier", + ExtensionOID.POLICY_CONSTRAINTS: "policyConstraints", + ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage", + ExtensionOID.FRESHEST_CRL: "freshestCRL", + ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy", + ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess", + ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess", + ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck", + ExtensionOID.CRL_NUMBER: "cRLNumber", + ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator", + ExtensionOID.TLS_FEATURE: "TLSFeature", + AuthorityInformationAccessOID.OCSP: "OCSP", + AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers", + CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps", + CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice", +} diff --git a/server/www/packages/packages-common/mako/__init__.py b/server/www/packages/packages-common/mako/__init__.py index eaa24dc..01c1739 100644 --- a/server/www/packages/packages-common/mako/__init__.py +++ b/server/www/packages/packages-common/mako/__init__.py @@ -5,4 +5,4 @@ # the MIT License: http://www.opensource.org/licenses/mit-license.php -__version__ = '1.0.6' +__version__ = '1.0.7' diff --git a/server/www/packages/packages-common/mako/_ast_util.py b/server/www/packages/packages-common/mako/_ast_util.py index 8d19b0d..c410287 100644 --- a/server/www/packages/packages-common/mako/_ast_util.py +++ b/server/www/packages/packages-common/mako/_ast_util.py @@ -187,7 +187,7 @@ def iter_fields(node): def get_fields(node): - """Like `iter_fiels` but returns a dict.""" + """Like `iter_fields` but returns a dict.""" return dict(iter_fields(node)) diff --git a/server/www/packages/packages-common/mako/cache.py b/server/www/packages/packages-common/mako/cache.py index 94f3870..1af17dd 100644 --- a/server/www/packages/packages-common/mako/cache.py +++ b/server/www/packages/packages-common/mako/cache.py @@ -95,7 +95,7 @@ class Cache(object): **self._get_cache_kw(kw, context)) def set(self, key, value, **kw): - """Place a value in the cache. + r"""Place a value in the cache. :param key: the value's key. :param value: the value. @@ -113,7 +113,7 @@ class Cache(object): """ def get(self, key, **kw): - """Retrieve a value from the cache. + r"""Retrieve a value from the cache. :param key: the value's key. :param \**kw: cache configuration arguments. The @@ -125,7 +125,7 @@ class Cache(object): return self.impl.get(key, **self._get_cache_kw(kw, None)) def invalidate(self, key, **kw): - """Invalidate a value in the cache. + r"""Invalidate a value in the cache. :param key: the value's key. :param \**kw: cache configuration arguments. The @@ -194,7 +194,7 @@ class CacheImpl(object): """ def get_or_create(self, key, creation_function, **kw): - """Retrieve a value from the cache, using the given creation function + r"""Retrieve a value from the cache, using the given creation function to generate a new value. This function *must* return a value, either from @@ -212,7 +212,7 @@ class CacheImpl(object): raise NotImplementedError() def set(self, key, value, **kw): - """Place a value in the cache. + r"""Place a value in the cache. :param key: the value's key. :param value: the value. @@ -222,7 +222,7 @@ class CacheImpl(object): raise NotImplementedError() def get(self, key, **kw): - """Retrieve a value from the cache. + r"""Retrieve a value from the cache. :param key: the value's key. :param \**kw: cache configuration arguments. @@ -231,7 +231,7 @@ class CacheImpl(object): raise NotImplementedError() def invalidate(self, key, **kw): - """Invalidate a value in the cache. + r"""Invalidate a value in the cache. :param key: the value's key. :param \**kw: cache configuration arguments. diff --git a/server/www/packages/packages-common/mako/cmd.py b/server/www/packages/packages-common/mako/cmd.py index dd1f833..8db1346 100644 --- a/server/www/packages/packages-common/mako/cmd.py +++ b/server/www/packages/packages-common/mako/cmd.py @@ -58,7 +58,7 @@ def cmdline(argv=None): kw = dict([varsplit(var) for var in options.var]) try: - print(template.render(**kw)) + sys.stdout.write(template.render(**kw)) except: _exit() diff --git a/server/www/packages/packages-common/mako/ext/extract.py b/server/www/packages/packages-common/mako/ext/extract.py index 8dd2e96..d777ea8 100644 --- a/server/www/packages/packages-common/mako/ext/extract.py +++ b/server/www/packages/packages-common/mako/ext/extract.py @@ -68,7 +68,7 @@ class MessageExtractor(object): else: continue - # Comments don't apply unless they immediately preceed the message + # Comments don't apply unless they immediately precede the message if translator_comments and \ translator_comments[-1][0] < node.lineno - 1: translator_comments = [] diff --git a/server/www/packages/packages-common/mako/parsetree.py b/server/www/packages/packages-common/mako/parsetree.py index 879882e..e129916 100644 --- a/server/www/packages/packages-common/mako/parsetree.py +++ b/server/www/packages/packages-common/mako/parsetree.py @@ -258,7 +258,7 @@ class Tag(compat.with_metaclass(_TagMeta, Node)): def __init__(self, keyword, attributes, expressions, nonexpressions, required, **kwargs): - """construct a new Tag instance. + r"""construct a new Tag instance. this constructor not called directly, and is only called by subclasses. diff --git a/server/www/packages/packages-common/mako/template.py b/server/www/packages/packages-common/mako/template.py index c3e0c25..329632c 100644 --- a/server/www/packages/packages-common/mako/template.py +++ b/server/www/packages/packages-common/mako/template.py @@ -21,7 +21,7 @@ import weakref class Template(object): - """Represents a compiled template. + r"""Represents a compiled template. :class:`.Template` includes a reference to the original template source (via the :attr:`.source` attribute) diff --git a/server/www/packages/packages-common/pymysql/__init__.py b/server/www/packages/packages-common/pymysql/__init__.py index 43fb9a0..b79b4b8 100644 --- a/server/www/packages/packages-common/pymysql/__init__.py +++ b/server/www/packages/packages-common/pymysql/__init__.py @@ -35,7 +35,11 @@ from .times import ( DateFromTicks, TimeFromTicks, TimestampFromTicks) -VERSION = (0, 7, 11, None) +VERSION = (0, 9, 2, None) +if VERSION[3] is not None: + VERSION_STRING = "%d.%d.%d_%s" % VERSION +else: + VERSION_STRING = "%d.%d.%d" % VERSION[:3] threadsafety = 1 apilevel = "2.0" paramstyle = "pyformat" @@ -96,12 +100,15 @@ del _orig_conn def get_client_info(): # for MySQLdb compatibility - return '.'.join(map(str, VERSION)) + version = VERSION + if VERSION[3] is None: + version = VERSION[:3] + return '.'.join(map(str, version)) connect = Connection = Connect # we include a doctored version_info here for MySQLdb compatibility -version_info = (1,2,6,"final",0) +version_info = (1, 3, 12, "final", 0) NULL = "NULL" @@ -113,7 +120,7 @@ def thread_safe(): def install_as_MySQLdb(): """ After this function is called, any application that imports MySQLdb or - _mysql will unwittingly actually use + _mysql will unwittingly actually use pymysql. """ sys.modules["MySQLdb"] = sys.modules["_mysql"] = sys.modules["pymysql"] diff --git a/server/www/packages/packages-common/pymysql/connections.py b/server/www/packages/packages-common/pymysql/connections.py index 31dd85a..1e580d2 100644 --- a/server/www/packages/packages-common/pymysql/connections.py +++ b/server/www/packages/packages-common/pymysql/connections.py @@ -6,8 +6,6 @@ from __future__ import print_function from ._compat import PY2, range_type, text_type, str_type, JYTHON, IRONPYTHON import errno -from functools import partial -import hashlib import io import os import socket @@ -16,13 +14,19 @@ import sys import traceback import warnings -from .charset import MBLENGTH, charset_by_name, charset_by_id +from . import _auth + +from .charset import charset_by_name, charset_by_id from .constants import CLIENT, COMMAND, CR, FIELD_TYPE, SERVER_STATUS -from .converters import escape_item, escape_string, through, conversions as _conv +from . import converters from .cursors import Cursor from .optionfile import Parser +from .protocol import ( + dump_packet, MysqlPacket, FieldDescriptorPacket, OKPacketWrapper, + EOFPacketWrapper, LoadLocalPacketWrapper +) from .util import byte2int, int2byte -from . import err +from . import err, VERSION_STRING try: import ssl @@ -39,51 +43,39 @@ except (ImportError, KeyError): # KeyError occurs when there's no entry in OS database for a current user. DEFAULT_USER = None - DEBUG = False _py_version = sys.version_info[:2] +if PY2: + pass +elif _py_version < (3, 6): + # See http://bugs.python.org/issue24870 + _surrogateescape_table = [chr(i) if i < 0x80 else chr(i + 0xdc00) for i in range(256)] + + def _fast_surrogateescape(s): + return s.decode('latin1').translate(_surrogateescape_table) +else: + def _fast_surrogateescape(s): + return s.decode('ascii', 'surrogateescape') # socket.makefile() in Python 2 is not usable because very inefficient and # bad behavior about timeout. # XXX: ._socketio doesn't work under IronPython. -if _py_version == (2, 7) and not IRONPYTHON: +if PY2 and not IRONPYTHON: # read method of file-like returned by sock.makefile() is very slow. # So we copy io-based one from Python 3. from ._socketio import SocketIO def _makefile(sock, mode): return io.BufferedReader(SocketIO(sock, mode)) -elif _py_version == (2, 6): - # Python 2.6 doesn't have fast io module. - # So we make original one. - class SockFile(object): - def __init__(self, sock): - self._sock = sock - - def read(self, n): - read = self._sock.recv(n) - if len(read) == n: - return read - while True: - data = self._sock.recv(n-len(read)) - if not data: - return read - read += data - if len(read) == n: - return read - - def _makefile(sock, mode): - assert mode == 'rb' - return SockFile(sock) else: # socket.makefile in Python 3 is nice. def _makefile(sock, mode): return sock.makefile(mode) -TEXT_TYPES = set([ +TEXT_TYPES = { FIELD_TYPE.BIT, FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, @@ -92,122 +84,19 @@ TEXT_TYPES = set([ FIELD_TYPE.TINY_BLOB, FIELD_TYPE.VAR_STRING, FIELD_TYPE.VARCHAR, - FIELD_TYPE.GEOMETRY]) + FIELD_TYPE.GEOMETRY, +} -sha_new = partial(hashlib.new, 'sha1') -NULL_COLUMN = 251 -UNSIGNED_CHAR_COLUMN = 251 -UNSIGNED_SHORT_COLUMN = 252 -UNSIGNED_INT24_COLUMN = 253 -UNSIGNED_INT64_COLUMN = 254 - -DEFAULT_CHARSET = 'latin1' +DEFAULT_CHARSET = 'utf8mb4' # TODO: change to utf8mb4 MAX_PACKET_LEN = 2**24-1 -def dump_packet(data): # pragma: no cover - def is_ascii(data): - if 65 <= byte2int(data) <= 122: - if isinstance(data, int): - return chr(data) - return data - return '.' - - try: - print("packet length:", len(data)) - for i in range(1, 6): - f = sys._getframe(i) - print("call[%d]: %s (line %d)" % (i, f.f_code.co_name, f.f_lineno)) - print("-" * 66) - except ValueError: - pass - dump_data = [data[i:i+16] for i in range_type(0, min(len(data), 256), 16)] - for d in dump_data: - print(' '.join(map(lambda x: "{:02X}".format(byte2int(x)), d)) + - ' ' * (16 - len(d)) + ' ' * 2 + - ''.join(map(lambda x: "{}".format(is_ascii(x)), d))) - print("-" * 66) - print() - - -def _scramble(password, message): - if not password: - return b'' - if DEBUG: print('password=' + str(password)) - stage1 = sha_new(password).digest() - stage2 = sha_new(stage1).digest() - s = sha_new() - s.update(message) - s.update(stage2) - result = s.digest() - return _my_crypt(result, stage1) - - -def _my_crypt(message1, message2): - length = len(message1) - result = b'' - for i in range_type(length): - x = (struct.unpack('B', message1[i:i+1])[0] ^ - struct.unpack('B', message2[i:i+1])[0]) - result += struct.pack('B', x) - return result - -# old_passwords support ported from libmysql/password.c -SCRAMBLE_LENGTH_323 = 8 - - -class RandStruct_323(object): - def __init__(self, seed1, seed2): - self.max_value = 0x3FFFFFFF - self.seed1 = seed1 % self.max_value - self.seed2 = seed2 % self.max_value - - def my_rnd(self): - self.seed1 = (self.seed1 * 3 + self.seed2) % self.max_value - self.seed2 = (self.seed1 + self.seed2 + 33) % self.max_value - return float(self.seed1) / float(self.max_value) - - -def _scramble_323(password, message): - hash_pass = _hash_password_323(password) - hash_message = _hash_password_323(message[:SCRAMBLE_LENGTH_323]) - hash_pass_n = struct.unpack(">LL", hash_pass) - hash_message_n = struct.unpack(">LL", hash_message) - - rand_st = RandStruct_323(hash_pass_n[0] ^ hash_message_n[0], - hash_pass_n[1] ^ hash_message_n[1]) - outbuf = io.BytesIO() - for _ in range_type(min(SCRAMBLE_LENGTH_323, len(message))): - outbuf.write(int2byte(int(rand_st.my_rnd() * 31) + 64)) - extra = int2byte(int(rand_st.my_rnd() * 31)) - out = outbuf.getvalue() - outbuf = io.BytesIO() - for c in out: - outbuf.write(int2byte(byte2int(c) ^ byte2int(extra))) - return outbuf.getvalue() - - -def _hash_password_323(password): - nr = 1345345333 - add = 7 - nr2 = 0x12345671 - - # x in py3 is numbers, p27 is chars - for c in [byte2int(x) for x in password if x not in (' ', '\t', 32, 9)]: - nr ^= (((nr & 63) + add) * c) + (nr << 8) & 0xFFFFFFFF - nr2 = (nr2 + ((nr2 << 8) ^ nr)) & 0xFFFFFFFF - add = (add + c) & 0xFFFFFFFF - - r1 = nr & ((1 << 31) - 1) # kill sign bits - r2 = nr2 & ((1 << 31) - 1) - return struct.pack(">LL", r1, r2) - - def pack_int24(n): return struct.pack(' len(self._data): - raise Exception('Invalid advance amount (%s) for cursor. ' - 'Position=%s' % (length, new_position)) - self._position = new_position - - def rewind(self, position=0): - """Set the position of the data buffer cursor to 'position'.""" - if position < 0 or position > len(self._data): - raise Exception("Invalid position to rewind cursor to: %s." % position) - self._position = position - - def get_bytes(self, position, length=1): - """Get 'length' bytes starting at 'position'. - - Position is start of payload (first four packet header bytes are not - included) starting at index '0'. - - No error checking is done. If requesting outside end of buffer - an empty string (or string shorter than 'length') may be returned! - """ - return self._data[position:(position+length)] - - if PY2: - def read_uint8(self): - result = ord(self._data[self._position]) - self._position += 1 - return result - else: - def read_uint8(self): - result = self._data[self._position] - self._position += 1 - return result - - def read_uint16(self): - result = struct.unpack_from('= 7 - - def is_eof_packet(self): - # http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-EOF_Packet - # Caution: \xFE may be LengthEncodedInteger. - # If \xFE is LengthEncodedInteger header, 8bytes followed. - return self._data[0:1] == b'\xfe' and len(self._data) < 9 - - def is_auth_switch_request(self): - # http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest - return self._data[0:1] == b'\xfe' - - def is_resultset_packet(self): - field_count = ord(self._data[0:1]) - return 1 <= field_count <= 250 - - def is_load_local_packet(self): - return self._data[0:1] == b'\xfb' - - def is_error_packet(self): - return self._data[0:1] == b'\xff' - - def check_error(self): - if self.is_error_packet(): - self.rewind() - self.advance(1) # field_count == error (we already know that) - errno = self.read_uint16() - if DEBUG: print("errno =", errno) - err.raise_mysql_exception(self._data) - - def dump(self): - dump_packet(self._data) - - -class FieldDescriptorPacket(MysqlPacket): - """A MysqlPacket that represents a specific column's metadata in the result. - - Parsing is automatically done and the results are exported via public - attributes on the class such as: db, table_name, name, length, type_code. - """ - - def __init__(self, data, encoding): - MysqlPacket.__init__(self, data, encoding) - self._parse_field_descriptor(encoding) - - def _parse_field_descriptor(self, encoding): - """Parse the 'Field Descriptor' (Metadata) packet. - - This is compatible with MySQL 4.1+ (not compatible with MySQL 4.0). - """ - self.catalog = self.read_length_coded_string() - self.db = self.read_length_coded_string() - self.table_name = self.read_length_coded_string().decode(encoding) - self.org_table = self.read_length_coded_string().decode(encoding) - self.name = self.read_length_coded_string().decode(encoding) - self.org_name = self.read_length_coded_string().decode(encoding) - self.charsetnr, self.length, self.type_code, self.flags, self.scale = ( - self.read_struct('`_ in the + specification. """ _sock = None _auth_plugin_name = '' _closed = False + _secure = False def __init__(self, host=None, user=None, password="", database=None, port=0, unix_socket=None, @@ -532,63 +187,12 @@ class Connection(object): read_default_file=None, conv=None, use_unicode=None, client_flag=0, cursorclass=Cursor, init_command=None, connect_timeout=10, ssl=None, read_default_group=None, - compress=None, named_pipe=None, no_delay=None, + compress=None, named_pipe=None, autocommit=False, db=None, passwd=None, local_infile=False, max_allowed_packet=16*1024*1024, defer_connect=False, - auth_plugin_map={}, read_timeout=None, write_timeout=None, - bind_address=None): - """ - Establish a connection to the MySQL database. Accepts several - arguments: - - host: Host where the database server is located - user: Username to log in as - password: Password to use. - database: Database to use, None to not use a particular one. - port: MySQL port to use, default is usually OK. (default: 3306) - bind_address: When the client has multiple network interfaces, specify - the interface from which to connect to the host. Argument can be - a hostname or an IP address. - unix_socket: Optionally, you can use a unix socket rather than TCP/IP. - charset: Charset you want to use. - sql_mode: Default SQL_MODE to use. - read_default_file: - Specifies my.cnf file to read these parameters from under the [client] section. - conv: - Conversion dictionary to use instead of the default one. - This is used to provide custom marshalling and unmarshaling of types. - See converters. - use_unicode: - Whether or not to default to unicode strings. - This option defaults to true for Py3k. - client_flag: Custom flags to send to MySQL. Find potential values in constants.CLIENT. - cursorclass: Custom cursor class to use. - init_command: Initial SQL statement to run when connection is established. - connect_timeout: Timeout before throwing an exception when connecting. - (default: 10, min: 1, max: 31536000) - ssl: - A dict of arguments similar to mysql_ssl_set()'s parameters. - For now the capath and cipher arguments are not supported. - read_default_group: Group to read from in the configuration file. - compress; Not supported - named_pipe: Not supported - autocommit: Autocommit mode. None means use server default. (default: False) - local_infile: Boolean to enable the use of LOAD DATA LOCAL command. (default: False) - max_allowed_packet: Max size of packet sent to server in bytes. (default: 16MB) - Only used to limit size of "LOAD LOCAL INFILE" data packet smaller than default (16KB). - defer_connect: Don't explicitly connect on contruction - wait for connect call. - (default: False) - auth_plugin_map: A dict of plugin names to a class that processes that plugin. - The class will take the Connection object as the argument to the constructor. - The class needs an authenticate method taking an authentication packet as - an argument. For the dialog plugin, a prompt(echo, prompt) method can be used - (if no authenticate method) for returning a string from the user. (experimental) - db: Alias for database. (for compatibility to MySQLdb) - passwd: Alias for password. (for compatibility to MySQLdb) - """ - if no_delay is not None: - warnings.warn("no_delay option is deprecated", DeprecationWarning) - + auth_plugin_map=None, read_timeout=None, write_timeout=None, + bind_address=None, binary_prefix=False, program_name=None, + server_public_key=None): if use_unicode is None and sys.version_info[0] > 2: use_unicode = True @@ -652,7 +256,9 @@ class Connection(object): self.host = host or "localhost" self.port = port or 3306 self.user = user or DEFAULT_USER - self.password = password or "" + self.password = password or b"" + if isinstance(self.password, text_type): + self.password = self.password.encode('latin1') self.db = database self.unix_socket = unix_socket self.bind_address = bind_address @@ -680,6 +286,7 @@ class Connection(object): client_flag |= CLIENT.CAPABILITIES if self.db: client_flag |= CLIENT.CONNECT_WITH_DB + self.client_flag = client_flag self.cursorclass = cursorclass @@ -692,14 +299,28 @@ class Connection(object): self.autocommit_mode = autocommit if conv is None: - conv = _conv + conv = converters.conversions + # Need for MySQLdb compatibility. self.encoders = dict([(k, v) for (k, v) in conv.items() if type(k) is not int]) self.decoders = dict([(k, v) for (k, v) in conv.items() if type(k) is int]) self.sql_mode = sql_mode self.init_command = init_command self.max_allowed_packet = max_allowed_packet - self._auth_plugin_map = auth_plugin_map + self._auth_plugin_map = auth_plugin_map or {} + self._binary_prefix = binary_prefix + self.server_public_key = server_public_key + + self._connect_attrs = { + '_client_name': 'pymysql', + '_pid': str(os.getpid()), + '_client_version': VERSION_STRING, + } + if program_name: + self._connect_attrs["program_name"] = program_name + elif sys.argv: + self._connect_attrs["program_name"] = sys.argv[0] + if defer_connect: self._sock = None else: @@ -723,7 +344,14 @@ class Connection(object): return ctx def close(self): - """Send the quit message and close the socket""" + """ + Send the quit message and close the socket. + + See `Connection.close() `_ + in the specification. + + :raise Error: If the connection is already closed. + """ if self._closed: raise err.Error("Already closed") self._closed = True @@ -739,6 +367,7 @@ class Connection(object): @property def open(self): + """Return True if the connection is open""" return self._sock is not None def _force_close(self): @@ -746,7 +375,7 @@ class Connection(object): if self._sock: try: self._sock.close() - except: + except: # noqa pass self._sock = None self._rfile = None @@ -783,39 +412,58 @@ class Connection(object): self._read_ok_packet() def commit(self): - """Commit changes to stable storage""" + """ + Commit changes to stable storage. + + See `Connection.commit() `_ + in the specification. + """ self._execute_command(COMMAND.COM_QUERY, "COMMIT") self._read_ok_packet() def rollback(self): - """Roll back the current transaction""" + """ + Roll back the current transaction. + + See `Connection.rollback() `_ + in the specification. + """ self._execute_command(COMMAND.COM_QUERY, "ROLLBACK") self._read_ok_packet() def show_warnings(self): - """SHOW WARNINGS""" + """Send the "SHOW WARNINGS" SQL command.""" self._execute_command(COMMAND.COM_QUERY, "SHOW WARNINGS") result = MySQLResult(self) result.read() return result.rows def select_db(self, db): - """Set current db""" + """ + Set current db. + + :param db: The name of the db. + """ self._execute_command(COMMAND.COM_INIT_DB, db) self._read_ok_packet() def escape(self, obj, mapping=None): """Escape whatever value you pass to it. - + Non-standard, for internal use; do not use this in your applications. """ if isinstance(obj, str_type): return "'" + self.escape_string(obj) + "'" - return escape_item(obj, self.charset, mapping=mapping) + if isinstance(obj, (bytes, bytearray)): + ret = self._quote_bytes(obj) + if self._binary_prefix: + ret = "_binary" + ret + return ret + return converters.escape_item(obj, self.charset, mapping=mapping) def literal(self, obj): """Alias for escape() - + Non-standard, for internal use; do not use this in your applications. """ return self.escape(obj, self.encoders) @@ -824,10 +472,22 @@ class Connection(object): if (self.server_status & SERVER_STATUS.SERVER_STATUS_NO_BACKSLASH_ESCAPES): return s.replace("'", "''") - return escape_string(s) + return converters.escape_string(s) + + def _quote_bytes(self, s): + if (self.server_status & + SERVER_STATUS.SERVER_STATUS_NO_BACKSLASH_ESCAPES): + return "'%s'" % (_fast_surrogateescape(s.replace(b"'", b"''")),) + return converters.escape_bytes(s) def cursor(self, cursor=None): - """Create a new cursor to execute queries with""" + """ + Create a new cursor to execute queries with. + + :param cursor: The type of cursor to create; one of :py:class:`Cursor`, + :py:class:`SSCursor`, :py:class:`DictCursor`, or :py:class:`SSDictCursor`. + None means use Cursor. + """ if cursor: return cursor(self) return self.cursorclass(self) @@ -869,7 +529,12 @@ class Connection(object): return self._read_ok_packet() def ping(self, reconnect=True): - """Check if the server is alive""" + """ + Check if the server is alive. + + :param reconnect: If the connection is closed, reconnect. + :raise Error: If the connection is closed and reconnect=False. + """ if self._sock is None: if reconnect: self.connect() @@ -878,11 +543,11 @@ class Connection(object): raise err.Error("Already closed") try: self._execute_command(COMMAND.COM_PING, "") - return self._read_ok_packet() + self._read_ok_packet() except Exception: if reconnect: self.connect() - return self.ping(False) + self.ping(False) else: raise @@ -899,11 +564,12 @@ class Connection(object): self._closed = False try: if sock is None: - if self.unix_socket and self.host in ('localhost', '127.0.0.1'): + if self.unix_socket: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(self.connect_timeout) sock.connect(self.unix_socket) self.host_info = "Localhost via UNIX socket" + self._secure = True if DEBUG: print('connected using unix_socket') else: kwargs = {} @@ -948,7 +614,7 @@ class Connection(object): if sock is not None: try: sock.close() - except: + except: # noqa pass if isinstance(e, (OSError, IOError, socket.error)): @@ -981,11 +647,14 @@ class Connection(object): def _read_packet(self, packet_type=MysqlPacket): """Read an entire "mysql packet" in its entirety from the network and return a MysqlPacket type that represents the results. + + :raise OperationalError: If the connection to the MySQL server is lost. + :raise InternalError: If the packet sequence number is wrong. """ buff = b'' while True: packet_header = self._read_bytes(4) - if DEBUG: dump_packet(packet_header) + #if DEBUG: dump_packet(packet_header) btrl, btrh, packet_number = struct.unpack('= i + 6: lang, stat, cap_h, salt_len = struct.unpack('`_ in + the specification. """ #: Max statement size which :meth:`executemany` generates. @@ -32,10 +38,6 @@ class Cursor(object): _defer_warnings = False def __init__(self, connection): - """ - Do not create an instance of a Cursor yourself. Call - connections.Connection.cursor(). - """ self.connection = connection self.description = None self.rownumber = 0 @@ -95,6 +97,8 @@ class Cursor(object): return None if not current_result.has_next: return None + self._result = None + self._clear_result() conn.next_result(unbuffered=unbuffered) self._do_get_result() return True @@ -260,9 +264,10 @@ class Cursor(object): disconnected. """ conn = self._get_db() - for index, arg in enumerate(args): - q = "SET @_%s_%d=%s" % (procname, index, conn.escape(arg)) - self._query(q) + if args: + fmt = '@_{0}_%d=%s'.format(procname) + self._query('SET %s' % ','.join(fmt % (index, conn.escape(arg)) + for index, arg in enumerate(args))) self.nextset() q = "CALL %s(%s)" % (procname, @@ -319,14 +324,23 @@ class Cursor(object): def _query(self, q): conn = self._get_db() self._last_executed = q + self._clear_result() conn.query(q) self._do_get_result() return self.rowcount + def _clear_result(self): + self.rownumber = 0 + self._result = None + + self.rowcount = 0 + self.description = None + self.lastrowid = None + self._rows = None + def _do_get_result(self): conn = self._get_db() - self.rownumber = 0 self._result = result = conn._result self.rowcount = result.affected_rows @@ -432,9 +446,12 @@ class SSCursor(Cursor): finally: self.connection = None + __del__ = close + def _query(self, q): conn = self._get_db() self._last_executed = q + self._clear_result() conn.query(q, unbuffered=True) self._do_get_result() return self.rowcount diff --git a/server/www/packages/packages-common/pymysql/err.py b/server/www/packages/packages-common/pymysql/err.py index 2486263..fbc6055 100644 --- a/server/www/packages/packages-common/pymysql/err.py +++ b/server/www/packages/packages-common/pymysql/err.py @@ -78,7 +78,9 @@ _map_error(ProgrammingError, ER.DB_CREATE_EXISTS, ER.SYNTAX_ERROR, ER.PARSE_ERROR, ER.NO_SUCH_TABLE, ER.WRONG_DB_NAME, ER.WRONG_TABLE_NAME, ER.FIELD_SPECIFIED_TWICE, ER.INVALID_GROUP_FUNC_USE, ER.UNSUPPORTED_EXTENSION, - ER.TABLE_MUST_HAVE_COLUMNS, ER.CANT_DO_THIS_DURING_AN_TRANSACTION) + ER.TABLE_MUST_HAVE_COLUMNS, ER.CANT_DO_THIS_DURING_AN_TRANSACTION, + ER.WRONG_DB_NAME, ER.WRONG_COLUMN_NAME, + ) _map_error(DataError, ER.WARN_DATA_TRUNCATED, ER.WARN_NULL_TO_NOTNULL, ER.WARN_DATA_OUT_OF_RANGE, ER.NO_DEFAULT, ER.PRIMARY_CANT_HAVE_NULL, ER.DATA_TOO_LONG, ER.DATETIME_FUNCTION_OVERFLOW) @@ -89,7 +91,7 @@ _map_error(NotSupportedError, ER.WARNING_NOT_COMPLETE_ROLLBACK, ER.NOT_SUPPORTED_YET, ER.FEATURE_DISABLED, ER.UNKNOWN_STORAGE_ENGINE) _map_error(OperationalError, ER.DBACCESS_DENIED_ERROR, ER.ACCESS_DENIED_ERROR, ER.CON_COUNT_ERROR, ER.TABLEACCESS_DENIED_ERROR, - ER.COLUMNACCESS_DENIED_ERROR) + ER.COLUMNACCESS_DENIED_ERROR, ER.CONSTRAINT_FAILED, ER.LOCK_DEADLOCK) del _map_error, ER diff --git a/server/www/packages/packages-common/pymysql/optionfile.py b/server/www/packages/packages-common/pymysql/optionfile.py index 23cce8a..91e2dfe 100644 --- a/server/www/packages/packages-common/pymysql/optionfile.py +++ b/server/www/packages/packages-common/pymysql/optionfile.py @@ -7,6 +7,9 @@ else: class Parser(configparser.RawConfigParser): + def __init__(self, **kwargs): + kwargs['allow_no_value'] = True + configparser.RawConfigParser.__init__(self, **kwargs) def __remove_quotes(self, value): quotes = ["'", "\""] diff --git a/server/www/packages/packages-common/pymysql/protocol.py b/server/www/packages/packages-common/pymysql/protocol.py new file mode 100644 index 0000000..8ccf7c4 --- /dev/null +++ b/server/www/packages/packages-common/pymysql/protocol.py @@ -0,0 +1,341 @@ +# Python implementation of low level MySQL client-server protocol +# http://dev.mysql.com/doc/internals/en/client-server-protocol.html + +from __future__ import print_function +from .charset import MBLENGTH +from ._compat import PY2, range_type +from .constants import FIELD_TYPE, SERVER_STATUS +from . import err +from .util import byte2int + +import struct +import sys + + +DEBUG = False + +NULL_COLUMN = 251 +UNSIGNED_CHAR_COLUMN = 251 +UNSIGNED_SHORT_COLUMN = 252 +UNSIGNED_INT24_COLUMN = 253 +UNSIGNED_INT64_COLUMN = 254 + + +def dump_packet(data): # pragma: no cover + def printable(data): + if 32 <= byte2int(data) < 127: + if isinstance(data, int): + return chr(data) + return data + return '.' + + try: + print("packet length:", len(data)) + for i in range(1, 7): + f = sys._getframe(i) + print("call[%d]: %s (line %d)" % (i, f.f_code.co_name, f.f_lineno)) + print("-" * 66) + except ValueError: + pass + dump_data = [data[i:i+16] for i in range_type(0, min(len(data), 256), 16)] + for d in dump_data: + print(' '.join("{:02X}".format(byte2int(x)) for x in d) + + ' ' * (16 - len(d)) + ' ' * 2 + + ''.join(printable(x) for x in d)) + print("-" * 66) + print() + + +class MysqlPacket(object): + """Representation of a MySQL response packet. + + Provides an interface for reading/parsing the packet results. + """ + __slots__ = ('_position', '_data') + + def __init__(self, data, encoding): + self._position = 0 + self._data = data + + def get_all_data(self): + return self._data + + def read(self, size): + """Read the first 'size' bytes in packet and advance cursor past them.""" + result = self._data[self._position:(self._position+size)] + if len(result) != size: + error = ('Result length not requested length:\n' + 'Expected=%s. Actual=%s. Position: %s. Data Length: %s' + % (size, len(result), self._position, len(self._data))) + if DEBUG: + print(error) + self.dump() + raise AssertionError(error) + self._position += size + return result + + def read_all(self): + """Read all remaining data in the packet. + + (Subsequent read() will return errors.) + """ + result = self._data[self._position:] + self._position = None # ensure no subsequent read() + return result + + def advance(self, length): + """Advance the cursor in data buffer 'length' bytes.""" + new_position = self._position + length + if new_position < 0 or new_position > len(self._data): + raise Exception('Invalid advance amount (%s) for cursor. ' + 'Position=%s' % (length, new_position)) + self._position = new_position + + def rewind(self, position=0): + """Set the position of the data buffer cursor to 'position'.""" + if position < 0 or position > len(self._data): + raise Exception("Invalid position to rewind cursor to: %s." % position) + self._position = position + + def get_bytes(self, position, length=1): + """Get 'length' bytes starting at 'position'. + + Position is start of payload (first four packet header bytes are not + included) starting at index '0'. + + No error checking is done. If requesting outside end of buffer + an empty string (or string shorter than 'length') may be returned! + """ + return self._data[position:(position+length)] + + if PY2: + def read_uint8(self): + result = ord(self._data[self._position]) + self._position += 1 + return result + else: + def read_uint8(self): + result = self._data[self._position] + self._position += 1 + return result + + def read_uint16(self): + result = struct.unpack_from('= 7 + + def is_eof_packet(self): + # http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-EOF_Packet + # Caution: \xFE may be LengthEncodedInteger. + # If \xFE is LengthEncodedInteger header, 8bytes followed. + return self._data[0:1] == b'\xfe' and len(self._data) < 9 + + def is_auth_switch_request(self): + # http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest + return self._data[0:1] == b'\xfe' + + def is_extra_auth_data(self): + # https://dev.mysql.com/doc/internals/en/successful-authentication.html + return self._data[0:1] == b'\x01' + + def is_resultset_packet(self): + field_count = ord(self._data[0:1]) + return 1 <= field_count <= 250 + + def is_load_local_packet(self): + return self._data[0:1] == b'\xfb' + + def is_error_packet(self): + return self._data[0:1] == b'\xff' + + def check_error(self): + if self.is_error_packet(): + self.rewind() + self.advance(1) # field_count == error (we already know that) + errno = self.read_uint16() + if DEBUG: print("errno =", errno) + err.raise_mysql_exception(self._data) + + def dump(self): + dump_packet(self._data) + + +class FieldDescriptorPacket(MysqlPacket): + """A MysqlPacket that represents a specific column's metadata in the result. + + Parsing is automatically done and the results are exported via public + attributes on the class such as: db, table_name, name, length, type_code. + """ + + def __init__(self, data, encoding): + MysqlPacket.__init__(self, data, encoding) + self._parse_field_descriptor(encoding) + + def _parse_field_descriptor(self, encoding): + """Parse the 'Field Descriptor' (Metadata) packet. + + This is compatible with MySQL 4.1+ (not compatible with MySQL 4.0). + """ + self.catalog = self.read_length_coded_string() + self.db = self.read_length_coded_string() + self.table_name = self.read_length_coded_string().decode(encoding) + self.org_table = self.read_length_coded_string().decode(encoding) + self.name = self.read_length_coded_string().decode(encoding) + self.org_name = self.read_length_coded_string().decode(encoding) + self.charsetnr, self.length, self.type_code, self.flags, self.scale = ( + self.read_struct(' 7: + raise ValueError( + "Mask pattern should be in range(8) (got %s)" % mask_pattern) + class QRCode: def __init__(self, version=None, error_correction=constants.ERROR_CORRECT_M, box_size=10, border=4, - image_factory=None): + image_factory=None, + mask_pattern=None): _check_box_size(box_size) self.version = version and int(version) self.error_correction = int(error_correction) @@ -36,6 +47,8 @@ class QRCode: # Spec says border should be at least four boxes wide, but allow for # any (e.g. for producing printable QR codes). self.border = int(border) + _check_mask_pattern(mask_pattern) + self.mask_pattern = mask_pattern self.image_factory = image_factory if image_factory is not None: assert issubclass(image_factory, BaseImage) @@ -62,7 +75,8 @@ class QRCode: self.data_list.append(data) else: if optimize: - self.data_list.extend(util.optimal_data_chunks(data)) + self.data_list.extend( + util.optimal_data_chunks(data, minimum=optimize)) else: self.data_list.append(util.QRData(data)) self.data_cache = None @@ -76,7 +90,10 @@ class QRCode: """ if fit or (self.version is None): self.best_fit(start=self.version) - self.makeImpl(False, self.best_mask_pattern()) + if self.mask_pattern is None: + self.makeImpl(False, self.best_mask_pattern()) + else: + self.makeImpl(False, self.mask_pattern) def makeImpl(self, test, mask_pattern): _check_version(self.version) diff --git a/server/www/packages/packages-common/qrcode/mecard.py b/server/www/packages/packages-common/qrcode/mecard.py deleted file mode 100644 index ce05582..0000000 --- a/server/www/packages/packages-common/qrcode/mecard.py +++ /dev/null @@ -1,33 +0,0 @@ -import six - -# {'code': 'N', 'label': 'Name', 'required': True, 'multipart': [ -# 'Last Name', 'First Name']}, -PROPERTIES = { - 'NICKNAME': {'label': 'Nickname'}, - 'BDAY': {'label': 'Birthday', 'date': True}, - 'TEL': {'label': 'Phone'}, - 'EMAIL': {'label': 'E-mail'}, - 'ADR': {'label': 'Address', 'multipart': [ - 'PO Box', 'Room Number', 'House Number', 'City', 'Prefecture', - 'Zip Code', 'Country']}, - 'URL': {'label': 'URL'}, - 'MEMO': {'label': 'Note'}, -} - - -def build_code(data): - notation = [] - - name = data['N'] - if not isinstance(name, six.text_type): - name = ','.join(name) - notation.append('N', name) - - for prop in PROPERTIES: - value = data.get(prop['code']) - if not value: - continue - if prop['date']: - value = value.strftime('%Y%m%d') - elif prop['multipart']: - value = ','.join(value) diff --git a/server/www/packages/packages-common/qrcode/release.py b/server/www/packages/packages-common/qrcode/release.py new file mode 100644 index 0000000..abbabb4 --- /dev/null +++ b/server/www/packages/packages-common/qrcode/release.py @@ -0,0 +1,42 @@ +""" +This file provides zest.releaser entrypoints using when releasing new +qrcode versions. +""" +import os +import re +import datetime + + +def update_manpage(data): + """ + Update the version in the manpage document. + """ + if data['name'] != 'qrcode': + print('no qrcode') + return + + base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + filename = os.path.join(base_dir, 'doc', 'qr.1') + with open(filename, 'r') as f: + lines = f.readlines() + + changed = False + for i, line in enumerate(lines): + if not line.startswith('.TH '): + continue + parts = re.split(r'"([^"]*)"', line) + if len(parts) < 5: + continue + changed = parts[3] != data['new_version'] + if changed: + # Update version + parts[3] = data['new_version'] + # Update date + parts[1] = datetime.datetime.now().strftime('%-d %b %Y') + lines[i] = '"'.join(parts) + break + + if changed: + with open(filename, 'w') as f: + for line in lines: + f.write(line) diff --git a/server/www/packages/packages-common/qrcode/speedy.py b/server/www/packages/packages-common/qrcode/speedy.py deleted file mode 100644 index 11ec3aa..0000000 --- a/server/www/packages/packages-common/qrcode/speedy.py +++ /dev/null @@ -1,8 +0,0 @@ -import string -import qrcode - -qr = qrcode.QRCode() - -qr.add_data(string.letters*13) -qr.make() -print(qr.version) diff --git a/server/www/packages/packages-common/qrcode/util.py b/server/www/packages/packages-common/qrcode/util.py index 89dcf09..a9652f7 100644 --- a/server/www/packages/packages-common/qrcode/util.py +++ b/server/www/packages/packages-common/qrcode/util.py @@ -4,7 +4,7 @@ import math import six from six.moves import xrange -from qrcode import base, exceptions +from qrcode import base, exceptions, LUT # QR encoding modes. MODE_NUMBER = 1 << 0 @@ -189,51 +189,39 @@ def _lost_point_level1(modules, modules_count): lost_point = 0 modules_range = xrange(modules_count) - row_range_first = (0, 1) - row_range_last = (-1, 0) - row_range_standard = (-1, 0, 1) - - col_range_first = ((0, 1), (1,)) - col_range_last = ((-1, 0), (-1,)) - col_range_standard = ((-1, 0, 1), (-1, 1)) + container = [0] * (modules_count + 1) for row in modules_range: - - if row == 0: - row_range = row_range_first - elif row == modules_count-1: - row_range = row_range_last - else: - row_range = row_range_standard - + this_row = modules[row] + previous_color = this_row[0] + length = 0 for col in modules_range: - - sameCount = 0 - dark = modules[row][col] - - if col == 0: - col_range = col_range_first - elif col == modules_count-1: - col_range = col_range_last + if this_row[col] == previous_color: + length += 1 else: - col_range = col_range_standard + if length >= 5: + container[length] += 1 + length = 1 + previous_color = this_row[col] + if length >= 5: + container[length] += 1 - for r in row_range: + for col in modules_range: + previous_color = modules[0][col] + length = 0 + for row in modules_range: + if modules[row][col] == previous_color: + length += 1 + else: + if length >= 5: + container[length] += 1 + length = 1 + previous_color = modules[row][col] + if length >= 5: + container[length] += 1 - row_offset = row + r - - if r != 0: - col_idx = 0 - else: - col_idx = 1 - - for c in col_range[col_idx]: - - if dark == modules[row_offset][col + c]: - sameCount += 1 - - if sameCount > 5: - lost_point += (3 + sameCount - 5) + lost_point += sum(container[each_length] * (each_length - 2) + for each_length in xrange(5, modules_count + 1)) return lost_point @@ -242,68 +230,111 @@ def _lost_point_level2(modules, modules_count): lost_point = 0 modules_range = xrange(modules_count - 1) - for row in modules_range: this_row = modules[row] - next_row = modules[row+1] - for col in modules_range: - count = 0 - if this_row[col]: - count += 1 - if next_row[col]: - count += 1 - if this_row[col + 1]: - count += 1 - if next_row[col + 1]: - count += 1 - if count == 0 or count == 4: + next_row = modules[row + 1] + # use iter() and next() to skip next four-block. e.g. + # d a f if top-right a != b botton-right, + # c b e then both abcd and abef won't lost any point. + modules_range_iter = iter(modules_range) + for col in modules_range_iter: + top_right = this_row[col + 1] + if top_right != next_row[col + 1]: + # reduce 33.3% of runtime via next(). + # None: raise nothing if there is no next item. + next(modules_range_iter, None) + elif top_right != this_row[col]: + continue + elif top_right != next_row[col]: + continue + else: lost_point += 3 return lost_point def _lost_point_level3(modules, modules_count): - modules_range_short = xrange(modules_count-6) - + # 1 : 1 : 3 : 1 : 1 ratio (dark:light:dark:light:dark) pattern in + # row/column, preceded or followed by light area 4 modules wide. From ISOIEC. + # pattern1: 10111010000 + # pattern2: 00001011101 + modules_range = xrange(modules_count) + modules_range_short = xrange(modules_count-10) lost_point = 0 - for row in xrange(modules_count): + + for row in modules_range: this_row = modules[row] - for col in modules_range_short: - if (this_row[col] - and not this_row[col + 1] - and this_row[col + 2] - and this_row[col + 3] + modules_range_short_iter = iter(modules_range_short) + col = 0 + for col in modules_range_short_iter: + if ( + not this_row[col + 1] and this_row[col + 4] and not this_row[col + 5] - and this_row[col + 6]): + and this_row[col + 6] + and not this_row[col + 9] + and ( + this_row[col + 0] + and this_row[col + 2] + and this_row[col + 3] + and not this_row[col + 7] + and not this_row[col + 8] + and not this_row[col + 10] + or + not this_row[col + 0] + and not this_row[col + 2] + and not this_row[col + 3] + and this_row[col + 7] + and this_row[col + 8] + and this_row[col + 10] + ) + ): lost_point += 40 +# horspool algorithm. +# if this_row[col + 10] == True, pattern1 shift 4, pattern2 shift 2. So min=2. +# if this_row[col + 10] == False, pattern1 shift 1, pattern2 shift 1. So min=1. + if this_row[col + 10]: + next(modules_range_short_iter, None) - for col in xrange(modules_count): - for row in modules_range_short: - if (modules[row][col] - and not modules[row + 1][col] - and modules[row + 2][col] - and modules[row + 3][col] + for col in modules_range: + modules_range_short_iter = iter(modules_range_short) + row = 0 + for row in modules_range_short_iter: + if ( + not modules[row + 1][col] and modules[row + 4][col] and not modules[row + 5][col] - and modules[row + 6][col]): + and modules[row + 6][col] + and not modules[row + 9][col] + and ( + modules[row + 0][col] + and modules[row + 2][col] + and modules[row + 3][col] + and not modules[row + 7][col] + and not modules[row + 8][col] + and not modules[row + 10][col] + or + not modules[row + 0][col] + and not modules[row + 2][col] + and not modules[row + 3][col] + and modules[row + 7][col] + and modules[row + 8][col] + and modules[row + 10][col] + ) + ): lost_point += 40 + if modules[row + 10][col]: + next(modules_range_short_iter, None) return lost_point def _lost_point_level4(modules, modules_count): - modules_range = xrange(modules_count) - dark_count = 0 - - for row in modules_range: - this_row = modules[row] - for col in modules_range: - if this_row[col]: - dark_count += 1 - - ratio = abs(100 * dark_count / modules_count / modules_count - 50) / 5 - return ratio * 10 + dark_count = sum(map(sum, modules)) + percent = float(dark_count) / (modules_count**2) + # Every 5% departure from 50%, rating++ + rating = int(abs(percent * 100 - 50) / 5) + return rating * 10 def optimal_data_chunks(data, minimum=4): @@ -479,9 +510,12 @@ def create_bytes(buffer, rs_blocks): offset += dcCount # Get error correction polynomial. - rsPoly = base.Polynomial([1], 0) - for i in range(ecCount): - rsPoly = rsPoly * base.Polynomial([1, base.gexp(i)], 0) + if ecCount in LUT.rsPoly_LUT: + rsPoly = base.Polynomial(LUT.rsPoly_LUT[ecCount], 0) + else: + rsPoly = base.Polynomial([1], 0) + for i in range(ecCount): + rsPoly = rsPoly * base.Polynomial([1, base.gexp(i)], 0) rawPoly = base.Polynomial(dcdata[r], len(rsPoly) - 1) diff --git a/server/www/packages/packages-common/six.py b/server/www/packages/packages-common/six.py index 190c023..6bf4fd3 100644 --- a/server/www/packages/packages-common/six.py +++ b/server/www/packages/packages-common/six.py @@ -1,6 +1,4 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2015 Benjamin Peterson +# Copyright (c) 2010-2017 Benjamin Peterson # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -20,6 +18,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +"""Utilities for writing code that runs on Python 2 and 3""" + from __future__ import absolute_import import functools @@ -29,7 +29,7 @@ import sys import types __author__ = "Benjamin Peterson " -__version__ = "1.10.0" +__version__ = "1.11.0" # Useful for very coarse version differentiation. @@ -241,6 +241,7 @@ _moved_attributes = [ MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), @@ -262,10 +263,11 @@ _moved_attributes = [ MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), @@ -337,10 +339,12 @@ _urllib_parse_moved_attributes = [ MovedAttribute("quote_plus", "urllib", "urllib.parse"), MovedAttribute("unquote", "urllib", "urllib.parse"), MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), MovedAttribute("urlencode", "urllib", "urllib.parse"), MovedAttribute("splitquery", "urllib", "urllib.parse"), MovedAttribute("splittag", "urllib", "urllib.parse"), MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), MovedAttribute("uses_params", "urlparse", "urllib.parse"), @@ -416,6 +420,8 @@ _urllib_request_moved_attributes = [ MovedAttribute("URLopener", "urllib", "urllib.request"), MovedAttribute("FancyURLopener", "urllib", "urllib.request"), MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), ] for attr in _urllib_request_moved_attributes: setattr(Module_six_moves_urllib_request, attr.name, attr) @@ -679,11 +685,15 @@ if PY3: exec_ = getattr(moves.builtins, "exec") def reraise(tp, value, tb=None): - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None else: def exec_(_code_, _globs_=None, _locs_=None): @@ -699,19 +709,28 @@ else: exec("""exec _code_ in _globs_, _locs_""") exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb + try: + raise tp, value, tb + finally: + tb = None """) if sys.version_info[:2] == (3, 2): exec_("""def raise_from(value, from_value): - if from_value is None: - raise value - raise value from from_value + try: + if from_value is None: + raise value + raise value from from_value + finally: + value = None """) elif sys.version_info[:2] > (3, 2): exec_("""def raise_from(value, from_value): - raise value from from_value + try: + raise value from from_value + finally: + value = None """) else: def raise_from(value, from_value): @@ -802,10 +821,14 @@ def with_metaclass(meta, *bases): # This requires a bit of explanation: the basic idea is to make a dummy # metaclass for one level of class instantiation that replaces itself with # the actual metaclass. - class metaclass(meta): + class metaclass(type): def __new__(cls, name, this_bases, d): return meta(name, bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/server/www/packages/packages-common/tornado/__init__.py b/server/www/packages/packages-common/tornado/__init__.py index f054e40..6bb5ec2 100644 --- a/server/www/packages/packages-common/tornado/__init__.py +++ b/server/www/packages/packages-common/tornado/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -25,5 +24,5 @@ from __future__ import absolute_import, division, print_function # is zero for an official release, positive for a development branch, # or negative for a release candidate or beta (after the base version # number has been incremented) -version = "4.5.1" -version_info = (4, 5, 1, 0) +version = "5.1" +version_info = (5, 1, 0, 0) diff --git a/server/www/packages/packages-common/tornado/_locale_data.py b/server/www/packages/packages-common/tornado/_locale_data.py index 6fa2c29..a2c5039 100644 --- a/server/www/packages/packages-common/tornado/_locale_data.py +++ b/server/www/packages/packages-common/tornado/_locale_data.py @@ -1,5 +1,4 @@ -#!/usr/bin/env python -# coding: utf-8 +# -*- coding: utf-8 -*- # # Copyright 2012 Facebook # diff --git a/server/www/packages/packages-common/tornado/auth.py b/server/www/packages/packages-common/tornado/auth.py index f02d289..ab1a850 100644 --- a/server/www/packages/packages-common/tornado/auth.py +++ b/server/www/packages/packages-common/tornado/auth.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -38,15 +37,14 @@ Example usage for Google OAuth: class GoogleOAuth2LoginHandler(tornado.web.RequestHandler, tornado.auth.GoogleOAuth2Mixin): - @tornado.gen.coroutine - def get(self): + async def get(self): if self.get_argument('code', False): - user = yield self.get_authenticated_user( + user = await self.get_authenticated_user( redirect_uri='http://your.site.com/auth/google', code=self.get_argument('code')) # Save the user with e.g. set_secure_cookie else: - yield self.authorize_redirect( + await self.authorize_redirect( redirect_uri='http://your.site.com/auth/google', client_id=self.settings['google_oauth']['key'], scope=['profile', 'email'], @@ -74,8 +72,11 @@ import hashlib import hmac import time import uuid +import warnings -from tornado.concurrent import TracebackFuture, return_future, chain_future +from tornado.concurrent import (Future, _non_deprecated_return_future, + future_set_exc_info, chain_future, + future_set_result_unless_cancelled) from tornado import gen from tornado import httpclient from tornado import escape @@ -112,14 +113,19 @@ def _auth_return_future(f): Note that when using this decorator the ``callback`` parameter inside the function will actually be a future. + + .. deprecated:: 5.1 + Will be removed in 6.0. """ replacer = ArgReplacer(f, 'callback') @functools.wraps(f) def wrapper(*args, **kwargs): - future = TracebackFuture() + future = Future() callback, args, kwargs = replacer.replace(future, args, kwargs) if callback is not None: + warnings.warn("callback arguments are deprecated, use the returned Future instead", + DeprecationWarning) future.add_done_callback( functools.partial(_auth_future_to_callback, callback)) @@ -127,9 +133,9 @@ def _auth_return_future(f): if future.done(): return False else: - future.set_exc_info((typ, value, tb)) + future_set_exc_info(future, (typ, value, tb)) return True - with ExceptionStackContext(handle_exception): + with ExceptionStackContext(handle_exception, delay_warning=True): f(*args, **kwargs) return future return wrapper @@ -142,7 +148,7 @@ class OpenIdMixin(object): * ``_OPENID_ENDPOINT``: the identity provider's URI. """ - @return_future + @_non_deprecated_return_future def authenticate_redirect(self, callback_uri=None, ax_attrs=["name", "email", "language", "username"], callback=None): @@ -161,6 +167,11 @@ class OpenIdMixin(object): not strictly necessary as this method is synchronous, but they are supplied for consistency with `OAuthMixin.authorize_redirect`. + + .. deprecated:: 5.1 + + The ``callback`` argument and returned awaitable will be removed + in Tornado 6.0; this will be an ordinary synchronous function. """ callback_uri = callback_uri or self.request.uri args = self._openid_args(callback_uri, ax_attrs=ax_attrs) @@ -178,6 +189,11 @@ class OpenIdMixin(object): is present and `authenticate_redirect` if it is not). The result of this method will generally be used to set a cookie. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ # Verify the OpenID response via direct request to the OP args = dict((k, v[-1]) for k, v in self.request.arguments.items()) @@ -185,9 +201,9 @@ class OpenIdMixin(object): url = self._OPENID_ENDPOINT if http_client is None: http_client = self.get_auth_http_client() - http_client.fetch(url, functools.partial( - self._on_authentication_verified, callback), - method="POST", body=urllib_parse.urlencode(args)) + fut = http_client.fetch(url, method="POST", body=urllib_parse.urlencode(args)) + fut.add_done_callback(functools.partial( + self._on_authentication_verified, callback)) def _openid_args(self, callback_uri, ax_attrs=[], oauth_scope=None): url = urlparse.urljoin(self.request.full_url(), callback_uri) @@ -237,11 +253,16 @@ class OpenIdMixin(object): }) return args - def _on_authentication_verified(self, future, response): - if response.error or b"is_valid:true" not in response.body: + def _on_authentication_verified(self, future, response_fut): + try: + response = response_fut.result() + except Exception as e: future.set_exception(AuthError( - "Invalid OpenID response: %s" % (response.error or - response.body))) + "Error response %s" % e)) + return + if b"is_valid:true" not in response.body: + future.set_exception(AuthError( + "Invalid OpenID response: %s" % response.body)) return # Make sure we got back at least an email from attribute exchange @@ -295,7 +316,7 @@ class OpenIdMixin(object): claimed_id = self.get_argument("openid.claimed_id", None) if claimed_id: user["claimed_id"] = claimed_id - future.set_result(user) + future_set_result_unless_cancelled(future, user) def get_auth_http_client(self): """Returns the `.AsyncHTTPClient` instance to be used for auth requests. @@ -322,48 +343,52 @@ class OAuthMixin(object): Subclasses must also override the `_oauth_get_user_future` and `_oauth_consumer_token` methods. """ - @return_future + @_non_deprecated_return_future def authorize_redirect(self, callback_uri=None, extra_params=None, http_client=None, callback=None): """Redirects the user to obtain OAuth authorization for this service. The ``callback_uri`` may be omitted if you have previously - registered a callback URI with the third-party service. For - some services (including Friendfeed), you must use a - previously-registered callback URI and cannot specify a - callback via this method. + registered a callback URI with the third-party service. For + some services, you must use a previously-registered callback + URI and cannot specify a callback via this method. This method sets a cookie called ``_oauth_request_token`` which is subsequently used (and cleared) in `get_authenticated_user` for security purposes. - Note that this method is asynchronous, although it calls - `.RequestHandler.finish` for you so it may not be necessary - to pass a callback or use the `.Future` it returns. However, - if this method is called from a function decorated with - `.gen.coroutine`, you must call it with ``yield`` to keep the - response from being closed prematurely. + This method is asynchronous and must be called with ``await`` + or ``yield`` (This is different from other ``auth*_redirect`` + methods defined in this module). It calls + `.RequestHandler.finish` for you so you should not write any + other response after it returns. .. versionchanged:: 3.1 Now returns a `.Future` and takes an optional callback, for compatibility with `.gen.coroutine`. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. + """ if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False): raise Exception("This service does not support oauth_callback") if http_client is None: http_client = self.get_auth_http_client() if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a": - http_client.fetch( + fut = http_client.fetch( self._oauth_request_token_url(callback_uri=callback_uri, - extra_params=extra_params), - functools.partial( - self._on_request_token, - self._OAUTH_AUTHORIZE_URL, - callback_uri, - callback)) + extra_params=extra_params)) + fut.add_done_callback(functools.partial( + self._on_request_token, + self._OAUTH_AUTHORIZE_URL, + callback_uri, + callback)) else: - http_client.fetch( - self._oauth_request_token_url(), + fut = http_client.fetch(self._oauth_request_token_url()) + fut.add_done_callback( functools.partial( self._on_request_token, self._OAUTH_AUTHORIZE_URL, callback_uri, @@ -380,6 +405,11 @@ class OAuthMixin(object): requests to this service on behalf of the user. The dictionary will also contain other fields such as ``name``, depending on the service used. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ future = callback request_key = escape.utf8(self.get_argument("oauth_token")) @@ -390,7 +420,8 @@ class OAuthMixin(object): "Missing OAuth request token cookie")) return self.clear_cookie("_oauth_request_token") - cookie_key, cookie_secret = [base64.b64decode(escape.utf8(i)) for i in request_cookie.split("|")] + cookie_key, cookie_secret = [ + base64.b64decode(escape.utf8(i)) for i in request_cookie.split("|")] if cookie_key != request_key: future.set_exception(AuthError( "Request token does not match cookie")) @@ -400,8 +431,8 @@ class OAuthMixin(object): token["verifier"] = oauth_verifier if http_client is None: http_client = self.get_auth_http_client() - http_client.fetch(self._oauth_access_token_url(token), - functools.partial(self._on_access_token, callback)) + fut = http_client.fetch(self._oauth_access_token_url(token)) + fut.add_done_callback(functools.partial(self._on_access_token, callback)) def _oauth_request_token_url(self, callback_uri=None, extra_params=None): consumer_token = self._oauth_consumer_token() @@ -429,9 +460,11 @@ class OAuthMixin(object): return url + "?" + urllib_parse.urlencode(args) def _on_request_token(self, authorize_url, callback_uri, callback, - response): - if response.error: - raise Exception("Could not get request token: %s" % response.error) + response_fut): + try: + response = response_fut.result() + except Exception as e: + raise Exception("Could not get request token: %s" % e) request_token = _oauth_parse_response(response.body) data = (base64.b64encode(escape.utf8(request_token["key"])) + b"|" + base64.b64encode(escape.utf8(request_token["secret"]))) @@ -471,13 +504,17 @@ class OAuthMixin(object): args["oauth_signature"] = signature return url + "?" + urllib_parse.urlencode(args) - def _on_access_token(self, future, response): - if response.error: + def _on_access_token(self, future, response_fut): + try: + response = response_fut.result() + except Exception: future.set_exception(AuthError("Could not fetch access token")) return access_token = _oauth_parse_response(response.body) - self._oauth_get_user_future(access_token).add_done_callback( + fut = self._oauth_get_user_future(access_token) + fut = gen.convert_yielded(fut) + fut.add_done_callback( functools.partial(self._on_oauth_get_user, access_token, future)) def _oauth_consumer_token(self): @@ -487,7 +524,7 @@ class OAuthMixin(object): """ raise NotImplementedError() - @return_future + @_non_deprecated_return_future def _oauth_get_user_future(self, access_token, callback): """Subclasses must override this to get basic information about the user. @@ -502,7 +539,18 @@ class OAuthMixin(object): For backwards compatibility, the callback-based ``_oauth_get_user`` method is also supported. + + .. versionchanged:: 5.1 + + Subclasses may also define this method with ``async def``. + + .. deprecated:: 5.1 + + The ``_oauth_get_user`` fallback is deprecated and support for it + will be removed in 6.0. """ + warnings.warn("_oauth_get_user is deprecated, override _oauth_get_user_future instead", + DeprecationWarning) # By default, call the old-style _oauth_get_user, but new code # should override this method instead. self._oauth_get_user(access_token, callback) @@ -519,7 +567,7 @@ class OAuthMixin(object): future.set_exception(AuthError("Error getting user")) return user["access_token"] = access_token - future.set_result(user) + future_set_result_unless_cancelled(future, user) def _oauth_request_parameters(self, url, access_token, parameters={}, method="GET"): @@ -569,7 +617,7 @@ class OAuth2Mixin(object): * ``_OAUTH_AUTHORIZE_URL``: The service's authorization url. * ``_OAUTH_ACCESS_TOKEN_URL``: The service's access token url. """ - @return_future + @_non_deprecated_return_future def authorize_redirect(self, redirect_uri=None, client_id=None, client_secret=None, extra_params=None, callback=None, scope=None, response_type="code"): @@ -586,6 +634,11 @@ class OAuth2Mixin(object): not strictly necessary as this method is synchronous, but they are supplied for consistency with `OAuthMixin.authorize_redirect`. + + .. deprecated:: 5.1 + + The ``callback`` argument and returned awaitable will be removed + in Tornado 6.0; this will be an ordinary synchronous function. """ args = { "redirect_uri": redirect_uri, @@ -629,16 +682,15 @@ class OAuth2Mixin(object): class MainHandler(tornado.web.RequestHandler, tornado.auth.FacebookGraphMixin): @tornado.web.authenticated - @tornado.gen.coroutine - def get(self): - new_entry = yield self.oauth2_request( + async def get(self): + new_entry = await self.oauth2_request( "https://graph.facebook.com/me/feed", post_args={"message": "I am posting from my Tornado application!"}, access_token=self.current_user["access_token"]) if not new_entry: # Call failed; perhaps missing permission? - yield self.authorize_redirect() + await self.authorize_redirect() return self.finish("Posted a message!") @@ -646,6 +698,11 @@ class OAuth2Mixin(object): :hide: .. versionadded:: 4.3 + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ all_args = {} if access_token: @@ -657,18 +714,19 @@ class OAuth2Mixin(object): callback = functools.partial(self._on_oauth2_request, callback) http = self.get_auth_http_client() if post_args is not None: - http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args), - callback=callback) + fut = http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args)) else: - http.fetch(url, callback=callback) + fut = http.fetch(url) + fut.add_done_callback(callback) - def _on_oauth2_request(self, future, response): - if response.error: - future.set_exception(AuthError("Error response %s fetching %s" % - (response.error, response.request.url))) + def _on_oauth2_request(self, future, response_fut): + try: + response = response_fut.result() + except Exception as e: + future.set_exception(AuthError("Error response %s" % e)) return - future.set_result(escape.json_decode(response.body)) + future_set_result_unless_cancelled(future, escape.json_decode(response.body)) def get_auth_http_client(self): """Returns the `.AsyncHTTPClient` instance to be used for auth requests. @@ -698,13 +756,12 @@ class TwitterMixin(OAuthMixin): class TwitterLoginHandler(tornado.web.RequestHandler, tornado.auth.TwitterMixin): - @tornado.gen.coroutine - def get(self): + async def get(self): if self.get_argument("oauth_token", None): - user = yield self.get_authenticated_user() + user = await self.get_authenticated_user() # Save the user using e.g. set_secure_cookie() else: - yield self.authorize_redirect() + await self.authorize_redirect() .. testoutput:: :hide: @@ -721,7 +778,7 @@ class TwitterMixin(OAuthMixin): _OAUTH_NO_CALLBACKS = False _TWITTER_BASE_URL = "https://api.twitter.com/1.1" - @return_future + @_non_deprecated_return_future def authenticate_redirect(self, callback_uri=None, callback=None): """Just like `~OAuthMixin.authorize_redirect`, but auto-redirects if authorized. @@ -732,6 +789,11 @@ class TwitterMixin(OAuthMixin): .. versionchanged:: 3.1 Now returns a `.Future` and takes an optional callback, for compatibility with `.gen.coroutine`. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ http = self.get_auth_http_client() http.fetch(self._oauth_request_token_url(callback_uri=callback_uri), @@ -764,9 +826,8 @@ class TwitterMixin(OAuthMixin): class MainHandler(tornado.web.RequestHandler, tornado.auth.TwitterMixin): @tornado.web.authenticated - @tornado.gen.coroutine - def get(self): - new_entry = yield self.twitter_request( + async def get(self): + new_entry = await self.twitter_request( "/statuses/update", post_args={"status": "Testing Tornado Web Server"}, access_token=self.current_user["access_token"]) @@ -779,6 +840,10 @@ class TwitterMixin(OAuthMixin): .. testoutput:: :hide: + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ if path.startswith('http:') or path.startswith('https:'): # Raw urls are useful for e.g. search which doesn't follow the @@ -798,20 +863,21 @@ class TwitterMixin(OAuthMixin): if args: url += "?" + urllib_parse.urlencode(args) http = self.get_auth_http_client() - http_callback = functools.partial(self._on_twitter_request, callback) + http_callback = functools.partial(self._on_twitter_request, callback, url) if post_args is not None: - http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args), - callback=http_callback) + fut = http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args)) else: - http.fetch(url, callback=http_callback) + fut = http.fetch(url) + fut.add_done_callback(http_callback) - def _on_twitter_request(self, future, response): - if response.error: + def _on_twitter_request(self, future, url, response_fut): + try: + response = response_fut.result() + except Exception as e: future.set_exception(AuthError( - "Error response %s fetching %s" % (response.error, - response.request.url))) + "Error response %s fetching %s" % (e, url))) return - future.set_result(escape.json_decode(response.body)) + future_set_result_unless_cancelled(future, escape.json_decode(response.body)) def _oauth_consumer_token(self): self.require_setting("twitter_consumer_key", "Twitter OAuth") @@ -848,8 +914,8 @@ class GoogleOAuth2Mixin(OAuth2Mixin): .. versionadded:: 3.2 """ - _OAUTH_AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/auth" - _OAUTH_ACCESS_TOKEN_URL = "https://accounts.google.com/o/oauth2/token" + _OAUTH_AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/v2/auth" + _OAUTH_ACCESS_TOKEN_URL = "https://www.googleapis.com/oauth2/v4/token" _OAUTH_USERINFO_URL = "https://www.googleapis.com/oauth2/v1/userinfo" _OAUTH_NO_CALLBACKS = False _OAUTH_SETTINGS_KEY = 'google_oauth' @@ -872,19 +938,18 @@ class GoogleOAuth2Mixin(OAuth2Mixin): class GoogleOAuth2LoginHandler(tornado.web.RequestHandler, tornado.auth.GoogleOAuth2Mixin): - @tornado.gen.coroutine - def get(self): + async def get(self): if self.get_argument('code', False): - access = yield self.get_authenticated_user( + access = await self.get_authenticated_user( redirect_uri='http://your.site.com/auth/google', code=self.get_argument('code')) - user = yield self.oauth2_request( + user = await self.oauth2_request( "https://www.googleapis.com/oauth2/v1/userinfo", access_token=access["access_token"]) # Save the user and access token with # e.g. set_secure_cookie. else: - yield self.authorize_redirect( + await self.authorize_redirect( redirect_uri='http://your.site.com/auth/google', client_id=self.settings['google_oauth']['key'], scope=['profile', 'email'], @@ -894,7 +959,11 @@ class GoogleOAuth2Mixin(OAuth2Mixin): .. testoutput:: :hide: - """ + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. + """ # noqa: E501 http = self.get_auth_http_client() body = urllib_parse.urlencode({ "redirect_uri": redirect_uri, @@ -904,18 +973,22 @@ class GoogleOAuth2Mixin(OAuth2Mixin): "grant_type": "authorization_code", }) - http.fetch(self._OAUTH_ACCESS_TOKEN_URL, - functools.partial(self._on_access_token, callback), - method="POST", headers={'Content-Type': 'application/x-www-form-urlencoded'}, body=body) + fut = http.fetch(self._OAUTH_ACCESS_TOKEN_URL, + method="POST", + headers={'Content-Type': 'application/x-www-form-urlencoded'}, + body=body) + fut.add_done_callback(functools.partial(self._on_access_token, callback)) - def _on_access_token(self, future, response): + def _on_access_token(self, future, response_fut): """Callback function for the exchange to the access token.""" - if response.error: - future.set_exception(AuthError('Google auth error: %s' % str(response))) + try: + response = response_fut.result() + except Exception as e: + future.set_exception(AuthError('Google auth error: %s' % str(e))) return args = escape.json_decode(response.body) - future.set_result(args) + future_set_result_unless_cancelled(future, args) class FacebookGraphMixin(OAuth2Mixin): @@ -936,17 +1009,16 @@ class FacebookGraphMixin(OAuth2Mixin): class FacebookGraphLoginHandler(tornado.web.RequestHandler, tornado.auth.FacebookGraphMixin): - @tornado.gen.coroutine - def get(self): + async def get(self): if self.get_argument("code", False): - user = yield self.get_authenticated_user( + user = await self.get_authenticated_user( redirect_uri='/auth/facebookgraph/', client_id=self.settings["facebook_api_key"], client_secret=self.settings["facebook_secret"], code=self.get_argument("code")) # Save the user with e.g. set_secure_cookie else: - yield self.authorize_redirect( + await self.authorize_redirect( redirect_uri='/auth/facebookgraph/', client_id=self.settings["facebook_api_key"], extra_params={"scope": "read_stream,offline_access"}) @@ -963,11 +1035,17 @@ class FacebookGraphMixin(OAuth2Mixin): Tornado it will change from a string to an integer. * ``id``, ``name``, ``first_name``, ``last_name``, ``locale``, ``picture``, ``link``, plus any fields named in the ``extra_fields`` argument. These - fields are copied from the Facebook graph API `user object `_ + fields are copied from the Facebook graph API + `user object `_ .. versionchanged:: 4.5 The ``session_expires`` field was updated to support changes made to the Facebook API in March 2017. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ http = self.get_auth_http_client() args = { @@ -982,14 +1060,17 @@ class FacebookGraphMixin(OAuth2Mixin): if extra_fields: fields.update(extra_fields) - http.fetch(self._oauth_request_token_url(**args), - functools.partial(self._on_access_token, redirect_uri, client_id, - client_secret, callback, fields)) + fut = http.fetch(self._oauth_request_token_url(**args)) + fut.add_done_callback(functools.partial(self._on_access_token, redirect_uri, client_id, + client_secret, callback, fields)) + @gen.coroutine def _on_access_token(self, redirect_uri, client_id, client_secret, - future, fields, response): - if response.error: - future.set_exception(AuthError('Facebook auth error: %s' % str(response))) + future, fields, response_fut): + try: + response = response_fut.result() + except Exception as e: + future.set_exception(AuthError('Facebook auth error: %s' % str(e))) return args = escape.json_decode(response.body) @@ -998,10 +1079,8 @@ class FacebookGraphMixin(OAuth2Mixin): "expires_in": args.get("expires_in") } - self.facebook_request( + user = yield self.facebook_request( path="/me", - callback=functools.partial( - self._on_get_user_info, future, session, fields), access_token=session["access_token"], appsecret_proof=hmac.new(key=client_secret.encode('utf8'), msg=session["access_token"].encode('utf8'), @@ -1009,9 +1088,8 @@ class FacebookGraphMixin(OAuth2Mixin): fields=",".join(fields) ) - def _on_get_user_info(self, future, session, fields, user): if user is None: - future.set_result(None) + future_set_result_unless_cancelled(future, None) return fieldmap = {} @@ -1024,7 +1102,7 @@ class FacebookGraphMixin(OAuth2Mixin): # This should change in Tornado 5.0. fieldmap.update({"access_token": session["access_token"], "session_expires": str(session.get("expires_in"))}) - future.set_result(fieldmap) + future_set_result_unless_cancelled(future, fieldmap) @_auth_return_future def facebook_request(self, path, callback, access_token=None, @@ -1045,14 +1123,13 @@ class FacebookGraphMixin(OAuth2Mixin): Example usage: - ..testcode:: + .. testcode:: class MainHandler(tornado.web.RequestHandler, tornado.auth.FacebookGraphMixin): @tornado.web.authenticated - @tornado.gen.coroutine - def get(self): - new_entry = yield self.facebook_request( + async def get(self): + new_entry = await self.facebook_request( "/me/feed", post_args={"message": "I am posting from my Tornado application!"}, access_token=self.current_user["access_token"]) @@ -1075,6 +1152,11 @@ class FacebookGraphMixin(OAuth2Mixin): .. versionchanged:: 3.1 Added the ability to override ``self._FACEBOOK_BASE_URL``. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ url = self._FACEBOOK_BASE_URL + path # Thanks to the _auth_return_future decorator, our "callback" diff --git a/server/www/packages/packages-common/tornado/autoreload.py b/server/www/packages/packages-common/tornado/autoreload.py index 60571ef..7d69474 100644 --- a/server/www/packages/packages-common/tornado/autoreload.py +++ b/server/www/packages/packages-common/tornado/autoreload.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -63,12 +62,11 @@ import sys # file.py gets added to the path, which can cause confusion as imports # may become relative in spite of the future import. # -# We address the former problem by setting the $PYTHONPATH environment -# variable before re-execution so the new process will see the correct -# path. We attempt to address the latter problem when tornado.autoreload -# is run as __main__, although we can't fix the general case because -# we cannot reliably reconstruct the original command line -# (http://bugs.python.org/issue14208). +# We address the former problem by reconstructing the original command +# line (Python >= 3.4) or by setting the $PYTHONPATH environment +# variable (Python < 3.4) before re-execution so the new process will +# see the correct path. We attempt to address the latter problem when +# tornado.autoreload is run as __main__. if __name__ == "__main__": # This sys.path manipulation must come before our imports (as much @@ -109,15 +107,18 @@ _watched_files = set() _reload_hooks = [] _reload_attempted = False _io_loops = weakref.WeakKeyDictionary() # type: ignore +_autoreload_is_main = False +_original_argv = None +_original_spec = None -def start(io_loop=None, check_time=500): +def start(check_time=500): """Begins watching source files for changes. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - io_loop = io_loop or ioloop.IOLoop.current() + io_loop = ioloop.IOLoop.current() if io_loop in _io_loops: return _io_loops[io_loop] = True @@ -125,7 +126,7 @@ def start(io_loop=None, check_time=500): gen_log.warning("tornado.autoreload started more than once in the same process") modify_times = {} callback = functools.partial(_reload_on_update, modify_times) - scheduler = ioloop.PeriodicCallback(callback, check_time, io_loop=io_loop) + scheduler = ioloop.PeriodicCallback(callback, check_time) scheduler.start() @@ -137,7 +138,7 @@ def wait(): the command-line interface in `main`) """ io_loop = ioloop.IOLoop() - start(io_loop) + io_loop.add_callback(start) io_loop.start() @@ -209,21 +210,33 @@ def _reload(): # ioloop.set_blocking_log_threshold so it doesn't fire # after the exec. signal.setitimer(signal.ITIMER_REAL, 0, 0) - # sys.path fixes: see comments at top of file. If sys.path[0] is an empty - # string, we were (probably) invoked with -m and the effective path - # is about to change on re-exec. Add the current directory to $PYTHONPATH - # to ensure that the new process sees the same path we did. - path_prefix = '.' + os.pathsep - if (sys.path[0] == '' and - not os.environ.get("PYTHONPATH", "").startswith(path_prefix)): - os.environ["PYTHONPATH"] = (path_prefix + - os.environ.get("PYTHONPATH", "")) + # sys.path fixes: see comments at top of file. If __main__.__spec__ + # exists, we were invoked with -m and the effective path is about to + # change on re-exec. Reconstruct the original command line to + # ensure that the new process sees the same path we did. If + # __spec__ is not available (Python < 3.4), check instead if + # sys.path[0] is an empty string and add the current directory to + # $PYTHONPATH. + if _autoreload_is_main: + spec = _original_spec + argv = _original_argv + else: + spec = getattr(sys.modules['__main__'], '__spec__', None) + argv = sys.argv + if spec: + argv = ['-m', spec.name] + argv[1:] + else: + path_prefix = '.' + os.pathsep + if (sys.path[0] == '' and + not os.environ.get("PYTHONPATH", "").startswith(path_prefix)): + os.environ["PYTHONPATH"] = (path_prefix + + os.environ.get("PYTHONPATH", "")) if not _has_execv: - subprocess.Popen([sys.executable] + sys.argv) - sys.exit(0) + subprocess.Popen([sys.executable] + argv) + os._exit(0) else: try: - os.execv(sys.executable, [sys.executable] + sys.argv) + os.execv(sys.executable, [sys.executable] + argv) except OSError: # Mac OS X versions prior to 10.6 do not support execv in # a process that contains multiple threads. Instead of @@ -236,8 +249,7 @@ def _reload(): # Unfortunately the errno returned in this case does not # appear to be consistent, so we can't easily check for # this error specifically. - os.spawnv(os.P_NOWAIT, sys.executable, - [sys.executable] + sys.argv) + os.spawnv(os.P_NOWAIT, sys.executable, [sys.executable] + argv) # At this point the IOLoop has been closed and finally # blocks will experience errors if we allow the stack to # unwind, so just exit uncleanly. @@ -264,7 +276,17 @@ def main(): can catch import-time problems like syntax errors that would otherwise prevent the script from reaching its call to `wait`. """ + # Remember that we were launched with autoreload as main. + # The main module can be tricky; set the variables both in our globals + # (which may be __main__) and the real importable version. + import tornado.autoreload + global _autoreload_is_main + global _original_argv, _original_spec + tornado.autoreload._autoreload_is_main = _autoreload_is_main = True original_argv = sys.argv + tornado.autoreload._original_argv = _original_argv = original_argv + original_spec = getattr(sys.modules['__main__'], '__spec__', None) + tornado.autoreload._original_spec = _original_spec = original_spec sys.argv = sys.argv[:] if len(sys.argv) >= 3 and sys.argv[1] == "-m": mode = "module" diff --git a/server/www/packages/packages-common/tornado/concurrent.py b/server/www/packages/packages-common/tornado/concurrent.py index 667e6b1..78b2091 100644 --- a/server/www/packages/packages-common/tornado/concurrent.py +++ b/server/www/packages/packages-common/tornado/concurrent.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2012 Facebook # @@ -13,13 +12,19 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -"""Utilities for working with threads and ``Futures``. +"""Utilities for working with ``Future`` objects. ``Futures`` are a pattern for concurrent programming introduced in -Python 3.2 in the `concurrent.futures` package. This package defines -a mostly-compatible `Future` class designed for use from coroutines, -as well as some utility functions for interacting with the -`concurrent.futures` package. +Python 3.2 in the `concurrent.futures` package, and also adopted (in a +slightly different form) in Python 3.4's `asyncio` package. This +package defines a ``Future`` class that is an alias for `asyncio.Future` +when available, and a compatible implementation for older versions of +Python. It also includes some utility functions for interacting with +``Future`` objects. + +While this package is an important part of Tornado's internal +implementation, applications rarely need to interact with it +directly. """ from __future__ import absolute_import, division, print_function @@ -28,6 +33,7 @@ import platform import textwrap import traceback import sys +import warnings from tornado.log import app_log from tornado.stack_context import ExceptionStackContext, wrap @@ -38,6 +44,11 @@ try: except ImportError: futures = None +try: + import asyncio +except ImportError: + asyncio = None + try: import typing except ImportError: @@ -138,16 +149,17 @@ class Future(object): Tornado they are normally used with `.IOLoop.add_future` or by yielding them in a `.gen.coroutine`. - `tornado.concurrent.Future` is similar to - `concurrent.futures.Future`, but not thread-safe (and therefore - faster for use with single-threaded event loops). + `tornado.concurrent.Future` is an alias for `asyncio.Future` when + that package is available (Python 3.4+). Unlike + `concurrent.futures.Future`, the ``Futures`` used by Tornado and + `asyncio` are not thread-safe (and therefore faster for use with + single-threaded event loops). - In addition to ``exception`` and ``set_exception``, methods ``exc_info`` - and ``set_exc_info`` are supported to capture tracebacks in Python 2. - The traceback is automatically available in Python 3, but in the - Python 2 futures backport this information is discarded. - This functionality was previously available in a separate class - ``TracebackFuture``, which is now a deprecated alias for this class. + In addition to ``exception`` and ``set_exception``, Tornado's + ``Future`` implementation supports storing an ``exc_info`` triple + to support better tracebacks on Python 2. To set an ``exc_info`` + triple, use `future_set_exc_info`, and to retrieve one, call + `result()` (which will raise it). .. versionchanged:: 4.0 `tornado.concurrent.Future` is always a thread-unsafe ``Future`` @@ -164,6 +176,17 @@ class Future(object): where it results in undesired logging it may be necessary to suppress the logging by ensuring that the exception is observed: ``f.add_done_callback(lambda f: f.exception())``. + + .. versionchanged:: 5.0 + + This class was previoiusly available under the name + ``TracebackFuture``. This name, which was deprecated since + version 4.0, has been removed. When `asyncio` is available + ``tornado.concurrent.Future`` is now an alias for + `asyncio.Future`. Like `asyncio.Future`, callbacks are now + always scheduled on the `.IOLoop` and are never run + synchronously. + """ def __init__(self): self._done = False @@ -265,7 +288,8 @@ class Future(object): `add_done_callback` directly. """ if self._done: - fn(self) + from tornado.ioloop import IOLoop + IOLoop.current().add_callback(fn, self) else: self._callbacks.append(fn) @@ -320,13 +344,12 @@ class Future(object): def _set_done(self): self._done = True - for cb in self._callbacks: - try: - cb(self) - except Exception: - app_log.exception('Exception in callback %r for %r', - cb, self) - self._callbacks = None + if self._callbacks: + from tornado.ioloop import IOLoop + loop = IOLoop.current() + for cb in self._callbacks: + loop.add_callback(cb, self) + self._callbacks = None # On Python 3.3 or older, objects with a destructor part of a reference # cycle are never destroyed. It's no longer the case on Python 3.4 thanks to @@ -344,7 +367,8 @@ class Future(object): self, ''.join(tb).rstrip()) -TracebackFuture = Future +if asyncio is not None: + Future = asyncio.Future # noqa if futures is None: FUTURES = Future # type: typing.Union[type, typing.Tuple[type, ...]] @@ -358,11 +382,11 @@ def is_future(x): class DummyExecutor(object): def submit(self, fn, *args, **kwargs): - future = TracebackFuture() + future = Future() try: - future.set_result(fn(*args, **kwargs)) + future_set_result_unless_cancelled(future, fn(*args, **kwargs)) except Exception: - future.set_exc_info(sys.exc_info()) + future_set_exc_info(future, sys.exc_info()) return future def shutdown(self, wait=True): @@ -378,29 +402,53 @@ def run_on_executor(*args, **kwargs): The decorated method may be called with a ``callback`` keyword argument and returns a future. - The `.IOLoop` and executor to be used are determined by the ``io_loop`` - and ``executor`` attributes of ``self``. To use different attributes, - pass keyword arguments to the decorator:: + The executor to be used is determined by the ``executor`` + attributes of ``self``. To use a different attribute name, pass a + keyword argument to the decorator:: @run_on_executor(executor='_thread_pool') def foo(self): pass + This decorator should not be confused with the similarly-named + `.IOLoop.run_in_executor`. In general, using ``run_in_executor`` + when *calling* a blocking method is recommended instead of using + this decorator when *defining* a method. If compatibility with older + versions of Tornado is required, consider defining an executor + and using ``executor.submit()`` at the call site. + .. versionchanged:: 4.2 Added keyword arguments to use alternative attributes. + + .. versionchanged:: 5.0 + Always uses the current IOLoop instead of ``self.io_loop``. + + .. versionchanged:: 5.1 + Returns a `.Future` compatible with ``await`` instead of a + `concurrent.futures.Future`. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in + 6.0. The decorator itself is discouraged in new code but will + not be removed in 6.0. """ def run_on_executor_decorator(fn): executor = kwargs.get("executor", "executor") - io_loop = kwargs.get("io_loop", "io_loop") @functools.wraps(fn) def wrapper(self, *args, **kwargs): callback = kwargs.pop("callback", None) - future = getattr(self, executor).submit(fn, self, *args, **kwargs) + async_future = Future() + conc_future = getattr(self, executor).submit(fn, self, *args, **kwargs) + chain_future(conc_future, async_future) if callback: - getattr(self, io_loop).add_future( - future, lambda future: callback(future.result())) - return future + warnings.warn("callback arguments are deprecated, use the returned Future instead", + DeprecationWarning) + from tornado.ioloop import IOLoop + IOLoop.current().add_future( + async_future, lambda future: callback(future.result())) + return async_future return wrapper if args and kwargs: raise ValueError("cannot combine positional and keyword args") @@ -418,6 +466,10 @@ def return_future(f): """Decorator to make a function that returns via callback return a `Future`. + This decorator was provided to ease the transition from + callback-oriented code to coroutines. It is not recommended for + new code. + The wrapped function should take a ``callback`` keyword argument and invoke it with one argument when it has finished. To signal failure, the function can simply raise an exception (which will be @@ -425,13 +477,13 @@ def return_future(f): From the caller's perspective, the callback argument is optional. If one is given, it will be invoked when the function is complete - with `Future.result()` as an argument. If the function fails, the + with ``Future.result()`` as an argument. If the function fails, the callback will not be run and an exception will be raised into the surrounding `.StackContext`. If no callback is given, the caller should use the ``Future`` to wait for the function to complete (perhaps by yielding it in a - `.gen.engine` function, or passing it to `.IOLoop.add_future`). + coroutine, or passing it to `.IOLoop.add_future`). Usage: @@ -442,31 +494,52 @@ def return_future(f): # Do stuff (possibly asynchronous) callback(result) - @gen.engine - def caller(callback): - yield future_func(arg1, arg2) - callback() + async def caller(): + await future_func(arg1, arg2) .. Note that ``@return_future`` and ``@gen.engine`` can be applied to the same function, provided ``@return_future`` appears first. However, consider using ``@gen.coroutine`` instead of this combination. + + .. versionchanged:: 5.1 + + Now raises a `.DeprecationWarning` if a callback argument is passed to + the decorated function and deprecation warnings are enabled. + + .. deprecated:: 5.1 + + This decorator will be removed in Tornado 6.0. New code should + use coroutines directly instead of wrapping callback-based code + with this decorator. Interactions with non-Tornado + callback-based code should be managed explicitly to avoid + relying on the `.ExceptionStackContext` built into this + decorator. """ + warnings.warn("@return_future is deprecated, use coroutines instead", + DeprecationWarning) + return _non_deprecated_return_future(f) + + +def _non_deprecated_return_future(f): + # Allow auth.py to use this decorator without triggering + # deprecation warnings. This will go away once auth.py has removed + # its legacy interfaces in 6.0. replacer = ArgReplacer(f, 'callback') @functools.wraps(f) def wrapper(*args, **kwargs): - future = TracebackFuture() + future = Future() callback, args, kwargs = replacer.replace( - lambda value=_NO_RESULT: future.set_result(value), + lambda value=_NO_RESULT: future_set_result_unless_cancelled(future, value), args, kwargs) def handle_error(typ, value, tb): - future.set_exc_info((typ, value, tb)) + future_set_exc_info(future, (typ, value, tb)) return True exc_info = None - with ExceptionStackContext(handle_error): + with ExceptionStackContext(handle_error, delay_warning=True): try: result = f(*args, **kwargs) if result is not None: @@ -489,13 +562,16 @@ def return_future(f): # immediate exception, and again when the future resolves and # the callback triggers its exception by calling future.result()). if callback is not None: + warnings.warn("callback arguments are deprecated, use the returned Future instead", + DeprecationWarning) + def run_callback(future): result = future.result() if result is _NO_RESULT: callback() else: callback(future.result()) - future.add_done_callback(wrap(run_callback)) + future_add_done_callback(future, wrap(run_callback)) return future return wrapper @@ -505,17 +581,72 @@ def chain_future(a, b): The result (success or failure) of ``a`` will be copied to ``b``, unless ``b`` has already been completed or cancelled by the time ``a`` finishes. + + .. versionchanged:: 5.0 + + Now accepts both Tornado/asyncio `Future` objects and + `concurrent.futures.Future`. + """ def copy(future): assert future is a if b.done(): return - if (isinstance(a, TracebackFuture) and - isinstance(b, TracebackFuture) and + if (hasattr(a, 'exc_info') and a.exc_info() is not None): - b.set_exc_info(a.exc_info()) + future_set_exc_info(b, a.exc_info()) elif a.exception() is not None: b.set_exception(a.exception()) else: b.set_result(a.result()) - a.add_done_callback(copy) + if isinstance(a, Future): + future_add_done_callback(a, copy) + else: + # concurrent.futures.Future + from tornado.ioloop import IOLoop + IOLoop.current().add_future(a, copy) + + +def future_set_result_unless_cancelled(future, value): + """Set the given ``value`` as the `Future`'s result, if not cancelled. + + Avoids asyncio.InvalidStateError when calling set_result() on + a cancelled `asyncio.Future`. + + .. versionadded:: 5.0 + """ + if not future.cancelled(): + future.set_result(value) + + +def future_set_exc_info(future, exc_info): + """Set the given ``exc_info`` as the `Future`'s exception. + + Understands both `asyncio.Future` and Tornado's extensions to + enable better tracebacks on Python 2. + + .. versionadded:: 5.0 + """ + if hasattr(future, 'set_exc_info'): + # Tornado's Future + future.set_exc_info(exc_info) + else: + # asyncio.Future + future.set_exception(exc_info[1]) + + +def future_add_done_callback(future, callback): + """Arrange to call ``callback`` when ``future`` is complete. + + ``callback`` is invoked with one argument, the ``future``. + + If ``future`` is already done, ``callback`` is invoked immediately. + This may differ from the behavior of ``Future.add_done_callback``, + which makes no such guarantee. + + .. versionadded:: 5.0 + """ + if future.done(): + callback(future) + else: + future.add_done_callback(callback) diff --git a/server/www/packages/packages-common/tornado/curl_httpclient.py b/server/www/packages/packages-common/tornado/curl_httpclient.py index eef4a17..7f5cb10 100644 --- a/server/www/packages/packages-common/tornado/curl_httpclient.py +++ b/server/www/packages/packages-common/tornado/curl_httpclient.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -37,8 +36,8 @@ curl_log = logging.getLogger('tornado.curl_httpclient') class CurlAsyncHTTPClient(AsyncHTTPClient): - def initialize(self, io_loop, max_clients=10, defaults=None): - super(CurlAsyncHTTPClient, self).initialize(io_loop, defaults=defaults) + def initialize(self, max_clients=10, defaults=None): + super(CurlAsyncHTTPClient, self).initialize(defaults=defaults) self._multi = pycurl.CurlMulti() self._multi.setopt(pycurl.M_TIMERFUNCTION, self._set_timeout) self._multi.setopt(pycurl.M_SOCKETFUNCTION, self._handle_socket) @@ -53,7 +52,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): # SOCKETFUNCTION. Mitigate the effects of such bugs by # forcing a periodic scan of all active requests. self._force_timeout_callback = ioloop.PeriodicCallback( - self._handle_force_timeout, 1000, io_loop=io_loop) + self._handle_force_timeout, 1000) self._force_timeout_callback.start() # Work around a bug in libcurl 7.29.0: Some fields in the curl @@ -74,8 +73,14 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): self._multi.close() super(CurlAsyncHTTPClient, self).close() + # Set below properties to None to reduce the reference count of current + # instance, because those properties hold some methods of current + # instance that will case circular reference. + self._force_timeout_callback = None + self._multi = None + def fetch_impl(self, request, callback): - self._requests.append((request, callback)) + self._requests.append((request, callback, self.io_loop.time())) self._process_queue() self._set_timeout(0) @@ -200,13 +205,15 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): while self._free_list and self._requests: started += 1 curl = self._free_list.pop() - (request, callback) = self._requests.popleft() + (request, callback, queue_start_time) = self._requests.popleft() curl.info = { "headers": httputil.HTTPHeaders(), "buffer": BytesIO(), "request": request, "callback": callback, + "queue_start_time": queue_start_time, "curl_start_time": time.time(), + "curl_start_ioloop_time": self.io_loop.current().time(), } try: self._curl_setup_request( @@ -252,9 +259,10 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): # the various curl timings are documented at # http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html time_info = dict( - queue=info["curl_start_time"] - info["request"].start_time, + queue=info["curl_start_ioloop_time"] - info["queue_start_time"], namelookup=curl.getinfo(pycurl.NAMELOOKUP_TIME), connect=curl.getinfo(pycurl.CONNECT_TIME), + appconnect=curl.getinfo(pycurl.APPCONNECT_TIME), pretransfer=curl.getinfo(pycurl.PRETRANSFER_TIME), starttransfer=curl.getinfo(pycurl.STARTTRANSFER_TIME), total=curl.getinfo(pycurl.TOTAL_TIME), @@ -265,7 +273,8 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): request=info["request"], code=code, headers=info["headers"], buffer=buffer, effective_url=effective_url, error=error, reason=info['headers'].get("X-Http-Reason", None), - request_time=time.time() - info["curl_start_time"], + request_time=self.io_loop.time() - info["curl_start_ioloop_time"], + start_time=info["curl_start_time"], time_info=time_info)) except Exception: self.handle_callback_exception(info["callback"]) @@ -313,17 +322,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): self.io_loop.add_callback(request.streaming_callback, chunk) else: write_function = buffer.write - if bytes is str: # py2 - curl.setopt(pycurl.WRITEFUNCTION, write_function) - else: # py3 - # Upstream pycurl doesn't support py3, but ubuntu 12.10 includes - # a fork/port. That version has a bug in which it passes unicode - # strings instead of bytes to the WRITEFUNCTION. This means that - # if you use a WRITEFUNCTION (which tornado always does), you cannot - # download arbitrary binary data. This needs to be fixed in the - # ported pycurl package, but in the meantime this lambda will - # make it work for downloading (utf8) text. - curl.setopt(pycurl.WRITEFUNCTION, lambda s: write_function(utf8(s))) + curl.setopt(pycurl.WRITEFUNCTION, write_function) curl.setopt(pycurl.FOLLOWLOCATION, request.follow_redirects) curl.setopt(pycurl.MAXREDIRS, request.max_redirects) curl.setopt(pycurl.CONNECTTIMEOUT_MS, int(1000 * request.connect_timeout)) @@ -342,8 +341,8 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): curl.setopt(pycurl.PROXY, request.proxy_host) curl.setopt(pycurl.PROXYPORT, request.proxy_port) if request.proxy_username: - credentials = '%s:%s' % (request.proxy_username, - request.proxy_password) + credentials = httputil.encode_username_password(request.proxy_username, + request.proxy_password) curl.setopt(pycurl.PROXYUSERPWD, credentials) if (request.proxy_auth_mode is None or @@ -435,8 +434,6 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): curl.setopt(pycurl.INFILESIZE, len(request.body or '')) if request.auth_username is not None: - userpwd = "%s:%s" % (request.auth_username, request.auth_password or '') - if request.auth_mode is None or request.auth_mode == "basic": curl.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC) elif request.auth_mode == "digest": @@ -444,7 +441,9 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): else: raise ValueError("Unsupported auth_mode %s" % request.auth_mode) - curl.setopt(pycurl.USERPWD, native_str(userpwd)) + userpwd = httputil.encode_username_password(request.auth_username, + request.auth_password) + curl.setopt(pycurl.USERPWD, userpwd) curl_log.debug("%s %s (username: %r)", request.method, request.url, request.auth_username) else: @@ -494,8 +493,10 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): def _curl_debug(self, debug_type, debug_msg): debug_types = ('I', '<', '>', '<', '>') if debug_type == 0: + debug_msg = native_str(debug_msg) curl_log.debug('%s', debug_msg.strip()) elif debug_type in (1, 2): + debug_msg = native_str(debug_msg) for line in debug_msg.splitlines(): curl_log.debug('%s %s', debug_types[debug_type], line) elif debug_type == 4: diff --git a/server/www/packages/packages-common/tornado/escape.py b/server/www/packages/packages-common/tornado/escape.py index 2ca3fe3..a79ece6 100644 --- a/server/www/packages/packages-common/tornado/escape.py +++ b/server/www/packages/packages-common/tornado/escape.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -274,7 +273,9 @@ def recursive_unicode(obj): # This regex should avoid those problems. # Use to_unicode instead of tornado.util.u - we don't want backslashes getting # processed as escapes. -_URL_RE = re.compile(to_unicode(r"""\b((?:([\w-]+):(/{1,3})|www[.])(?:(?:(?:[^\s&()]|&|")*(?:[^!"#$%&'()*+,.:;<=>?@\[\]^`{|}~\s]))|(?:\((?:[^\s&()]|&|")*\)))+)""")) +_URL_RE = re.compile(to_unicode( + r"""\b((?:([\w-]+):(/{1,3})|www[.])(?:(?:(?:[^\s&()]|&|")*(?:[^!"#$%&'()*+,.:;<=>?@\[\]^`{|}~\s]))|(?:\((?:[^\s&()]|&|")*\)))+)""" # noqa: E501 +)) def linkify(text, shorten=False, extra_params="", @@ -289,24 +290,24 @@ def linkify(text, shorten=False, extra_params="", * ``shorten``: Long urls will be shortened for display. * ``extra_params``: Extra text to include in the link tag, or a callable - taking the link as an argument and returning the extra text - e.g. ``linkify(text, extra_params='rel="nofollow" class="external"')``, - or:: + taking the link as an argument and returning the extra text + e.g. ``linkify(text, extra_params='rel="nofollow" class="external"')``, + or:: - def extra_params_cb(url): - if url.startswith("http://example.com"): - return 'class="internal"' - else: - return 'class="external" rel="nofollow"' - linkify(text, extra_params=extra_params_cb) + def extra_params_cb(url): + if url.startswith("http://example.com"): + return 'class="internal"' + else: + return 'class="external" rel="nofollow"' + linkify(text, extra_params=extra_params_cb) * ``require_protocol``: Only linkify urls which include a protocol. If - this is False, urls such as www.facebook.com will also be linkified. + this is False, urls such as www.facebook.com will also be linkified. * ``permitted_protocols``: List (or set) of protocols which should be - linkified, e.g. ``linkify(text, permitted_protocols=["http", "ftp", - "mailto"])``. It is very unsafe to include protocols such as - ``javascript``. + linkified, e.g. ``linkify(text, permitted_protocols=["http", "ftp", + "mailto"])``. It is very unsafe to include protocols such as + ``javascript``. """ if extra_params and not callable(extra_params): extra_params = " " + extra_params.strip() diff --git a/server/www/packages/packages-common/tornado/gen.py b/server/www/packages/packages-common/tornado/gen.py index 99f9106..3556374 100644 --- a/server/www/packages/packages-common/tornado/gen.py +++ b/server/www/packages/packages-common/tornado/gen.py @@ -1,9 +1,23 @@ -"""``tornado.gen`` is a generator-based interface to make it easier to -work in an asynchronous environment. Code using the ``gen`` module -is technically asynchronous, but it is written as a single generator +"""``tornado.gen`` implements generator-based coroutines. + +.. note:: + + The "decorator and generator" approach in this module is a + precursor to native coroutines (using ``async def`` and ``await``) + which were introduced in Python 3.5. Applications that do not + require compatibility with older versions of Python should use + native coroutines instead. Some parts of this module are still + useful with native coroutines, notably `multi`, `sleep`, + `WaitIterator`, and `with_timeout`. Some of these functions have + counterparts in the `asyncio` module which may be used as well, + although the two may not necessarily be 100% compatible. + +Coroutines provide an easier way to work in an asynchronous +environment than chaining callbacks. Code using coroutines is +technically asynchronous, but it is written as a single generator instead of a collection of separate functions. -For example, the following asynchronous handler: +For example, the following callback-based asynchronous handler: .. testcode:: @@ -37,7 +51,7 @@ could be written with ``gen`` as: :hide: Most asynchronous functions in Tornado return a `.Future`; -yielding this object returns its `~.Future.result`. +yielding this object returns its ``Future.result``. You can also yield a list or dict of ``Futures``, which will be started at the same time and run in parallel; a list or dict of results will @@ -81,15 +95,15 @@ import functools import itertools import os import sys -import textwrap import types -import weakref +import warnings -from tornado.concurrent import Future, TracebackFuture, is_future, chain_future +from tornado.concurrent import (Future, is_future, chain_future, future_set_exc_info, + future_add_done_callback, future_set_result_unless_cancelled) from tornado.ioloop import IOLoop from tornado.log import app_log from tornado import stack_context -from tornado.util import PY3, raise_exc_info +from tornado.util import PY3, raise_exc_info, TimeoutError try: try: @@ -154,10 +168,6 @@ class ReturnValueIgnoredError(Exception): pass -class TimeoutError(Exception): - """Exception raised by ``with_timeout``.""" - - def _value_from_stopiteration(e): try: # StopIteration has a value attribute beginning in py33. @@ -173,6 +183,21 @@ def _value_from_stopiteration(e): return None +def _create_future(): + future = Future() + # Fixup asyncio debug info by removing extraneous stack entries + source_traceback = getattr(future, "_source_traceback", ()) + while source_traceback: + # Each traceback entry is equivalent to a + # (filename, self.lineno, self.name, self.line) tuple + filename = source_traceback[-1][0] + if filename == __file__: + del source_traceback[-1] + else: + break + return future + + def engine(func): """Callback-oriented decorator for asynchronous generators. @@ -189,7 +214,14 @@ def engine(func): they are finished. One notable exception is the `~tornado.web.RequestHandler` :ref:`HTTP verb methods `, which use ``self.finish()`` in place of a callback argument. + + .. deprecated:: 5.1 + + This decorator will be removed in 6.0. Use `coroutine` or + ``async def`` instead. """ + warnings.warn("gen.engine is deprecated, use gen.coroutine or async def instead", + DeprecationWarning) func = _make_coroutine_wrapper(func, replace_callback=False) @functools.wraps(func) @@ -204,11 +236,11 @@ def engine(func): # The engine interface doesn't give us any way to return # errors but to raise them into the stack context. # Save the stack context here to use when the Future has resolved. - future.add_done_callback(stack_context.wrap(final_callback)) + future_add_done_callback(future, stack_context.wrap(final_callback)) return wrapper -def coroutine(func, replace_callback=True): +def coroutine(func): """Decorator for asynchronous generators. Any generator that yields objects from this module must be wrapped @@ -229,9 +261,6 @@ def coroutine(func, replace_callback=True): ``callback`` argument is not visible inside the decorated function; it is handled by the decorator itself. - From the caller's perspective, ``@gen.coroutine`` is similar to - the combination of ``@return_future`` and ``@gen.engine``. - .. warning:: When exceptions occur inside a coroutine, the exception @@ -242,30 +271,14 @@ def coroutine(func, replace_callback=True): `.IOLoop.run_sync` for top-level calls, or passing the `.Future` to `.IOLoop.add_future`. + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ return _make_coroutine_wrapper(func, replace_callback=True) -# Ties lifetime of runners to their result futures. Github Issue #1769 -# Generators, like any object in Python, must be strong referenced -# in order to not be cleaned up by the garbage collector. When using -# coroutines, the Runner object is what strong-refs the inner -# generator. However, the only item that strong-reffed the Runner -# was the last Future that the inner generator yielded (via the -# Future's internal done_callback list). Usually this is enough, but -# it is also possible for this Future to not have any strong references -# other than other objects referenced by the Runner object (usually -# when using other callback patterns and/or weakrefs). In this -# situation, if a garbage collection ran, a cycle would be detected and -# Runner objects could be destroyed along with their inner generators -# and everything in their local scope. -# This map provides strong references to Runner objects as long as -# their result future objects also have strong references (typically -# from the parent coroutine's Runner). This keeps the coroutine's -# Runner alive. -_futures_to_runners = weakref.WeakKeyDictionary() - - def _make_coroutine_wrapper(func, replace_callback): """The inner workings of ``@gen.coroutine`` and ``@gen.engine``. @@ -281,9 +294,11 @@ def _make_coroutine_wrapper(func, replace_callback): @functools.wraps(wrapped) def wrapper(*args, **kwargs): - future = TracebackFuture() + future = _create_future() if replace_callback and 'callback' in kwargs: + warnings.warn("callback arguments are deprecated, use the returned Future instead", + DeprecationWarning, stacklevel=2) callback = kwargs.pop('callback') IOLoop.current().add_future( future, lambda future: callback(future.result())) @@ -293,8 +308,12 @@ def _make_coroutine_wrapper(func, replace_callback): except (Return, StopIteration) as e: result = _value_from_stopiteration(e) except Exception: - future.set_exc_info(sys.exc_info()) - return future + future_set_exc_info(future, sys.exc_info()) + try: + return future + finally: + # Avoid circular references + future = None else: if isinstance(result, GeneratorType): # Inline the first iteration of Runner.run. This lets us @@ -306,17 +325,26 @@ def _make_coroutine_wrapper(func, replace_callback): orig_stack_contexts = stack_context._state.contexts yielded = next(result) if stack_context._state.contexts is not orig_stack_contexts: - yielded = TracebackFuture() + yielded = _create_future() yielded.set_exception( stack_context.StackContextInconsistentError( 'stack_context inconsistency (probably caused ' 'by yield within a "with StackContext" block)')) except (StopIteration, Return) as e: - future.set_result(_value_from_stopiteration(e)) + future_set_result_unless_cancelled(future, _value_from_stopiteration(e)) except Exception: - future.set_exc_info(sys.exc_info()) + future_set_exc_info(future, sys.exc_info()) else: - _futures_to_runners[future] = Runner(result, future, yielded) + # Provide strong references to Runner objects as long + # as their result future objects also have strong + # references (typically from the parent coroutine's + # Runner). This keeps the coroutine's Runner alive. + # We do this by exploiting the public API + # add_done_callback() instead of putting a private + # attribute on the Future. + # (Github issues #1769, #2229). + runner = Runner(result, future, yielded) + future.add_done_callback(lambda _: runner) yielded = None try: return future @@ -330,7 +358,7 @@ def _make_coroutine_wrapper(func, replace_callback): # used in the absence of cycles). We can avoid the # cycle by clearing the local variable after we return it. future = None - future.set_result(result) + future_set_result_unless_cancelled(future, result) return future wrapper.__wrapped__ = wrapped @@ -444,7 +472,7 @@ class WaitIterator(object): self._running_future = None for future in futures: - future.add_done_callback(self._done_callback) + future_add_done_callback(future, self._done_callback) def done(self): """Returns True if this iterator has no more results.""" @@ -460,7 +488,7 @@ class WaitIterator(object): Note that this `.Future` will not be the same object as any of the inputs. """ - self._running_future = TracebackFuture() + self._running_future = Future() if self._finished: self._return_result(self._finished.popleft()) @@ -482,9 +510,8 @@ class WaitIterator(object): self.current_future = done self.current_index = self._unfinished.pop(done) - @coroutine def __aiter__(self): - raise Return(self) + return self def __anext__(self): if self.done(): @@ -497,8 +524,13 @@ class YieldPoint(object): """Base class for objects that may be yielded from the generator. .. deprecated:: 4.0 - Use `Futures <.Future>` instead. + Use `Futures <.Future>` instead. This class and all its subclasses + will be removed in 6.0 """ + def __init__(self): + warnings.warn("YieldPoint is deprecated, use Futures instead", + DeprecationWarning) + def start(self, runner): """Called by the runner after the generator has yielded. @@ -535,9 +567,11 @@ class Callback(YieldPoint): is given it will be returned by `Wait`. .. deprecated:: 4.0 - Use `Futures <.Future>` instead. + Use `Futures <.Future>` instead. This class will be removed in 6.0. """ def __init__(self, key): + warnings.warn("gen.Callback is deprecated, use Futures instead", + DeprecationWarning) self.key = key def start(self, runner): @@ -555,9 +589,11 @@ class Wait(YieldPoint): """Returns the argument passed to the result of a previous `Callback`. .. deprecated:: 4.0 - Use `Futures <.Future>` instead. + Use `Futures <.Future>` instead. This class will be removed in 6.0. """ def __init__(self, key): + warnings.warn("gen.Wait is deprecated, use Futures instead", + DeprecationWarning) self.key = key def start(self, runner): @@ -579,9 +615,11 @@ class WaitAll(YieldPoint): `WaitAll` is equivalent to yielding a list of `Wait` objects. .. deprecated:: 4.0 - Use `Futures <.Future>` instead. + Use `Futures <.Future>` instead. This class will be removed in 6.0. """ def __init__(self, keys): + warnings.warn("gen.WaitAll is deprecated, use gen.multi instead", + DeprecationWarning) self.keys = keys def start(self, runner): @@ -605,33 +643,43 @@ def Task(func, *args, **kwargs): ``gen.Task`` is now a function that returns a `.Future`, instead of a subclass of `YieldPoint`. It still behaves the same way when yielded. + + .. deprecated:: 5.1 + This function is deprecated and will be removed in 6.0. """ - future = Future() + warnings.warn("gen.Task is deprecated, use Futures instead", + DeprecationWarning) + future = _create_future() def handle_exception(typ, value, tb): if future.done(): return False - future.set_exc_info((typ, value, tb)) + future_set_exc_info(future, (typ, value, tb)) return True def set_result(result): if future.done(): return - future.set_result(result) + future_set_result_unless_cancelled(future, result) with stack_context.ExceptionStackContext(handle_exception): func(*args, callback=_argument_adapter(set_result), **kwargs) return future class YieldFuture(YieldPoint): - def __init__(self, future, io_loop=None): + def __init__(self, future): """Adapts a `.Future` to the `YieldPoint` interface. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + + .. deprecated:: 5.1 + This class will be removed in 6.0. """ + warnings.warn("YieldFuture is deprecated, use Futures instead", + DeprecationWarning) self.future = future - self.io_loop = io_loop or IOLoop.current() + self.io_loop = IOLoop.current() def start(self, runner): if not self.future.done(): @@ -704,6 +752,10 @@ def multi(children, quiet_exceptions=()): This function is available under the names ``multi()`` and ``Multi()`` for historical reasons. + Cancelling a `.Future` returned by ``multi()`` does not cancel its + children. `asyncio.gather` is similar to ``multi()``, but it does + cancel its children. + .. versionchanged:: 4.2 If multiple yieldables fail, any exceptions after the first (which is raised) will be logged. Added the ``quiet_exceptions`` @@ -741,9 +793,11 @@ class MultiYieldPoint(YieldPoint): remains as an alias for the equivalent `multi` function. .. deprecated:: 4.3 - Use `multi` instead. + Use `multi` instead. This class will be removed in 6.0. """ def __init__(self, children, quiet_exceptions=()): + warnings.warn("MultiYieldPoint is deprecated, use Futures instead", + DeprecationWarning) self.keys = None if isinstance(children, dict): self.keys = list(children.keys()) @@ -812,12 +866,13 @@ def multi_future(children, quiet_exceptions=()): else: keys = None children = list(map(convert_yielded, children)) - assert all(is_future(i) for i in children) + assert all(is_future(i) or isinstance(i, _NullFuture) for i in children) unfinished_children = set(children) - future = Future() + future = _create_future() if not children: - future.set_result({} if keys is not None else []) + future_set_result_unless_cancelled(future, + {} if keys is not None else []) def callback(f): unfinished_children.remove(f) @@ -832,18 +887,19 @@ def multi_future(children, quiet_exceptions=()): app_log.error("Multiple exceptions in yield list", exc_info=True) else: - future.set_exc_info(sys.exc_info()) + future_set_exc_info(future, sys.exc_info()) if not future.done(): if keys is not None: - future.set_result(dict(zip(keys, result_list))) + future_set_result_unless_cancelled(future, + dict(zip(keys, result_list))) else: - future.set_result(result_list) + future_set_result_unless_cancelled(future, result_list) listening = set() for f in children: if f not in listening: listening.add(f) - f.add_done_callback(callback) + future_add_done_callback(f, callback) return future @@ -863,18 +919,18 @@ def maybe_future(x): if is_future(x): return x else: - fut = Future() + fut = _create_future() fut.set_result(x) return fut -def with_timeout(timeout, future, io_loop=None, quiet_exceptions=()): +def with_timeout(timeout, future, quiet_exceptions=()): """Wraps a `.Future` (or other yieldable object) in a timeout. - Raises `TimeoutError` if the input future does not complete before - ``timeout``, which may be specified in any form allowed by - `.IOLoop.add_timeout` (i.e. a `datetime.timedelta` or an absolute time - relative to `.IOLoop.time`) + Raises `tornado.util.TimeoutError` if the input future does not + complete before ``timeout``, which may be specified in any form + allowed by `.IOLoop.add_timeout` (i.e. a `datetime.timedelta` or + an absolute time relative to `.IOLoop.time`) If the wrapped `.Future` fails after it has timed out, the exception will be logged unless it is of a type contained in ``quiet_exceptions`` @@ -882,6 +938,10 @@ def with_timeout(timeout, future, io_loop=None, quiet_exceptions=()): Does not support `YieldPoint` subclasses. + The wrapped `.Future` is not canceled when the timeout expires, + permitting it to be reused. `asyncio.wait_for` is similar to this + function but it does cancel the wrapped `.Future` on timeout. + .. versionadded:: 4.0 .. versionchanged:: 4.1 @@ -890,6 +950,7 @@ def with_timeout(timeout, future, io_loop=None, quiet_exceptions=()): .. versionchanged:: 4.4 Added support for yieldable objects other than `.Future`. + """ # TODO: allow YieldPoints in addition to other yieldables? # Tricky to do with stack_context semantics. @@ -900,10 +961,9 @@ def with_timeout(timeout, future, io_loop=None, quiet_exceptions=()): # callers and B) concurrent futures can only be cancelled while they are # in the queue, so cancellation cannot reliably bound our waiting time. future = convert_yielded(future) - result = Future() + result = _create_future() chain_future(future, result) - if io_loop is None: - io_loop = IOLoop.current() + io_loop = IOLoop.current() def error_callback(future): try: @@ -914,17 +974,18 @@ def with_timeout(timeout, future, io_loop=None, quiet_exceptions=()): future, exc_info=True) def timeout_callback(): - result.set_exception(TimeoutError("Timeout")) + if not result.done(): + result.set_exception(TimeoutError("Timeout")) # In case the wrapped future goes on to fail, log it. - future.add_done_callback(error_callback) + future_add_done_callback(future, error_callback) timeout_handle = io_loop.add_timeout( timeout, timeout_callback) if isinstance(future, Future): # We know this future will resolve on the IOLoop, so we don't # need the extra thread-safety of IOLoop.add_future (and we also # don't care about StackContext here. - future.add_done_callback( - lambda future: io_loop.remove_timeout(timeout_handle)) + future_add_done_callback( + future, lambda future: io_loop.remove_timeout(timeout_handle)) else: # concurrent.futures.Futures may resolve on any thread, so we # need to route them back to the IOLoop. @@ -947,15 +1008,31 @@ def sleep(duration): .. versionadded:: 4.1 """ - f = Future() - IOLoop.current().call_later(duration, lambda: f.set_result(None)) + f = _create_future() + IOLoop.current().call_later(duration, + lambda: future_set_result_unless_cancelled(f, None)) return f -_null_future = Future() -_null_future.set_result(None) +class _NullFuture(object): + """_NullFuture resembles a Future that finished with a result of None. -moment = Future() + It's not actually a `Future` to avoid depending on a particular event loop. + Handled as a special case in the coroutine runner. + """ + def result(self): + return None + + def done(self): + return True + + +# _null_future is used as a dummy value in the coroutine runner. It differs +# from moment in that moment always adds a delay of one IOLoop iteration +# while _null_future is processed as soon as possible. +_null_future = _NullFuture() + +moment = _NullFuture() moment.__doc__ = \ """A special object which may be yielded to allow the IOLoop to run for one iteration. @@ -968,9 +1045,9 @@ Usage: ``yield gen.moment`` .. versionadded:: 4.0 .. deprecated:: 4.5 - ``yield None`` is now equivalent to ``yield gen.moment``. + ``yield None`` (or ``yield`` with no argument) is now equivalent to + ``yield gen.moment``. """ -moment.set_result(None) class Runner(object): @@ -979,7 +1056,7 @@ class Runner(object): Maintains information about pending callbacks and their results. The results of the generator are stored in ``result_future`` (a - `.TracebackFuture`) + `.Future`) """ def __init__(self, gen, result_future, first_yielded): self.gen = gen @@ -1023,9 +1100,10 @@ class Runner(object): self.results[key] = result if self.yield_point is not None and self.yield_point.is_ready(): try: - self.future.set_result(self.yield_point.get_result()) + future_set_result_unless_cancelled(self.future, + self.yield_point.get_result()) except: - self.future.set_exc_info(sys.exc_info()) + future_set_exc_info(self.future, sys.exc_info()) self.yield_point = None self.run() @@ -1084,14 +1162,15 @@ class Runner(object): raise LeakedCallbackError( "finished without waiting for callbacks %r" % self.pending_callbacks) - self.result_future.set_result(_value_from_stopiteration(e)) + future_set_result_unless_cancelled(self.result_future, + _value_from_stopiteration(e)) self.result_future = None self._deactivate_stack_context() return except Exception: self.finished = True self.future = _null_future - self.result_future.set_exc_info(sys.exc_info()) + future_set_exc_info(self.result_future, sys.exc_info()) self.result_future = None self._deactivate_stack_context() return @@ -1110,19 +1189,18 @@ class Runner(object): if isinstance(yielded, YieldPoint): # YieldPoints are too closely coupled to the Runner to go # through the generic convert_yielded mechanism. - self.future = TracebackFuture() + self.future = Future() def start_yield_point(): try: yielded.start(self) if yielded.is_ready(): - self.future.set_result( - yielded.get_result()) + future_set_result_unless_cancelled(self.future, yielded.get_result()) else: self.yield_point = yielded except Exception: - self.future = TracebackFuture() - self.future.set_exc_info(sys.exc_info()) + self.future = Future() + future_set_exc_info(self.future, sys.exc_info()) if self.stack_context_deactivate is None: # Start a stack context if this is the first @@ -1142,13 +1220,16 @@ class Runner(object): try: self.future = convert_yielded(yielded) except BadYieldError: - self.future = TracebackFuture() - self.future.set_exc_info(sys.exc_info()) + self.future = Future() + future_set_exc_info(self.future, sys.exc_info()) - if not self.future.done() or self.future is moment: + if self.future is moment: + self.io_loop.add_callback(self.run) + return False + elif not self.future.done(): def inner(f): # Break a reference cycle to speed GC. - f = None # noqa + f = None # noqa self.run() self.io_loop.add_future( self.future, inner) @@ -1161,8 +1242,8 @@ class Runner(object): def handle_exception(self, typ, value, tb): if not self.running and not self.finished: - self.future = TracebackFuture() - self.future.set_exc_info((typ, value, tb)) + self.future = Future() + future_set_exc_info(self.future, (typ, value, tb)) self.run() return True else: @@ -1194,20 +1275,10 @@ def _argument_adapter(callback): return wrapper -# Convert Awaitables into Futures. It is unfortunately possible -# to have infinite recursion here if those Awaitables assume that -# we're using a different coroutine runner and yield objects -# we don't understand. If that happens, the solution is to -# register that runner's yieldable objects with convert_yielded. -if sys.version_info >= (3, 3): - exec(textwrap.dedent(""" - @coroutine - def _wrap_awaitable(x): - if hasattr(x, '__await__'): - x = x.__await__() - return (yield from x) - """)) -else: +# Convert Awaitables into Futures. +try: + import asyncio +except ImportError: # Py2-compatible version for use with Cython. # Copied from PEP 380. @coroutine @@ -1254,6 +1325,13 @@ else: _r = _value_from_stopiteration(_e) break raise Return(_r) +else: + try: + _wrap_awaitable = asyncio.ensure_future + except AttributeError: + # asyncio.ensure_future was introduced in Python 3.4.4, but + # Debian jessie still ships with 3.4.2 so try the old name. + _wrap_awaitable = getattr(asyncio, 'async') def convert_yielded(yielded): @@ -1271,8 +1349,10 @@ def convert_yielded(yielded): .. versionadded:: 4.1 """ # Lists and dicts containing YieldPoints were handled earlier. - if yielded is None: + if yielded is None or yielded is moment: return moment + elif yielded is _null_future: + return _null_future elif isinstance(yielded, (list, dict)): return multi(yielded) elif is_future(yielded): @@ -1285,19 +1365,3 @@ def convert_yielded(yielded): if singledispatch is not None: convert_yielded = singledispatch(convert_yielded) - - try: - # If we can import t.p.asyncio, do it for its side effect - # (registering asyncio.Future with convert_yielded). - # It's ugly to do this here, but it prevents a cryptic - # infinite recursion in _wrap_awaitable. - # Note that even with this, asyncio integration is unlikely - # to work unless the application also configures AsyncIOLoop, - # but at least the error messages in that case are more - # comprehensible than a stack overflow. - import tornado.platform.asyncio - except ImportError: - pass - else: - # Reference the imported module to make pyflakes happy. - tornado diff --git a/server/www/packages/packages-common/tornado/http1connection.py b/server/www/packages/packages-common/tornado/http1connection.py index 53744ec..af7abe7 100644 --- a/server/www/packages/packages-common/tornado/http1connection.py +++ b/server/www/packages/packages-common/tornado/http1connection.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2014 Facebook # @@ -22,8 +21,10 @@ from __future__ import absolute_import, division, print_function import re +import warnings -from tornado.concurrent import Future +from tornado.concurrent import (Future, future_add_done_callback, + future_set_result_unless_cancelled) from tornado.escape import native_str, utf8 from tornado import gen from tornado import httputil @@ -164,7 +165,6 @@ class HTTP1Connection(httputil.HTTPConnection): header_data = yield gen.with_timeout( self.stream.io_loop.time() + self.params.header_timeout, header_future, - io_loop=self.stream.io_loop, quiet_exceptions=iostream.StreamClosedError) except gen.TimeoutError: self.close() @@ -224,7 +224,7 @@ class HTTP1Connection(httputil.HTTPConnection): try: yield gen.with_timeout( self.stream.io_loop.time() + self._body_timeout, - body_future, self.stream.io_loop, + body_future, quiet_exceptions=iostream.StreamClosedError) except gen.TimeoutError: gen_log.info("Timeout reading body from %s", @@ -251,6 +251,8 @@ class HTTP1Connection(httputil.HTTPConnection): except httputil.HTTPInputError as e: gen_log.info("Malformed HTTP message from %s: %s", self.context, e) + if not self.is_client: + yield self.stream.write(b'HTTP/1.1 400 Bad Request\r\n\r\n') self.close() raise gen.Return(False) finally: @@ -276,8 +278,14 @@ class HTTP1Connection(httputil.HTTPConnection): def set_close_callback(self, callback): """Sets a callback that will be run when the connection is closed. - .. deprecated:: 4.0 - Use `.HTTPMessageDelegate.on_connection_close` instead. + Note that this callback is slightly different from + `.HTTPMessageDelegate.on_connection_close`: The + `.HTTPMessageDelegate` method is called when the connection is + closed while recieving a message. This callback is used when + there is not an active delegate (for example, on the server + side this callback is used if the client closes the connection + after sending its request but before receiving all the + response. """ self._close_callback = stack_context.wrap(callback) @@ -290,7 +298,7 @@ class HTTP1Connection(httputil.HTTPConnection): self._close_callback = None callback() if not self._finish_future.done(): - self._finish_future.set_result(None) + future_set_result_unless_cancelled(self._finish_future, None) self._clear_callbacks() def close(self): @@ -298,7 +306,7 @@ class HTTP1Connection(httputil.HTTPConnection): self.stream.close() self._clear_callbacks() if not self._finish_future.done(): - self._finish_future.set_result(None) + future_set_result_unless_cancelled(self._finish_future, None) def detach(self): """Take control of the underlying stream. @@ -312,7 +320,7 @@ class HTTP1Connection(httputil.HTTPConnection): stream = self.stream self.stream = None if not self._finish_future.done(): - self._finish_future.set_result(None) + future_set_result_unless_cancelled(self._finish_future, None) return stream def set_body_timeout(self, timeout): @@ -349,19 +357,22 @@ class HTTP1Connection(httputil.HTTPConnection): # self._request_start_line.version or # start_line.version? self._request_start_line.version == 'HTTP/1.1' and - # 304 responses have no body (not even a zero-length body), and so - # should not have either Content-Length or Transfer-Encoding. - # headers. + # 1xx, 204 and 304 responses have no body (not even a zero-length + # body), and so should not have either Content-Length or + # Transfer-Encoding headers. start_line.code not in (204, 304) and + (start_line.code < 100 or start_line.code >= 200) and # No need to chunk the output if a Content-Length is specified. 'Content-Length' not in headers and # Applications are discouraged from touching Transfer-Encoding, # but if they do, leave it alone. 'Transfer-Encoding' not in headers) + # If connection to a 1.1 client will be closed, inform client + if (self._request_start_line.version == 'HTTP/1.1' and self._disconnect_on_finish): + headers['Connection'] = 'close' # If a 1.0 client asked for keep-alive, add the header. if (self._request_start_line.version == 'HTTP/1.0' and - (self._request_headers.get('Connection', '').lower() == - 'keep-alive')): + self._request_headers.get('Connection', '').lower() == 'keep-alive'): headers['Connection'] = 'Keep-Alive' if self._chunking_output: headers['Transfer-Encoding'] = 'chunked' @@ -391,6 +402,8 @@ class HTTP1Connection(httputil.HTTPConnection): future.exception() else: if callback is not None: + warnings.warn("callback argument is deprecated, use returned Future instead", + DeprecationWarning) self._write_callback = stack_context.wrap(callback) else: future = self._write_future = Future() @@ -419,7 +432,7 @@ class HTTP1Connection(httputil.HTTPConnection): def write(self, chunk, callback=None): """Implements `.HTTPConnection.write`. - For backwards compatibility is is allowed but deprecated to + For backwards compatibility it is allowed but deprecated to skip `write_headers` and instead call `write()` with a pre-encoded header block. """ @@ -430,6 +443,8 @@ class HTTP1Connection(httputil.HTTPConnection): self._write_future.exception() else: if callback is not None: + warnings.warn("callback argument is deprecated, use returned Future instead", + DeprecationWarning) self._write_callback = stack_context.wrap(callback) else: future = self._write_future = Future() @@ -464,7 +479,7 @@ class HTTP1Connection(httputil.HTTPConnection): if self._pending_write is None: self._finish_request(None) else: - self._pending_write.add_done_callback(self._finish_request) + future_add_done_callback(self._pending_write, self._finish_request) def _on_write_complete(self, future): exc = future.exception() @@ -477,7 +492,7 @@ class HTTP1Connection(httputil.HTTPConnection): if self._write_future is not None: future = self._write_future self._write_future = None - future.set_result(None) + future_set_result_unless_cancelled(future, None) def _can_keep_alive(self, start_line, headers): if self.params.no_keep_alive: @@ -504,7 +519,7 @@ class HTTP1Connection(httputil.HTTPConnection): # default state for the next request. self.stream.set_nodelay(False) if not self._finish_future.done(): - self._finish_future.set_result(None) + future_set_result_unless_cancelled(self._finish_future, None) def _parse_headers(self, data): # The lstrip removes newlines that some implementations sometimes @@ -515,12 +530,7 @@ class HTTP1Connection(httputil.HTTPConnection): # RFC 7230 section allows for both CRLF and bare LF. eol = data.find("\n") start_line = data[:eol].rstrip("\r") - try: - headers = httputil.HTTPHeaders.parse(data[eol:]) - except ValueError: - # probably form split() if there was no ':' in the line - raise httputil.HTTPInputError("Malformed HTTP headers: %r" % - data[eol:100]) + headers = httputil.HTTPHeaders.parse(data[eol:]) return start_line, headers def _read_body(self, code, headers, delegate): @@ -592,6 +602,9 @@ class HTTP1Connection(httputil.HTTPConnection): chunk_len = yield self.stream.read_until(b"\r\n", max_bytes=64) chunk_len = int(chunk_len.strip(), 16) if chunk_len == 0: + crlf = yield self.stream.read_bytes(2) + if crlf != b'\r\n': + raise httputil.HTTPInputError("improperly terminated chunked request") return total_size += chunk_len if total_size > self._max_body_size: diff --git a/server/www/packages/packages-common/tornado/httpclient.py b/server/www/packages/packages-common/tornado/httpclient.py index 8436ece..5ed2ee6 100644 --- a/server/www/packages/packages-common/tornado/httpclient.py +++ b/server/www/packages/packages-common/tornado/httpclient.py @@ -42,11 +42,12 @@ from __future__ import absolute_import, division, print_function import functools import time +import warnings import weakref -from tornado.concurrent import TracebackFuture +from tornado.concurrent import Future, future_set_result_unless_cancelled from tornado.escape import utf8, native_str -from tornado import httputil, stack_context +from tornado import gen, httputil, stack_context from tornado.ioloop import IOLoop from tornado.util import Configurable @@ -54,8 +55,10 @@ from tornado.util import Configurable class HTTPClient(object): """A blocking HTTP client. - This interface is provided for convenience and testing; most applications - that are running an IOLoop will want to use `AsyncHTTPClient` instead. + This interface is provided to make it easier to share code between + synchronous and asynchronous applications. Applications that are + running an `.IOLoop` must use `AsyncHTTPClient` instead. + Typical usage looks like this:: http_client = httpclient.HTTPClient() @@ -70,12 +73,26 @@ class HTTPClient(object): # Other errors are possible, such as IOError. print("Error: " + str(e)) http_client.close() + + .. versionchanged:: 5.0 + + Due to limitations in `asyncio`, it is no longer possible to + use the synchronous ``HTTPClient`` while an `.IOLoop` is running. + Use `AsyncHTTPClient` instead. + """ def __init__(self, async_client_class=None, **kwargs): + # Initialize self._closed at the beginning of the constructor + # so that an exception raised here doesn't lead to confusing + # failures in __del__. + self._closed = True self._io_loop = IOLoop(make_current=False) if async_client_class is None: async_client_class = AsyncHTTPClient - self._async_client = async_client_class(self._io_loop, **kwargs) + # Create the client while our IOLoop is "current", without + # clobbering the thread's real current IOLoop (if any). + self._async_client = self._io_loop.run_sync( + gen.coroutine(lambda: async_client_class(**kwargs))) self._closed = False def __del__(self): @@ -108,24 +125,24 @@ class AsyncHTTPClient(Configurable): Example usage:: - def handle_response(response): - if response.error: - print("Error: %s" % response.error) + async def f(): + http_client = AsyncHTTPClient() + try: + response = await http_client.fetch("http://www.google.com") + except Exception as e: + print("Error: %s" % e) else: print(response.body) - http_client = AsyncHTTPClient() - http_client.fetch("http://www.google.com/", handle_response) - The constructor for this class is magic in several respects: It actually creates an instance of an implementation-specific subclass, and instances are reused as a kind of pseudo-singleton - (one per `.IOLoop`). The keyword argument ``force_instance=True`` - can be used to suppress this singleton behavior. Unless - ``force_instance=True`` is used, no arguments other than - ``io_loop`` should be passed to the `AsyncHTTPClient` constructor. - The implementation subclass as well as arguments to its - constructor can be set with the static method `configure()` + (one per `.IOLoop`). The keyword argument ``force_instance=True`` + can be used to suppress this singleton behavior. Unless + ``force_instance=True`` is used, no arguments should be passed to + the `AsyncHTTPClient` constructor. The implementation subclass as + well as arguments to its constructor can be set with the static + method `configure()` All `AsyncHTTPClient` implementations support a ``defaults`` keyword argument, which can be used to set default values for @@ -137,8 +154,9 @@ class AsyncHTTPClient(Configurable): client = AsyncHTTPClient(force_instance=True, defaults=dict(user_agent="MyUserAgent")) - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + """ @classmethod def configurable_base(cls): @@ -156,16 +174,15 @@ class AsyncHTTPClient(Configurable): setattr(cls, attr_name, weakref.WeakKeyDictionary()) return getattr(cls, attr_name) - def __new__(cls, io_loop=None, force_instance=False, **kwargs): - io_loop = io_loop or IOLoop.current() + def __new__(cls, force_instance=False, **kwargs): + io_loop = IOLoop.current() if force_instance: instance_cache = None else: instance_cache = cls._async_clients() if instance_cache is not None and io_loop in instance_cache: return instance_cache[io_loop] - instance = super(AsyncHTTPClient, cls).__new__(cls, io_loop=io_loop, - **kwargs) + instance = super(AsyncHTTPClient, cls).__new__(cls, **kwargs) # Make sure the instance knows which cache to remove itself from. # It can't simply call _async_clients() because we may be in # __new__(AsyncHTTPClient) but instance.__class__ may be @@ -175,8 +192,8 @@ class AsyncHTTPClient(Configurable): instance_cache[instance.io_loop] = instance return instance - def initialize(self, io_loop, defaults=None): - self.io_loop = io_loop + def initialize(self, defaults=None): + self.io_loop = IOLoop.current() self.defaults = dict(HTTPRequest._DEFAULTS) if defaults is not None: self.defaults.update(defaults) @@ -222,6 +239,18 @@ class AsyncHTTPClient(Configurable): In the callback interface, `HTTPError` is not automatically raised. Instead, you must check the response's ``error`` attribute or call its `~HTTPResponse.rethrow` method. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in 6.0. Use the returned `.Future` instead. + + The ``raise_error=False`` argument currently suppresses + *all* errors, encapsulating them in `HTTPResponse` objects + with a 599 response code. This will change in Tornado 6.0: + ``raise_error=False`` will only affect the `HTTPError` + raised when a non-200 response code is used. + """ if self._closed: raise RuntimeError("fetch() called on closed AsyncHTTPClient") @@ -235,8 +264,10 @@ class AsyncHTTPClient(Configurable): # where normal dicts get converted to HTTPHeaders objects. request.headers = httputil.HTTPHeaders(request.headers) request = _RequestProxy(request, self.defaults) - future = TracebackFuture() + future = Future() if callback is not None: + warnings.warn("callback arguments are deprecated, use the returned Future instead", + DeprecationWarning) callback = stack_context.wrap(callback) def handle_future(future): @@ -254,9 +285,14 @@ class AsyncHTTPClient(Configurable): def handle_response(response): if raise_error and response.error: + if isinstance(response.error, HTTPError): + response.error.response = response future.set_exception(response.error) else: - future.set_result(response) + if response.error and not response._error_is_response_code: + warnings.warn("raise_error=False will allow '%s' to be raised in the future" % + response.error, DeprecationWarning) + future_set_result_unless_cancelled(future, response) self.fetch_impl(request, handle_response) return future @@ -318,8 +354,8 @@ class HTTPRequest(object): ssl_options=None): r"""All parameters except ``url`` are optional. - :arg string url: URL to fetch - :arg string method: HTTP method, e.g. "GET" or "POST" + :arg str url: URL to fetch + :arg str method: HTTP method, e.g. "GET" or "POST" :arg headers: Additional HTTP headers to pass on the request :type headers: `~tornado.httputil.HTTPHeaders` or `dict` :arg body: HTTP request body as a string (byte or unicode; if unicode @@ -335,9 +371,9 @@ class HTTPRequest(object): to pass a ``Content-Length`` in the headers as otherwise chunked encoding will be used, and many servers do not support chunked encoding on requests. New in Tornado 4.0 - :arg string auth_username: Username for HTTP authentication - :arg string auth_password: Password for HTTP authentication - :arg string auth_mode: Authentication mode; default is "basic". + :arg str auth_username: Username for HTTP authentication + :arg str auth_password: Password for HTTP authentication + :arg str auth_mode: Authentication mode; default is "basic". Allowed values are implementation-defined; ``curl_httpclient`` supports "basic" and "digest"; ``simple_httpclient`` only supports "basic" @@ -350,19 +386,19 @@ class HTTPRequest(object): :arg bool follow_redirects: Should redirects be followed automatically or return the 3xx response? Default True. :arg int max_redirects: Limit for ``follow_redirects``, default 5. - :arg string user_agent: String to send as ``User-Agent`` header + :arg str user_agent: String to send as ``User-Agent`` header :arg bool decompress_response: Request a compressed response from the server and decompress it after downloading. Default is True. New in Tornado 4.0. :arg bool use_gzip: Deprecated alias for ``decompress_response`` since Tornado 4.0. - :arg string network_interface: Network interface to use for request. + :arg str network_interface: Network interface to use for request. ``curl_httpclient`` only; see note below. - :arg callable streaming_callback: If set, ``streaming_callback`` will + :arg collections.abc.Callable streaming_callback: If set, ``streaming_callback`` will be run with each chunk of data as it is received, and ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in the final response. - :arg callable header_callback: If set, ``header_callback`` will + :arg collections.abc.Callable header_callback: If set, ``header_callback`` will be run with each header line as it is received (including the first line, e.g. ``HTTP/1.0 200 OK\r\n``, and a final line containing only ``\r\n``. All lines include the trailing newline @@ -370,28 +406,28 @@ class HTTPRequest(object): response. This is most useful in conjunction with ``streaming_callback``, because it's the only way to get access to header data while the request is in progress. - :arg callable prepare_curl_callback: If set, will be called with + :arg collections.abc.Callable prepare_curl_callback: If set, will be called with a ``pycurl.Curl`` object to allow the application to make additional ``setopt`` calls. - :arg string proxy_host: HTTP proxy hostname. To use proxies, + :arg str proxy_host: HTTP proxy hostname. To use proxies, ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username``, ``proxy_pass`` and ``proxy_auth_mode`` are optional. Proxies are currently only supported with ``curl_httpclient``. :arg int proxy_port: HTTP proxy port - :arg string proxy_username: HTTP proxy username - :arg string proxy_password: HTTP proxy password - :arg string proxy_auth_mode: HTTP proxy Authentication mode; + :arg str proxy_username: HTTP proxy username + :arg str proxy_password: HTTP proxy password + :arg str proxy_auth_mode: HTTP proxy Authentication mode; default is "basic". supports "basic" and "digest" :arg bool allow_nonstandard_methods: Allow unknown values for ``method`` argument? Default is False. :arg bool validate_cert: For HTTPS requests, validate the server's certificate? Default is True. - :arg string ca_certs: filename of CA certificates in PEM format, + :arg str ca_certs: filename of CA certificates in PEM format, or None to use defaults. See note below when used with ``curl_httpclient``. - :arg string client_key: Filename for client SSL key, if any. See + :arg str client_key: Filename for client SSL key, if any. See note below when used with ``curl_httpclient``. - :arg string client_cert: Filename for client SSL certificate, if any. + :arg str client_cert: Filename for client SSL certificate, if any. See note below when used with ``curl_httpclient``. :arg ssl.SSLContext ssl_options: `ssl.SSLContext` object for use in ``simple_httpclient`` (unsupported by ``curl_httpclient``). @@ -542,17 +578,35 @@ class HTTPResponse(object): * error: Exception object, if any - * request_time: seconds from request start to finish + * request_time: seconds from request start to finish. Includes all network + operations from DNS resolution to receiving the last byte of data. + Does not include time spent in the queue (due to the ``max_clients`` option). + If redirects were followed, only includes the final request. + + * start_time: Time at which the HTTP operation started, based on `time.time` + (not the monotonic clock used by `.IOLoop.time`). May be ``None`` if the request + timed out while in the queue. * time_info: dictionary of diagnostic timing information from the request. Available data are subject to change, but currently uses timings available from http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html, plus ``queue``, which is the delay (if any) introduced by waiting for a slot under `AsyncHTTPClient`'s ``max_clients`` setting. + + .. versionadded:: 5.1 + + Added the ``start_time`` attribute. + + .. versionchanged:: 5.1 + + The ``request_time`` attribute previously included time spent in the queue + for ``simple_httpclient``, but not in ``curl_httpclient``. Now queueing time + is excluded in both implementations. ``request_time`` is now more accurate for + ``curl_httpclient`` because it uses a monotonic clock when available. """ def __init__(self, request, code, headers=None, buffer=None, effective_url=None, error=None, request_time=None, - time_info=None, reason=None): + time_info=None, reason=None, start_time=None): if isinstance(request, _RequestProxy): self.request = request.request else: @@ -569,14 +623,17 @@ class HTTPResponse(object): self.effective_url = request.url else: self.effective_url = effective_url + self._error_is_response_code = False if error is None: if self.code < 200 or self.code >= 300: + self._error_is_response_code = True self.error = HTTPError(self.code, message=self.reason, response=self) else: self.error = None else: self.error = error + self.start_time = start_time self.request_time = request_time self.time_info = time_info or {} @@ -599,7 +656,7 @@ class HTTPResponse(object): return "%s(%s)" % (self.__class__.__name__, args) -class HTTPError(Exception): +class HTTPClientError(Exception): """Exception thrown for an unsuccessful HTTP request. Attributes: @@ -612,12 +669,18 @@ class HTTPError(Exception): Note that if ``follow_redirects`` is False, redirects become HTTPErrors, and you can look at ``error.response.headers['Location']`` to see the destination of the redirect. + + .. versionchanged:: 5.1 + + Renamed from ``HTTPError`` to ``HTTPClientError`` to avoid collisions with + `tornado.web.HTTPError`. The name ``tornado.httpclient.HTTPError`` remains + as an alias. """ def __init__(self, code, message=None, response=None): self.code = code self.message = message or httputil.responses.get(code, "Unknown") self.response = response - super(HTTPError, self).__init__(code, message, response) + super(HTTPClientError, self).__init__(code, message, response) def __str__(self): return "HTTP %d: %s" % (self.code, self.message) @@ -629,6 +692,9 @@ class HTTPError(Exception): __repr__ = __str__ +HTTPError = HTTPClientError + + class _RequestProxy(object): """Combines an object with a dictionary of defaults. @@ -654,6 +720,8 @@ def main(): define("print_body", type=bool, default=True) define("follow_redirects", type=bool, default=True) define("validate_cert", type=bool, default=True) + define("proxy_host", type=str) + define("proxy_port", type=int) args = parse_command_line() client = HTTPClient() for arg in args: @@ -661,6 +729,8 @@ def main(): response = client.fetch(arg, follow_redirects=options.follow_redirects, validate_cert=options.validate_cert, + proxy_host=options.proxy_host, + proxy_port=options.proxy_port, ) except HTTPError as e: if e.response is not None: diff --git a/server/www/packages/packages-common/tornado/httpserver.py b/server/www/packages/packages-common/tornado/httpserver.py index d757be1..3498d71 100644 --- a/server/www/packages/packages-common/tornado/httpserver.py +++ b/server/www/packages/packages-common/tornado/httpserver.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -77,7 +76,7 @@ class HTTPServer(TCPServer, Configurable, ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_ctx.load_cert_chain(os.path.join(data_dir, "mydomain.crt"), os.path.join(data_dir, "mydomain.key")) - HTTPServer(applicaton, ssl_options=ssl_ctx) + HTTPServer(application, ssl_options=ssl_ctx) `HTTPServer` initialization follows one of three patterns (the initialization methods are defined on `tornado.tcpserver.TCPServer`): @@ -134,6 +133,9 @@ class HTTPServer(TCPServer, Configurable, .. versionchanged:: 4.5 Added the ``trusted_downstream`` argument. + + .. versionchanged:: 5.0 + The ``io_loop`` argument has been removed. """ def __init__(self, *args, **kwargs): # Ignore args to __init__; real initialization belongs in @@ -143,7 +145,7 @@ class HTTPServer(TCPServer, Configurable, # completely) pass - def initialize(self, request_callback, no_keep_alive=False, io_loop=None, + def initialize(self, request_callback, no_keep_alive=False, xheaders=False, ssl_options=None, protocol=None, decompress_request=False, chunk_size=None, max_header_size=None, @@ -151,7 +153,6 @@ class HTTPServer(TCPServer, Configurable, max_body_size=None, max_buffer_size=None, trusted_downstream=None): self.request_callback = request_callback - self.no_keep_alive = no_keep_alive self.xheaders = xheaders self.protocol = protocol self.conn_params = HTTP1ConnectionParameters( @@ -162,7 +163,7 @@ class HTTPServer(TCPServer, Configurable, max_body_size=max_body_size, body_timeout=body_timeout, no_keep_alive=no_keep_alive) - TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options, + TCPServer.__init__(self, ssl_options=ssl_options, max_buffer_size=max_buffer_size, read_chunk_size=chunk_size) self._connections = set() @@ -285,6 +286,10 @@ class _HTTPRequestContext(object): proto_header = headers.get( "X-Scheme", headers.get("X-Forwarded-Proto", self.protocol)) + if proto_header: + # use only the last proto entry if there is more than one + # TODO: support trusting mutiple layers of proxied protocol + proto_header = proto_header.split(',')[-1].strip() if proto_header in ("http", "https"): self.protocol = proto_header diff --git a/server/www/packages/packages-common/tornado/httputil.py b/server/www/packages/packages-common/tornado/httputil.py index 818ea91..3961446 100644 --- a/server/www/packages/packages-common/tornado/httputil.py +++ b/server/www/packages/packages-common/tornado/httputil.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -30,10 +29,12 @@ import email.utils import numbers import re import time +import unicodedata +import warnings from tornado.escape import native_str, parse_qs_bytes, utf8 from tornado.log import gen_log -from tornado.util import ObjectDict, PY3 +from tornado.util import ObjectDict, PY3, unicode_type if PY3: import http.cookies as Cookie @@ -61,7 +62,7 @@ except ImportError: SSLError = _SSLError # type: ignore try: - import typing + import typing # noqa: F401 except ImportError: pass @@ -184,11 +185,16 @@ class HTTPHeaders(collections.MutableMapping): """ if line[0].isspace(): # continuation of a multi-line header + if self._last_key is None: + raise HTTPInputError("first header line cannot start with whitespace") new_part = ' ' + line.lstrip() self._as_list[self._last_key][-1] += new_part self._dict[self._last_key] += new_part else: - name, value = line.split(":", 1) + try: + name, value = line.split(":", 1) + except ValueError: + raise HTTPInputError("no colon in header line") self.add(name, value.strip()) @classmethod @@ -198,6 +204,12 @@ class HTTPHeaders(collections.MutableMapping): >>> h = HTTPHeaders.parse("Content-Type: text/html\\r\\nContent-Length: 42\\r\\n") >>> sorted(h.items()) [('Content-Length', '42'), ('Content-Type', 'text/html')] + + .. versionchanged:: 5.1 + + Raises `HTTPInputError` on malformed headers instead of a + mix of `KeyError`, and `ValueError`. + """ h = cls() for line in _CRLF_RE.split(headers): @@ -370,10 +382,15 @@ class HTTPServerRequest(object): """Returns True if this request supports HTTP/1.1 semantics. .. deprecated:: 4.0 - Applications are less likely to need this information with the - introduction of `.HTTPConnection`. If you still need it, access - the ``version`` attribute directly. + + Applications are less likely to need this information with + the introduction of `.HTTPConnection`. If you still need + it, access the ``version`` attribute directly. This method + will be removed in Tornado 6.0. + """ + warnings.warn("supports_http_1_1() is deprecated, use request.version instead", + DeprecationWarning) return self.version == "HTTP/1.1" @property @@ -402,8 +419,10 @@ class HTTPServerRequest(object): .. deprecated:: 4.0 Use ``request.connection`` and the `.HTTPConnection` methods - to write the response. + to write the response. This method will be removed in Tornado 6.0. """ + warnings.warn("req.write deprecated, use req.connection.write and write_headers instead", + DeprecationWarning) assert isinstance(chunk, bytes) assert self.version.startswith("HTTP/1."), \ "deprecated interface only supported in HTTP/1.x" @@ -414,8 +433,10 @@ class HTTPServerRequest(object): .. deprecated:: 4.0 Use ``request.connection`` and the `.HTTPConnection` methods - to write the response. + to write the response. This method will be removed in Tornado 6.0. """ + warnings.warn("req.finish deprecated, use req.connection.finish instead", + DeprecationWarning) self.connection.finish() self._finish_time = time.time() @@ -467,8 +488,7 @@ class HTTPServerRequest(object): def __repr__(self): attrs = ("protocol", "host", "method", "uri", "version", "remote_ip") args = ", ".join(["%s=%r" % (n, getattr(self, n)) for n in attrs]) - return "%s(%s, headers=%s)" % ( - self.__class__.__name__, args, dict(self.headers)) + return "%s(%s)" % (self.__class__.__name__, args) class HTTPInputError(Exception): @@ -572,6 +592,11 @@ class HTTPConnection(object): The ``version`` field of ``start_line`` is ignored. Returns a `.Future` if no callback is given. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. """ raise NotImplementedError() @@ -580,6 +605,11 @@ class HTTPConnection(object): The callback will be run when the write is complete. If no callback is given, returns a Future. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. """ raise NotImplementedError() @@ -753,6 +783,11 @@ def parse_multipart_form_data(boundary, data, arguments, files): The ``boundary`` and ``data`` parameters are both byte strings. The dictionaries given in the arguments and files parameters will be updated with the contents of the body. + + .. versionchanged:: 5.1 + + Now recognizes non-ASCII filenames in RFC 2231/5987 + (``filename*=``) format. """ # The standard allows for the boundary to be quoted in the header, # although it's rare (it happens at least for google app engine @@ -829,6 +864,8 @@ def parse_request_start_line(line): try: method, path, version = line.split(" ") except ValueError: + # https://tools.ietf.org/html/rfc7230#section-3.1.1 + # invalid request-line SHOULD respond with a 400 (Bad Request) raise HTTPInputError("Malformed HTTP request line") if not re.match(r"^HTTP/1\.[0-9]$", version): raise HTTPInputError( @@ -859,7 +896,8 @@ def parse_response_start_line(line): # The original 2.7 version of this code did not correctly support some # combinations of semicolons and double quotes. # It has also been modified to support valueless parameters as seen in -# websocket extension negotiations. +# websocket extension negotiations, and to support non-ascii values in +# RFC 2231/5987 format. def _parseparam(s): @@ -876,25 +914,37 @@ def _parseparam(s): def _parse_header(line): - """Parse a Content-type like header. + r"""Parse a Content-type like header. Return the main content-type and a dictionary of options. + >>> d = "form-data; foo=\"b\\\\a\\\"r\"; file*=utf-8''T%C3%A4st" + >>> ct, d = _parse_header(d) + >>> ct + 'form-data' + >>> d['file'] == r'T\u00e4st'.encode('ascii').decode('unicode_escape') + True + >>> d['foo'] + 'b\\a"r' """ parts = _parseparam(';' + line) key = next(parts) - pdict = {} + # decode_params treats first argument special, but we already stripped key + params = [('Dummy', 'value')] for p in parts: i = p.find('=') if i >= 0: name = p[:i].strip().lower() value = p[i + 1:].strip() - if len(value) >= 2 and value[0] == value[-1] == '"': - value = value[1:-1] - value = value.replace('\\\\', '\\').replace('\\"', '"') - pdict[name] = value - else: - pdict[p] = None + params.append((name, native_str(value))) + params = email.utils.decode_params(params) + params.pop(0) # get rid of the dummy again + pdict = {} + for name, value in params: + value = email.utils.collapse_rfc2231_value(value) + if len(value) >= 2 and value[0] == '"' and value[-1] == '"': + value = value[1:-1] + pdict[name] = value return key, pdict @@ -918,6 +968,20 @@ def _encode_header(key, pdict): return '; '.join(out) +def encode_username_password(username, password): + """Encodes a username/password pair in the format used by HTTP auth. + + The return value is a byte string in the form ``username:password``. + + .. versionadded:: 5.1 + """ + if isinstance(username, unicode_type): + username = unicodedata.normalize('NFC', username) + if isinstance(password, unicode_type): + password = unicodedata.normalize('NFC', password) + return utf8(username) + b":" + utf8(password) + + def doctests(): import doctest return doctest.DocTestSuite() @@ -940,6 +1004,16 @@ def split_host_and_port(netloc): return (host, port) +def qs_to_qsl(qs): + """Generator converting a result of ``parse_qs`` back to name-value pairs. + + .. versionadded:: 5.0 + """ + for k, vs in qs.items(): + for v in vs: + yield (k, v) + + _OctalPatt = re.compile(r"\\[0-3][0-7][0-7]") _QuotePatt = re.compile(r"[\\].") _nulljoin = ''.join diff --git a/server/www/packages/packages-common/tornado/ioloop.py b/server/www/packages/packages-common/tornado/ioloop.py index ad35787..f7ee6dd 100644 --- a/server/www/packages/packages-common/tornado/ioloop.py +++ b/server/www/packages/packages-common/tornado/ioloop.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -16,14 +15,19 @@ """An I/O event loop for non-blocking sockets. -Typical applications will use a single `IOLoop` object, in the -`IOLoop.instance` singleton. The `IOLoop.start` method should usually -be called at the end of the ``main()`` function. Atypical applications may -use more than one `IOLoop`, such as one `IOLoop` per thread, or per `unittest` -case. +On Python 3, `.IOLoop` is a wrapper around the `asyncio` event loop. + +Typical applications will use a single `IOLoop` object, accessed via +`IOLoop.current` class method. The `IOLoop.start` method (or +equivalently, `asyncio.AbstractEventLoop.run_forever`) should usually +be called at the end of the ``main()`` function. Atypical applications +may use more than one `IOLoop`, such as one `IOLoop` per thread, or +per `unittest` case. + +In addition to I/O events, the `IOLoop` can also schedule time-based +events. `IOLoop.add_timeout` is a non-blocking alternative to +`time.sleep`. -In addition to I/O events, the `IOLoop` can also schedule time-based events. -`IOLoop.add_timeout` is a non-blocking alternative to `time.sleep`. """ from __future__ import absolute_import, division, print_function @@ -43,40 +47,50 @@ import threading import time import traceback import math +import random -from tornado.concurrent import TracebackFuture, is_future +from tornado.concurrent import Future, is_future, chain_future, future_set_exc_info, future_add_done_callback # noqa: E501 from tornado.log import app_log, gen_log from tornado.platform.auto import set_close_exec, Waker from tornado import stack_context -from tornado.util import PY3, Configurable, errno_from_exception, timedelta_to_seconds +from tornado.util import ( + PY3, Configurable, errno_from_exception, timedelta_to_seconds, + TimeoutError, unicode_type, import_object, +) try: import signal except ImportError: signal = None +try: + from concurrent.futures import ThreadPoolExecutor +except ImportError: + ThreadPoolExecutor = None if PY3: import _thread as thread else: import thread +try: + import asyncio +except ImportError: + asyncio = None + _POLL_TIMEOUT = 3600.0 -class TimeoutError(Exception): - pass - - class IOLoop(Configurable): """A level-triggered I/O loop. - We use ``epoll`` (Linux) or ``kqueue`` (BSD and Mac OS X) if they - are available, or else we fall back on select(). If you are - implementing a system that needs to handle thousands of - simultaneous connections, you should use a system that supports - either ``epoll`` or ``kqueue``. + On Python 3, `IOLoop` is a wrapper around the `asyncio` event + loop. On Python 2, it uses ``epoll`` (Linux) or ``kqueue`` (BSD + and Mac OS X) if they are available, or else we fall back on + select(). If you are implementing a system that needs to handle + thousands of simultaneous connections, you should use a system + that supports either ``epoll`` or ``kqueue``. Example usage for a simple TCP server: @@ -84,9 +98,17 @@ class IOLoop(Configurable): import errno import functools - import tornado.ioloop import socket + import tornado.ioloop + from tornado import gen + from tornado.iostream import IOStream + + async def handle_connection(connection, address): + stream = IOStream(connection) + message = await stream.read_until_close() + print("message from client:", message.decode().strip()) + def connection_ready(sock, fd, events): while True: try: @@ -102,7 +124,7 @@ class IOLoop(Configurable): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setblocking(0) - sock.bind(("", port)) + sock.bind(("", 8888)) sock.listen(128) io_loop = tornado.ioloop.IOLoop.current() @@ -121,9 +143,26 @@ class IOLoop(Configurable): current instance. If ``make_current=False``, the new `IOLoop` will not try to become current. + In general, an `IOLoop` cannot survive a fork or be shared across + processes in any way. When multiple processes are being used, each + process should create its own `IOLoop`, which also implies that + any objects which depend on the `IOLoop` (such as + `.AsyncHTTPClient`) must also be created in the child processes. + As a guideline, anything that starts processes (including the + `tornado.process` and `multiprocessing` modules) should do so as + early as possible, ideally the first thing the application does + after loading its configuration in ``main()``. + .. versionchanged:: 4.2 Added the ``make_current`` keyword argument to the `IOLoop` constructor. + + .. versionchanged:: 5.0 + + Uses the `asyncio` event loop by default. The + ``IOLoop.configure`` method cannot be used on Python 3 except + to redundantly specify the `asyncio` event loop. + """ # Constants from the epoll module _EPOLLIN = 0x001 @@ -141,54 +180,75 @@ class IOLoop(Configurable): WRITE = _EPOLLOUT ERROR = _EPOLLERR | _EPOLLHUP - # Global lock for creating global IOLoop instance - _instance_lock = threading.Lock() - + # In Python 2, _current.instance points to the current IOLoop. _current = threading.local() + # In Python 3, _ioloop_for_asyncio maps from asyncio loops to IOLoops. + _ioloop_for_asyncio = dict() + + @classmethod + def configure(cls, impl, **kwargs): + if asyncio is not None: + from tornado.platform.asyncio import BaseAsyncIOLoop + + if isinstance(impl, (str, unicode_type)): + impl = import_object(impl) + if not issubclass(impl, BaseAsyncIOLoop): + raise RuntimeError( + "only AsyncIOLoop is allowed when asyncio is available") + super(IOLoop, cls).configure(impl, **kwargs) + @staticmethod def instance(): - """Returns a global `IOLoop` instance. + """Deprecated alias for `IOLoop.current()`. - Most applications have a single, global `IOLoop` running on the - main thread. Use this method to get this instance from - another thread. In most other cases, it is better to use `current()` - to get the current thread's `IOLoop`. + .. versionchanged:: 5.0 + + Previously, this method returned a global singleton + `IOLoop`, in contrast with the per-thread `IOLoop` returned + by `current()`. In nearly all cases the two were the same + (when they differed, it was generally used from non-Tornado + threads to communicate back to the main thread's `IOLoop`). + This distinction is not present in `asyncio`, so in order + to facilitate integration with that package `instance()` + was changed to be an alias to `current()`. Applications + using the cross-thread communications aspect of + `instance()` should instead set their own global variable + to point to the `IOLoop` they want to use. + + .. deprecated:: 5.0 """ - if not hasattr(IOLoop, "_instance"): - with IOLoop._instance_lock: - if not hasattr(IOLoop, "_instance"): - # New instance after double check - IOLoop._instance = IOLoop() - return IOLoop._instance - - @staticmethod - def initialized(): - """Returns true if the singleton instance has been created.""" - return hasattr(IOLoop, "_instance") + return IOLoop.current() def install(self): - """Installs this `IOLoop` object as the singleton instance. + """Deprecated alias for `make_current()`. - This is normally not necessary as `instance()` will create - an `IOLoop` on demand, but you may want to call `install` to use - a custom subclass of `IOLoop`. + .. versionchanged:: 5.0 - When using an `IOLoop` subclass, `install` must be called prior - to creating any objects that implicitly create their own - `IOLoop` (e.g., :class:`tornado.httpclient.AsyncHTTPClient`). + Previously, this method would set this `IOLoop` as the + global singleton used by `IOLoop.instance()`. Now that + `instance()` is an alias for `current()`, `install()` + is an alias for `make_current()`. + + .. deprecated:: 5.0 """ - assert not IOLoop.initialized() - IOLoop._instance = self + self.make_current() @staticmethod def clear_instance(): - """Clear the global `IOLoop` instance. + """Deprecated alias for `clear_current()`. + + .. versionchanged:: 5.0 + + Previously, this method would clear the `IOLoop` used as + the global singleton by `IOLoop.instance()`. Now that + `instance()` is an alias for `current()`, + `clear_instance()` is an alias for `clear_current()`. + + .. deprecated:: 5.0 - .. versionadded:: 4.0 """ - if hasattr(IOLoop, "_instance"): - del IOLoop._instance + IOLoop.clear_current() @staticmethod def current(instance=True): @@ -196,22 +256,42 @@ class IOLoop(Configurable): If an `IOLoop` is currently running or has been marked as current by `make_current`, returns that instance. If there is - no current `IOLoop`, returns `IOLoop.instance()` (i.e. the - main thread's `IOLoop`, creating one if necessary) if ``instance`` - is true. - - In general you should use `IOLoop.current` as the default when - constructing an asynchronous object, and use `IOLoop.instance` - when you mean to communicate to the main thread from a different - one. + no current `IOLoop` and ``instance`` is true, creates one. .. versionchanged:: 4.1 Added ``instance`` argument to control the fallback to `IOLoop.instance()`. + .. versionchanged:: 5.0 + On Python 3, control of the current `IOLoop` is delegated + to `asyncio`, with this and other methods as pass-through accessors. + The ``instance`` argument now controls whether an `IOLoop` + is created automatically when there is none, instead of + whether we fall back to `IOLoop.instance()` (which is now + an alias for this method). ``instance=False`` is deprecated, + since even if we do not create an `IOLoop`, this method + may initialize the asyncio loop. """ - current = getattr(IOLoop._current, "instance", None) - if current is None and instance: - return IOLoop.instance() + if asyncio is None: + current = getattr(IOLoop._current, "instance", None) + if current is None and instance: + current = IOLoop() + if IOLoop._current.instance is not current: + raise RuntimeError("new IOLoop did not become current") + else: + try: + loop = asyncio.get_event_loop() + except (RuntimeError, AssertionError): + if not instance: + return None + raise + try: + return IOLoop._ioloop_for_asyncio[loop] + except KeyError: + if instance: + from tornado.platform.asyncio import AsyncIOMainLoop + current = AsyncIOMainLoop(make_current=True) + else: + current = None return current def make_current(self): @@ -226,12 +306,38 @@ class IOLoop(Configurable): .. versionchanged:: 4.1 An `IOLoop` created while there is no current `IOLoop` will automatically become current. + + .. versionchanged:: 5.0 + This method also sets the current `asyncio` event loop. """ + # The asyncio event loops override this method. + assert asyncio is None + old = getattr(IOLoop._current, "instance", None) + if old is not None: + old.clear_current() IOLoop._current.instance = self @staticmethod def clear_current(): - IOLoop._current.instance = None + """Clears the `IOLoop` for the current thread. + + Intended primarily for use by test frameworks in between tests. + + .. versionchanged:: 5.0 + This method also clears the current `asyncio` event loop. + """ + old = IOLoop.current(instance=False) + if old is not None: + old._clear_current_hook() + if asyncio is None: + IOLoop._current.instance = None + + def _clear_current_hook(self): + """Instance method called when an IOLoop ceases to be current. + + May be overridden by subclasses as a counterpart to make_current. + """ + pass @classmethod def configurable_base(cls): @@ -239,22 +345,19 @@ class IOLoop(Configurable): @classmethod def configurable_default(cls): - if hasattr(select, "epoll"): - from tornado.platform.epoll import EPollIOLoop - return EPollIOLoop - if hasattr(select, "kqueue"): - # Python 2.6+ on BSD or Mac - from tornado.platform.kqueue import KQueueIOLoop - return KQueueIOLoop - from tornado.platform.select import SelectIOLoop - return SelectIOLoop + if asyncio is not None: + from tornado.platform.asyncio import AsyncIOLoop + return AsyncIOLoop + return PollIOLoop def initialize(self, make_current=None): if make_current is None: if IOLoop.current(instance=False) is None: self.make_current() elif make_current: - if IOLoop.current(instance=False) is not None: + current = IOLoop.current(instance=False) + # AsyncIO loops can already be current by this point. + if current is not None and current is not self: raise RuntimeError("current IOLoop already exists") self.make_current() @@ -333,6 +436,12 @@ class IOLoop(Configurable): documentation for the `signal` module for more information. If ``action`` is None, the process will be killed if it is blocked for too long. + + .. deprecated:: 5.0 + + Not implemented on the `asyncio` event loop. Use the environment + variable ``PYTHONASYNCIODEBUG=1`` instead. This method will be + removed in Tornado 6.0. """ raise NotImplementedError() @@ -342,6 +451,12 @@ class IOLoop(Configurable): Equivalent to ``set_blocking_signal_threshold(seconds, self.log_stack)`` + + .. deprecated:: 5.0 + + Not implemented on the `asyncio` event loop. Use the environment + variable ``PYTHONASYNCIODEBUG=1`` instead. This method will be + removed in Tornado 6.0. """ self.set_blocking_signal_threshold(seconds, self.log_stack) @@ -349,6 +464,10 @@ class IOLoop(Configurable): """Signal handler to log the stack trace of the current thread. For use with `set_blocking_signal_threshold`. + + .. deprecated:: 5.1 + + This method will be removed in Tornado 6.0. """ gen_log.warning('IOLoop blocked for %f seconds in\n%s', self._blocking_signal_threshold, @@ -384,17 +503,6 @@ class IOLoop(Configurable): If the event loop is not currently running, the next call to `start()` will return immediately. - To use asynchronous methods from otherwise-synchronous code (such as - unit tests), you can start and stop the event loop like this:: - - ioloop = IOLoop() - async_method(ioloop=ioloop, callback=ioloop.stop) - ioloop.start() - - ``ioloop.start()`` will return after ``async_method`` has run - its callback, whether that callback was invoked before or - after ``ioloop.start``. - Note that even after `stop` has been called, the `IOLoop` is not completely stopped until `IOLoop.start` has also returned. Some work that was scheduled before the call to `stop` may still @@ -405,29 +513,32 @@ class IOLoop(Configurable): def run_sync(self, func, timeout=None): """Starts the `IOLoop`, runs the given function, and stops the loop. - The function must return either a yieldable object or - ``None``. If the function returns a yieldable object, the - `IOLoop` will run until the yieldable is resolved (and - `run_sync()` will return the yieldable's result). If it raises + The function must return either an awaitable object or + ``None``. If the function returns an awaitable object, the + `IOLoop` will run until the awaitable is resolved (and + `run_sync()` will return the awaitable's result). If it raises an exception, the `IOLoop` will stop and the exception will be re-raised to the caller. The keyword-only argument ``timeout`` may be used to set a maximum duration for the function. If the timeout expires, - a `TimeoutError` is raised. + a `tornado.util.TimeoutError` is raised. - This method is useful in conjunction with `tornado.gen.coroutine` - to allow asynchronous calls in a ``main()`` function:: + This method is useful to allow asynchronous calls in a + ``main()`` function:: - @gen.coroutine - def main(): + async def main(): # do stuff... if __name__ == '__main__': IOLoop.current().run_sync(main) .. versionchanged:: 4.3 - Returning a non-``None``, non-yieldable value is now an error. + Returning a non-``None``, non-awaitable value is now an error. + + .. versionchanged:: 5.0 + If a timeout occurs, the ``func`` coroutine will be cancelled. + """ future_cell = [None] @@ -438,22 +549,29 @@ class IOLoop(Configurable): from tornado.gen import convert_yielded result = convert_yielded(result) except Exception: - future_cell[0] = TracebackFuture() - future_cell[0].set_exc_info(sys.exc_info()) + future_cell[0] = Future() + future_set_exc_info(future_cell[0], sys.exc_info()) else: if is_future(result): future_cell[0] = result else: - future_cell[0] = TracebackFuture() + future_cell[0] = Future() future_cell[0].set_result(result) self.add_future(future_cell[0], lambda future: self.stop()) self.add_callback(run) if timeout is not None: - timeout_handle = self.add_timeout(self.time() + timeout, self.stop) + def timeout_callback(): + # If we can cancel the future, do so and wait on it. If not, + # Just stop the loop and return with the task still pending. + # (If we neither cancel nor wait for the task, a warning + # will be logged). + if not future_cell[0].cancel(): + self.stop() + timeout_handle = self.add_timeout(self.time() + timeout, timeout_callback) self.start() if timeout is not None: self.remove_timeout(timeout_handle) - if not future_cell[0].done(): + if future_cell[0].cancelled() or not future_cell[0].done(): raise TimeoutError('Operation timed out after %s seconds' % timeout) return future_cell[0].result() @@ -590,11 +708,46 @@ class IOLoop(Configurable): The callback is invoked with one argument, the `.Future`. + + This method only accepts `.Future` objects and not other + awaitables (unlike most of Tornado where the two are + interchangeable). """ assert is_future(future) callback = stack_context.wrap(callback) - future.add_done_callback( - lambda future: self.add_callback(callback, future)) + future_add_done_callback( + future, lambda future: self.add_callback(callback, future)) + + def run_in_executor(self, executor, func, *args): + """Runs a function in a ``concurrent.futures.Executor``. If + ``executor`` is ``None``, the IO loop's default executor will be used. + + Use `functools.partial` to pass keyword arguments to ``func``. + + .. versionadded:: 5.0 + """ + if ThreadPoolExecutor is None: + raise RuntimeError( + "concurrent.futures is required to use IOLoop.run_in_executor") + + if executor is None: + if not hasattr(self, '_executor'): + from tornado.process import cpu_count + self._executor = ThreadPoolExecutor(max_workers=(cpu_count() * 5)) + executor = self._executor + c_future = executor.submit(func, *args) + # Concurrent Futures are not usable with await. Wrap this in a + # Tornado Future instead, using self.add_future for thread-safety. + t_future = Future() + self.add_future(c_future, lambda f: chain_future(f, t_future)) + return t_future + + def set_default_executor(self, executor): + """Sets the default executor to use with :meth:`run_in_executor`. + + .. versionadded:: 5.0 + """ + self._executor = executor def _run_callback(self, callback): """Runs a callback with error handling. @@ -634,6 +787,16 @@ class IOLoop(Configurable): The exception itself is not passed explicitly, but is available in `sys.exc_info`. + + .. versionchanged:: 5.0 + + When the `asyncio` event loop is used (which is now the + default on Python 3), some callback errors will be handled by + `asyncio` instead of this method. + + .. deprecated: 5.1 + + Support for this method will be removed in Tornado 6.0. """ app_log.error("Exception in callback %r", callback, exc_info=True) @@ -701,6 +864,7 @@ class PollIOLoop(IOLoop): self._stopped = False self._closing = False self._thread_ident = None + self._pid = os.getpid() self._blocking_signal_threshold = None self._timeout_counter = itertools.count() @@ -711,6 +875,22 @@ class PollIOLoop(IOLoop): lambda fd, events: self._waker.consume(), self.READ) + @classmethod + def configurable_base(cls): + return PollIOLoop + + @classmethod + def configurable_default(cls): + if hasattr(select, "epoll"): + from tornado.platform.epoll import EPollIOLoop + return EPollIOLoop + if hasattr(select, "kqueue"): + # Python 2.6+ on BSD or Mac + from tornado.platform.kqueue import KQueueIOLoop + return KQueueIOLoop + from tornado.platform.select import SelectIOLoop + return SelectIOLoop + def close(self, all_fds=False): self._closing = True self.remove_handler(self._waker.fileno()) @@ -721,6 +901,8 @@ class PollIOLoop(IOLoop): self._impl.close() self._callbacks = None self._timeouts = None + if hasattr(self, '_executor'): + self._executor.shutdown() def add_handler(self, fd, handler, events): fd, obj = self.split_fd(fd) @@ -753,12 +935,15 @@ class PollIOLoop(IOLoop): def start(self): if self._running: raise RuntimeError("IOLoop is already running") + if os.getpid() != self._pid: + raise RuntimeError("Cannot share PollIOLoops across processes") self._setup_logging() if self._stopped: self._stopped = False return - old_current = getattr(IOLoop._current, "instance", None) - IOLoop._current.instance = self + old_current = IOLoop.current(instance=False) + if old_current is not self: + self.make_current() self._thread_ident = thread.get_ident() self._running = True @@ -901,7 +1086,10 @@ class PollIOLoop(IOLoop): self._stopped = False if self._blocking_signal_threshold is not None: signal.setitimer(signal.ITIMER_REAL, 0, 0) - IOLoop._current.instance = old_current + if old_current is None: + IOLoop.clear_current() + elif old_current is not self: + old_current.make_current() if old_wakeup_fd is not None: signal.set_wakeup_fd(old_wakeup_fd) @@ -982,25 +1170,40 @@ class PeriodicCallback(object): Note that the timeout is given in milliseconds, while most other time-related functions in Tornado use seconds. + If ``jitter`` is specified, each callback time will be randomly selected + within a window of ``jitter * callback_time`` milliseconds. + Jitter can be used to reduce alignment of events with similar periods. + A jitter of 0.1 means allowing a 10% variation in callback time. + The window is centered on ``callback_time`` so the total number of calls + within a given interval should not be significantly affected by adding + jitter. + If the callback runs for longer than ``callback_time`` milliseconds, subsequent invocations will be skipped to get back on schedule. `start` must be called after the `PeriodicCallback` is created. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + + .. versionchanged:: 5.1 + The ``jitter`` argument is added. """ - def __init__(self, callback, callback_time, io_loop=None): + def __init__(self, callback, callback_time, jitter=0): self.callback = callback if callback_time <= 0: raise ValueError("Periodic callback must have a positive callback_time") self.callback_time = callback_time - self.io_loop = io_loop or IOLoop.current() + self.jitter = jitter self._running = False self._timeout = None def start(self): """Starts the timer.""" + # Looking up the IOLoop here allows to first instantiate the + # PeriodicCallback in another thread, then start it using + # IOLoop.add_callback(). + self.io_loop = IOLoop.current() self._running = True self._next_timeout = self.io_loop.time() self._schedule_next() @@ -1031,11 +1234,34 @@ class PeriodicCallback(object): def _schedule_next(self): if self._running: - current_time = self.io_loop.time() - - if self._next_timeout <= current_time: - callback_time_sec = self.callback_time / 1000.0 - self._next_timeout += (math.floor((current_time - self._next_timeout) / - callback_time_sec) + 1) * callback_time_sec - + self._update_next(self.io_loop.time()) self._timeout = self.io_loop.add_timeout(self._next_timeout, self._run) + + def _update_next(self, current_time): + callback_time_sec = self.callback_time / 1000.0 + if self.jitter: + # apply jitter fraction + callback_time_sec *= 1 + (self.jitter * (random.random() - 0.5)) + if self._next_timeout <= current_time: + # The period should be measured from the start of one call + # to the start of the next. If one call takes too long, + # skip cycles to get back to a multiple of the original + # schedule. + self._next_timeout += (math.floor((current_time - self._next_timeout) / + callback_time_sec) + 1) * callback_time_sec + else: + # If the clock moved backwards, ensure we advance the next + # timeout instead of recomputing the same value again. + # This may result in long gaps between callbacks if the + # clock jumps backwards by a lot, but the far more common + # scenario is a small NTP adjustment that should just be + # ignored. + # + # Note that on some systems if time.time() runs slower + # than time.monotonic() (most common on windows), we + # effectively experience a small backwards time jump on + # every iteration because PeriodicCallback uses + # time.time() while asyncio schedules callbacks using + # time.monotonic(). + # https://github.com/tornadoweb/tornado/issues/2333 + self._next_timeout += callback_time_sec diff --git a/server/www/packages/packages-common/tornado/iostream.py b/server/www/packages/packages-common/tornado/iostream.py index a1619c4..89e1e23 100644 --- a/server/www/packages/packages-common/tornado/iostream.py +++ b/server/www/packages/packages-common/tornado/iostream.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -28,16 +27,18 @@ from __future__ import absolute_import, division, print_function import collections import errno +import io import numbers import os import socket import sys import re +import warnings -from tornado.concurrent import TracebackFuture +from tornado.concurrent import Future from tornado import ioloop from tornado.log import gen_log, app_log -from tornado.netutil import ssl_wrap_socket, ssl_match_hostname, SSLCertificateError, _client_ssl_defaults, _server_ssl_defaults +from tornado.netutil import ssl_wrap_socket, _client_ssl_defaults, _server_ssl_defaults from tornado import stack_context from tornado.util import errno_from_exception @@ -66,7 +67,7 @@ _ERRNO_CONNRESET = (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE, errno.ETIMEDOUT) if hasattr(errno, "WSAECONNRESET"): - _ERRNO_CONNRESET += (errno.WSAECONNRESET, errno.WSAECONNABORTED, errno.WSAETIMEDOUT) # type: ignore + _ERRNO_CONNRESET += (errno.WSAECONNRESET, errno.WSAECONNABORTED, errno.WSAETIMEDOUT) # type: ignore # noqa: E501 if sys.platform == 'darwin': # OSX appears to have a race condition that causes send(2) to return @@ -117,6 +118,96 @@ class StreamBufferFullError(Exception): """ +class _StreamBuffer(object): + """ + A specialized buffer that tries to avoid copies when large pieces + of data are encountered. + """ + + def __init__(self): + # A sequence of (False, bytearray) and (True, memoryview) objects + self._buffers = collections.deque() + # Position in the first buffer + self._first_pos = 0 + self._size = 0 + + def __len__(self): + return self._size + + # Data above this size will be appended separately instead + # of extending an existing bytearray + _large_buf_threshold = 2048 + + def append(self, data): + """ + Append the given piece of data (should be a buffer-compatible object). + """ + size = len(data) + if size > self._large_buf_threshold: + if not isinstance(data, memoryview): + data = memoryview(data) + self._buffers.append((True, data)) + elif size > 0: + if self._buffers: + is_memview, b = self._buffers[-1] + new_buf = is_memview or len(b) >= self._large_buf_threshold + else: + new_buf = True + if new_buf: + self._buffers.append((False, bytearray(data))) + else: + b += data + + self._size += size + + def peek(self, size): + """ + Get a view over at most ``size`` bytes (possibly fewer) at the + current buffer position. + """ + assert size > 0 + try: + is_memview, b = self._buffers[0] + except IndexError: + return memoryview(b'') + + pos = self._first_pos + if is_memview: + return b[pos:pos + size] + else: + return memoryview(b)[pos:pos + size] + + def advance(self, size): + """ + Advance the current buffer position by ``size`` bytes. + """ + assert 0 < size <= self._size + self._size -= size + pos = self._first_pos + + buffers = self._buffers + while buffers and size > 0: + is_large, b = buffers[0] + b_remain = len(b) - size - pos + if b_remain <= 0: + buffers.popleft() + size -= len(b) - pos + pos = 0 + elif is_large: + pos += size + size = 0 + else: + # Amortized O(1) shrink for Python 2 + pos += size + if len(b) <= 2 * pos: + del b[:pos] + pos = 0 + size = 0 + + assert size == 0 + self._first_pos = pos + + class BaseIOStream(object): """A utility class to write to and read from a non-blocking file or socket. @@ -135,12 +226,10 @@ class BaseIOStream(object): Subclasses must implement `fileno`, `close_fd`, `write_to_fd`, `read_from_fd`, and optionally `get_fd_error`. """ - def __init__(self, io_loop=None, max_buffer_size=None, + def __init__(self, max_buffer_size=None, read_chunk_size=None, max_write_buffer_size=None): """`BaseIOStream` constructor. - :arg io_loop: The `.IOLoop` to use; defaults to `.IOLoop.current`. - Deprecated since Tornado 4.1. :arg max_buffer_size: Maximum amount of incoming data to buffer; defaults to 100MB. :arg read_chunk_size: Amount of data to read at one time from the @@ -151,8 +240,11 @@ class BaseIOStream(object): .. versionchanged:: 4.0 Add the ``max_write_buffer_size`` parameter. Changed default ``read_chunk_size`` to 64KB. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been + removed. """ - self.io_loop = io_loop or ioloop.IOLoop.current() + self.io_loop = ioloop.IOLoop.current() self.max_buffer_size = max_buffer_size or 104857600 # A chunk size that is too close to max_buffer_size can cause # spurious failures. @@ -163,13 +255,11 @@ class BaseIOStream(object): self._read_buffer = bytearray() self._read_buffer_pos = 0 self._read_buffer_size = 0 - self._write_buffer = bytearray() - self._write_buffer_pos = 0 - self._write_buffer_size = 0 - self._write_buffer_frozen = False + self._user_read_buffer = False + self._after_user_read_buffer = None + self._write_buffer = _StreamBuffer() self._total_write_index = 0 self._total_write_done_index = 0 - self._pending_writes_while_frozen = [] self._read_delimiter = None self._read_regex = None self._read_max_bytes = None @@ -213,13 +303,18 @@ class BaseIOStream(object): """ raise NotImplementedError() - def read_from_fd(self): + def read_from_fd(self, buf): """Attempts to read from the underlying file. - Returns ``None`` if there was nothing to read (the socket - returned `~errno.EWOULDBLOCK` or equivalent), otherwise - returns the data. When possible, should return no more than - ``self.read_chunk_size`` bytes at a time. + Reads up to ``len(buf)`` bytes, storing them in the buffer. + Returns the number of bytes read. Returns None if there was + nothing to read (the socket returned `~errno.EWOULDBLOCK` or + equivalent), and zero on EOF. + + .. versionchanged:: 5.0 + + Interface redesigned to take a buffer and return a number + of bytes instead of a freshly-allocated object. """ raise NotImplementedError() @@ -248,6 +343,12 @@ class BaseIOStream(object): .. versionchanged:: 4.0 Added the ``max_bytes`` argument. The ``callback`` argument is now optional and a `.Future` will be returned if it is omitted. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. Use the returned `.Future` instead. + """ future = self._set_read_callback(callback) self._read_regex = re.compile(regex) @@ -257,7 +358,7 @@ class BaseIOStream(object): except UnsatisfiableReadError as e: # Handle this the same way as in _handle_events. gen_log.info("Unsatisfiable read, closing connection: %s" % e) - self.close(exc_info=True) + self.close(exc_info=e) return future except: if future is not None: @@ -281,6 +382,11 @@ class BaseIOStream(object): .. versionchanged:: 4.0 Added the ``max_bytes`` argument. The ``callback`` argument is now optional and a `.Future` will be returned if it is omitted. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. Use the returned `.Future` instead. """ future = self._set_read_callback(callback) self._read_delimiter = delimiter @@ -290,7 +396,7 @@ class BaseIOStream(object): except UnsatisfiableReadError as e: # Handle this the same way as in _handle_events. gen_log.info("Unsatisfiable read, closing connection: %s" % e) - self.close(exc_info=True) + self.close(exc_info=e) return future except: if future is not None: @@ -314,12 +420,73 @@ class BaseIOStream(object): .. versionchanged:: 4.0 Added the ``partial`` argument. The callback argument is now optional and a `.Future` will be returned if it is omitted. + + .. deprecated:: 5.1 + + The ``callback`` and ``streaming_callback`` arguments are + deprecated and will be removed in Tornado 6.0. Use the + returned `.Future` (and ``partial=True`` for + ``streaming_callback``) instead. + """ future = self._set_read_callback(callback) assert isinstance(num_bytes, numbers.Integral) self._read_bytes = num_bytes self._read_partial = partial - self._streaming_callback = stack_context.wrap(streaming_callback) + if streaming_callback is not None: + warnings.warn("streaming_callback is deprecated, use partial instead", + DeprecationWarning) + self._streaming_callback = stack_context.wrap(streaming_callback) + try: + self._try_inline_read() + except: + if future is not None: + future.add_done_callback(lambda f: f.exception()) + raise + return future + + def read_into(self, buf, callback=None, partial=False): + """Asynchronously read a number of bytes. + + ``buf`` must be a writable buffer into which data will be read. + If a callback is given, it will be run with the number of read + bytes as an argument; if not, this method returns a `.Future`. + + If ``partial`` is true, the callback is run as soon as any bytes + have been read. Otherwise, it is run when the ``buf`` has been + entirely filled with read data. + + .. versionadded:: 5.0 + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. Use the returned `.Future` instead. + + """ + future = self._set_read_callback(callback) + + # First copy data already in read buffer + available_bytes = self._read_buffer_size + n = len(buf) + if available_bytes >= n: + end = self._read_buffer_pos + n + buf[:] = memoryview(self._read_buffer)[self._read_buffer_pos:end] + del self._read_buffer[:end] + self._after_user_read_buffer = self._read_buffer + elif available_bytes > 0: + buf[:available_bytes] = memoryview(self._read_buffer)[self._read_buffer_pos:] + + # Set up the supplied buffer as our temporary read buffer. + # The original (if it had any data remaining) has been + # saved for later. + self._user_read_buffer = True + self._read_buffer = buf + self._read_buffer_pos = 0 + self._read_buffer_size = available_bytes + self._read_bytes = n + self._read_partial = partial + try: self._try_inline_read() except: @@ -347,9 +514,19 @@ class BaseIOStream(object): The callback argument is now optional and a `.Future` will be returned if it is omitted. + .. deprecated:: 5.1 + + The ``callback`` and ``streaming_callback`` arguments are + deprecated and will be removed in Tornado 6.0. Use the + returned `.Future` (and `read_bytes` with ``partial=True`` + for ``streaming_callback``) instead. + """ future = self._set_read_callback(callback) - self._streaming_callback = stack_context.wrap(streaming_callback) + if streaming_callback is not None: + warnings.warn("streaming_callback is deprecated, use read_bytes(partial=True) instead", + DeprecationWarning) + self._streaming_callback = stack_context.wrap(streaming_callback) if self.closed(): if self._streaming_callback is not None: self._run_read_callback(self._read_buffer_size, True) @@ -383,28 +560,32 @@ class BaseIOStream(object): .. versionchanged:: 4.5 Added support for `memoryview` arguments. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. Use the returned `.Future` instead. + """ self._check_closed() if data: if (self.max_write_buffer_size is not None and - self._write_buffer_size + len(data) > self.max_write_buffer_size): + len(self._write_buffer) + len(data) > self.max_write_buffer_size): raise StreamBufferFullError("Reached maximum write buffer size") - if self._write_buffer_frozen: - self._pending_writes_while_frozen.append(data) - else: - self._write_buffer += data - self._write_buffer_size += len(data) + self._write_buffer.append(data) self._total_write_index += len(data) if callback is not None: + warnings.warn("callback argument is deprecated, use returned Future instead", + DeprecationWarning) self._write_callback = stack_context.wrap(callback) future = None else: - future = TracebackFuture() + future = Future() future.add_done_callback(lambda f: f.exception()) self._write_futures.append((self._total_write_index, future)) if not self._connecting: self._handle_write() - if self._write_buffer_size: + if self._write_buffer: self._add_io_state(self.io_loop.WRITE) self._maybe_add_error_listener() return future @@ -412,9 +593,14 @@ class BaseIOStream(object): def set_close_callback(self, callback): """Call the given callback when the stream is closed. - This is not necessary for applications that use the `.Future` - interface; all outstanding ``Futures`` will resolve with a - `StreamClosedError` when the stream is closed. + This mostly is not necessary for applications that use the + `.Future` interface; all outstanding ``Futures`` will resolve + with a `StreamClosedError` when the stream is closed. However, + it is still useful as a way to signal that the stream has been + closed while no other read or write is in progress. + + Unlike other callback-based interfaces, ``set_close_callback`` + will not be removed in Tornado 6.0. """ self._close_callback = stack_context.wrap(callback) self._maybe_add_error_listener() @@ -428,10 +614,14 @@ class BaseIOStream(object): """ if not self.closed(): if exc_info: - if not isinstance(exc_info, tuple): - exc_info = sys.exc_info() - if any(exc_info): + if isinstance(exc_info, tuple): self.error = exc_info[1] + elif isinstance(exc_info, BaseException): + self.error = exc_info + else: + exc_info = sys.exc_info() + if any(exc_info): + self.error = exc_info[1] if self._read_until_close: if (self._streaming_callback is not None and self._read_buffer_size): @@ -463,6 +653,7 @@ class BaseIOStream(object): self._ssl_connect_future = None for future in futures: future.set_exception(StreamClosedError(real_error=self.error)) + future.exception() if self._close_callback is not None: cb = self._close_callback self._close_callback = None @@ -473,7 +664,6 @@ class BaseIOStream(object): # if the IOStream object is kept alive by a reference cycle. # TODO: Clear the read buffer too; it currently breaks some tests. self._write_buffer = None - self._write_buffer_size = 0 def reading(self): """Returns true if we are currently reading from the stream.""" @@ -481,7 +671,7 @@ class BaseIOStream(object): def writing(self): """Returns true if we are currently writing to the stream.""" - return self._write_buffer_size > 0 + return bool(self._write_buffer) def closed(self): """Returns true if the stream has been closed.""" @@ -548,11 +738,11 @@ class BaseIOStream(object): self.io_loop.update_handler(self.fileno(), self._state) except UnsatisfiableReadError as e: gen_log.info("Unsatisfiable read, closing connection: %s" % e) - self.close(exc_info=True) - except Exception: + self.close(exc_info=e) + except Exception as e: gen_log.error("Uncaught exception, closing connection.", exc_info=True) - self.close(exc_info=True) + self.close(exc_info=e) raise def _run_callback(self, callback, *args): @@ -560,14 +750,14 @@ class BaseIOStream(object): self._pending_callbacks -= 1 try: return callback(*args) - except Exception: + except Exception as e: app_log.error("Uncaught exception, closing connection.", exc_info=True) # Close the socket on an uncaught exception from a user callback # (It would eventually get closed when the socket object is # gc'd, but we don't want to rely on gc happening before we # run out of file descriptors) - self.close(exc_info=True) + self.close(exc_info=e) # Re-raise the exception so that IOLoop.handle_callback_exception # can see it and log the error raise @@ -657,7 +847,7 @@ class BaseIOStream(object): raise except Exception as e: gen_log.warning("error on read: %s" % e) - self.close(exc_info=True) + self.close(exc_info=e) return if pos is not None: self._read_from_buffer(pos) @@ -669,12 +859,23 @@ class BaseIOStream(object): assert self._read_callback is None, "Already reading" assert self._read_future is None, "Already reading" if callback is not None: + warnings.warn("callbacks are deprecated, use returned Future instead", + DeprecationWarning) self._read_callback = stack_context.wrap(callback) else: - self._read_future = TracebackFuture() + self._read_future = Future() return self._read_future def _run_read_callback(self, size, streaming): + if self._user_read_buffer: + self._read_buffer = self._after_user_read_buffer or bytearray() + self._after_user_read_buffer = None + self._read_buffer_pos = 0 + self._read_buffer_size = len(self._read_buffer) + self._user_read_buffer = False + result = size + else: + result = self._consume(size) if streaming: callback = self._streaming_callback else: @@ -684,10 +885,11 @@ class BaseIOStream(object): assert callback is None future = self._read_future self._read_future = None - future.set_result(self._consume(size)) + + future.set_result(result) if callback is not None: assert (self._read_future is None) or streaming - self._run_callback(callback, self._consume(size)) + self._run_callback(callback, result) else: # If we scheduled a callback, we will add the error listener # afterwards. If we didn't, we have to do it now. @@ -733,31 +935,44 @@ class BaseIOStream(object): to read (i.e. the read returns EWOULDBLOCK or equivalent). On error closes the socket and raises an exception. """ - while True: - try: - chunk = self.read_from_fd() - except (socket.error, IOError, OSError) as e: - if errno_from_exception(e) == errno.EINTR: - continue - # ssl.SSLError is a subclass of socket.error - if self._is_connreset(e): - # Treat ECONNRESET as a connection close rather than - # an error to minimize log spam (the exception will - # be available on self.error for apps that care). - self.close(exc_info=True) - return - self.close(exc_info=True) - raise - break - if chunk is None: - return 0 - self._read_buffer += chunk - self._read_buffer_size += len(chunk) + try: + while True: + try: + if self._user_read_buffer: + buf = memoryview(self._read_buffer)[self._read_buffer_size:] + else: + buf = bytearray(self.read_chunk_size) + bytes_read = self.read_from_fd(buf) + except (socket.error, IOError, OSError) as e: + if errno_from_exception(e) == errno.EINTR: + continue + # ssl.SSLError is a subclass of socket.error + if self._is_connreset(e): + # Treat ECONNRESET as a connection close rather than + # an error to minimize log spam (the exception will + # be available on self.error for apps that care). + self.close(exc_info=e) + return + self.close(exc_info=e) + raise + break + if bytes_read is None: + return 0 + elif bytes_read == 0: + self.close() + return 0 + if not self._user_read_buffer: + self._read_buffer += memoryview(buf)[:bytes_read] + self._read_buffer_size += bytes_read + finally: + # Break the reference to buf so we don't waste a chunk's worth of + # memory in case an exception hangs on to our stack frame. + buf = None if self._read_buffer_size > self.max_buffer_size: gen_log.error("Reached maximum read buffer size") self.close() raise StreamBufferFullError("Reached maximum read buffer size") - return len(chunk) + return bytes_read def _run_streaming_callback(self): if self._streaming_callback is not None and self._read_buffer_size: @@ -827,56 +1042,28 @@ class BaseIOStream(object): "delimiter %r not found within %d bytes" % ( delimiter, self._read_max_bytes)) - def _freeze_write_buffer(self, size): - self._write_buffer_frozen = size - - def _unfreeze_write_buffer(self): - self._write_buffer_frozen = False - self._write_buffer += b''.join(self._pending_writes_while_frozen) - self._write_buffer_size += sum(map(len, self._pending_writes_while_frozen)) - self._pending_writes_while_frozen[:] = [] - - def _got_empty_write(self, size): - """ - Called when a non-blocking write() failed writing anything. - Can be overridden in subclasses. - """ - def _handle_write(self): - while self._write_buffer_size: - assert self._write_buffer_size >= 0 + while True: + size = len(self._write_buffer) + if not size: + break + assert size > 0 try: - start = self._write_buffer_pos - if self._write_buffer_frozen: - size = self._write_buffer_frozen - elif _WINDOWS: + if _WINDOWS: # On windows, socket.send blows up if given a # write buffer that's too large, instead of just # returning the number of bytes it was able to # process. Therefore we must not call socket.send # with more than 128KB at a time. size = 128 * 1024 - else: - size = self._write_buffer_size - num_bytes = self.write_to_fd( - memoryview(self._write_buffer)[start:start + size]) + + num_bytes = self.write_to_fd(self._write_buffer.peek(size)) if num_bytes == 0: - self._got_empty_write(size) break - self._write_buffer_pos += num_bytes - self._write_buffer_size -= num_bytes - # Amortized O(1) shrink - # (this heuristic is implemented natively in Python 3.4+ - # but is replicated here for Python 2) - if self._write_buffer_pos > self._write_buffer_size: - del self._write_buffer[:self._write_buffer_pos] - self._write_buffer_pos = 0 - if self._write_buffer_frozen: - self._unfreeze_write_buffer() + self._write_buffer.advance(num_bytes) self._total_write_done_index += num_bytes except (socket.error, IOError, OSError) as e: if e.args[0] in _ERRNO_WOULDBLOCK: - self._got_empty_write(size) break else: if not self._is_connreset(e): @@ -885,7 +1072,7 @@ class BaseIOStream(object): # minimize log spam gen_log.warning("Write error on %s: %s", self.fileno(), e) - self.close(exc_info=True) + self.close(exc_info=e) return while self._write_futures: @@ -895,7 +1082,7 @@ class BaseIOStream(object): self._write_futures.popleft() future.set_result(None) - if not self._write_buffer_size: + if not len(self._write_buffer): if self._write_callback: callback = self._write_callback self._write_callback = None @@ -1003,24 +1190,23 @@ class IOStream(BaseIOStream): import tornado.iostream import socket - def send_request(): - stream.write(b"GET / HTTP/1.0\r\nHost: friendfeed.com\r\n\r\n") - stream.read_until(b"\r\n\r\n", on_headers) - - def on_headers(data): + async def main(): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + stream = tornado.iostream.IOStream(s) + await stream.connect(("friendfeed.com", 80)) + await stream.write(b"GET / HTTP/1.0\r\nHost: friendfeed.com\r\n\r\n") + header_data = await stream.read_until(b"\r\n\r\n") headers = {} - for line in data.split(b"\r\n"): - parts = line.split(b":") - if len(parts) == 2: - headers[parts[0].strip()] = parts[1].strip() - stream.read_bytes(int(headers[b"Content-Length"]), on_body) - - def on_body(data): - print(data) + for line in header_data.split(b"\r\n"): + parts = line.split(b":") + if len(parts) == 2: + headers[parts[0].strip()] = parts[1].strip() + body_data = await stream.read_bytes(int(headers[b"Content-Length"])) + print(body_data) stream.close() - tornado.ioloop.IOLoop.current().stop() if __name__ == '__main__': + tornado.ioloop.IOLoop.current().run_sync(main) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) stream = tornado.iostream.IOStream(s) stream.connect(("friendfeed.com", 80), send_request) @@ -1047,21 +1233,24 @@ class IOStream(BaseIOStream): socket.SO_ERROR) return socket.error(errno, os.strerror(errno)) - def read_from_fd(self): + def read_from_fd(self, buf): try: - chunk = self.socket.recv(self.read_chunk_size) + return self.socket.recv_into(buf) except socket.error as e: if e.args[0] in _ERRNO_WOULDBLOCK: return None else: raise - if not chunk: - self.close() - return None - return chunk + finally: + buf = None def write_to_fd(self, data): - return self.socket.send(data) + try: + return self.socket.send(data) + finally: + # Avoid keeping to data, which can be a memoryview. + # See https://github.com/tornadoweb/tornado/pull/2008 + del data def connect(self, address, callback=None, server_hostname=None): """Connects the socket to a remote address without blocking. @@ -1101,13 +1290,21 @@ class IOStream(BaseIOStream): ``ssl_options=dict(cert_reqs=ssl.CERT_NONE)`` or a suitably-configured `ssl.SSLContext` to the `SSLIOStream` constructor to disable. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. Use the returned `.Future` instead. + """ self._connecting = True if callback is not None: + warnings.warn("callback argument is deprecated, use returned Future instead", + DeprecationWarning) self._connect_callback = stack_context.wrap(callback) future = None else: - future = self._connect_future = TracebackFuture() + future = self._connect_future = Future() try: self.socket.connect(address) except socket.error as e: @@ -1123,7 +1320,7 @@ class IOStream(BaseIOStream): if future is None: gen_log.warning("Connect error on fd %s: %s", self.socket.fileno(), e) - self.close(exc_info=True) + self.close(exc_info=e) return future self._add_io_state(self.io_loop.WRITE) return future @@ -1185,9 +1382,8 @@ class IOStream(BaseIOStream): orig_close_callback = self._close_callback self._close_callback = None - future = TracebackFuture() - ssl_stream = SSLIOStream(socket, ssl_options=ssl_options, - io_loop=self.io_loop) + future = Future() + ssl_stream = SSLIOStream(socket, ssl_options=ssl_options) # Wrap the original close callback so we can fail our Future as well. # If we had an "unwrap" counterpart to this method we would need # to restore the original callback after our Future resolves @@ -1214,7 +1410,13 @@ class IOStream(BaseIOStream): return future def _handle_connect(self): - err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + try: + err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + except socket.error as e: + # Hurd doesn't allow SO_ERROR for loopback sockets because all + # errors for such sockets are reported synchronously. + if errno_from_exception(e) == errno.ENOPROTOOPT: + err = 0 if err != 0: self.error = socket.error(err, os.strerror(err)) # IOLoop implementations may vary: some of them return @@ -1291,17 +1493,6 @@ class SSLIOStream(IOStream): def writing(self): return self._handshake_writing or super(SSLIOStream, self).writing() - def _got_empty_write(self, size): - # With OpenSSL, if we couldn't write the entire buffer, - # the very same string object must be used on the - # next call to send. Therefore we suppress - # merging the write buffer after an incomplete send. - # A cleaner solution would be to set - # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, but this is - # not yet accessible from python - # (http://bugs.python.org/issue8240) - self._freeze_write_buffer(size) - def _do_ssl_handshake(self): # Based on code from test_ssl.py in the python stdlib try: @@ -1317,7 +1508,7 @@ class SSLIOStream(IOStream): return elif err.args[0] in (ssl.SSL_ERROR_EOF, ssl.SSL_ERROR_ZERO_RETURN): - return self.close(exc_info=True) + return self.close(exc_info=err) elif err.args[0] == ssl.SSL_ERROR_SSL: try: peer = self.socket.getpeername() @@ -1325,7 +1516,7 @@ class SSLIOStream(IOStream): peer = '(not connected)' gen_log.warning("SSL Error on %s %s: %s", self.socket.fileno(), peer, err) - return self.close(exc_info=True) + return self.close(exc_info=err) raise except socket.error as err: # Some port scans (e.g. nmap in -sT mode) have been known @@ -1334,13 +1525,13 @@ class SSLIOStream(IOStream): # https://groups.google.com/forum/?fromgroups#!topic/python-tornado/ApucKJat1_0 if (self._is_connreset(err) or err.args[0] in (errno.EBADF, errno.ENOTCONN)): - return self.close(exc_info=True) + return self.close(exc_info=err) raise - except AttributeError: + except AttributeError as err: # On Linux, if the connection was reset before the call to # wrap_socket, do_handshake will fail with an # AttributeError. - return self.close(exc_info=True) + return self.close(exc_info=err) else: self._ssl_accepting = False if not self._verify_cert(self.socket.getpeercert()): @@ -1378,8 +1569,8 @@ class SSLIOStream(IOStream): gen_log.warning("No SSL certificate given") return False try: - ssl_match_hostname(peercert, self._server_hostname) - except SSLCertificateError as e: + ssl.match_hostname(peercert, self._server_hostname) + except ssl.CertificateError as e: gen_log.warning("Invalid SSL certificate: %s" % e) return False else: @@ -1399,9 +1590,13 @@ class SSLIOStream(IOStream): def connect(self, address, callback=None, server_hostname=None): self._server_hostname = server_hostname - # Pass a dummy callback to super.connect(), which is slightly - # more efficient than letting it return a Future we ignore. - super(SSLIOStream, self).connect(address, callback=lambda: None) + # Ignore the result of connect(). If it fails, + # wait_for_handshake will raise an error too. This is + # necessary for the old semantics of the connect callback + # (which takes no arguments). In 6.0 this can be refactored to + # be a regular coroutine. + fut = super(SSLIOStream, self).connect(address) + fut.add_done_callback(lambda f: f.exception()) return self.wait_for_handshake(callback) def _handle_connect(self): @@ -1445,15 +1640,23 @@ class SSLIOStream(IOStream): handshake to complete). It may only be called once per stream. .. versionadded:: 4.2 + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed + in Tornado 6.0. Use the returned `.Future` instead. + """ if (self._ssl_connect_callback is not None or self._ssl_connect_future is not None): raise RuntimeError("Already waiting") if callback is not None: + warnings.warn("callback argument is deprecated, use returned Future instead", + DeprecationWarning) self._ssl_connect_callback = stack_context.wrap(callback) future = None else: - future = self._ssl_connect_future = TracebackFuture() + future = self._ssl_connect_future = Future() if not self._ssl_accepting: self._run_ssl_connect_callback() return future @@ -1471,36 +1674,34 @@ class SSLIOStream(IOStream): # simply return 0 bytes written. return 0 raise + finally: + # Avoid keeping to data, which can be a memoryview. + # See https://github.com/tornadoweb/tornado/pull/2008 + del data - def read_from_fd(self): - if self._ssl_accepting: - # If the handshake hasn't finished yet, there can't be anything - # to read (attempting to read may or may not raise an exception - # depending on the SSL version) - return None + def read_from_fd(self, buf): try: - # SSLSocket objects have both a read() and recv() method, - # while regular sockets only have recv(). - # The recv() method blocks (at least in python 2.6) if it is - # called when there is nothing to read, so we have to use - # read() instead. - chunk = self.socket.read(self.read_chunk_size) - except ssl.SSLError as e: - # SSLError is a subclass of socket.error, so this except - # block must come first. - if e.args[0] == ssl.SSL_ERROR_WANT_READ: + if self._ssl_accepting: + # If the handshake hasn't finished yet, there can't be anything + # to read (attempting to read may or may not raise an exception + # depending on the SSL version) return None - else: - raise - except socket.error as e: - if e.args[0] in _ERRNO_WOULDBLOCK: - return None - else: - raise - if not chunk: - self.close() - return None - return chunk + try: + return self.socket.recv_into(buf) + except ssl.SSLError as e: + # SSLError is a subclass of socket.error, so this except + # block must come first. + if e.args[0] == ssl.SSL_ERROR_WANT_READ: + return None + else: + raise + except socket.error as e: + if e.args[0] in _ERRNO_WOULDBLOCK: + return None + else: + raise + finally: + buf = None def _is_connreset(self, e): if isinstance(e, ssl.SSLError) and e.args[0] == ssl.SSL_ERROR_EOF: @@ -1518,6 +1719,7 @@ class PipeIOStream(BaseIOStream): """ def __init__(self, fd, *args, **kwargs): self.fd = fd + self._fio = io.FileIO(self.fd, "r+") _set_nonblocking(fd) super(PipeIOStream, self).__init__(*args, **kwargs) @@ -1525,28 +1727,29 @@ class PipeIOStream(BaseIOStream): return self.fd def close_fd(self): - os.close(self.fd) + self._fio.close() def write_to_fd(self, data): - return os.write(self.fd, data) - - def read_from_fd(self): try: - chunk = os.read(self.fd, self.read_chunk_size) + return os.write(self.fd, data) + finally: + # Avoid keeping to data, which can be a memoryview. + # See https://github.com/tornadoweb/tornado/pull/2008 + del data + + def read_from_fd(self, buf): + try: + return self._fio.readinto(buf) except (IOError, OSError) as e: - if errno_from_exception(e) in _ERRNO_WOULDBLOCK: - return None - elif errno_from_exception(e) == errno.EBADF: + if errno_from_exception(e) == errno.EBADF: # If the writing half of a pipe is closed, select will # report it as readable but reads will fail with EBADF. - self.close(exc_info=True) + self.close(exc_info=e) return None else: raise - if not chunk: - self.close() - return None - return chunk + finally: + buf = None def doctests(): diff --git a/server/www/packages/packages-common/tornado/locale.py b/server/www/packages/packages-common/tornado/locale.py index 7dba10d..d45172f 100644 --- a/server/www/packages/packages-common/tornado/locale.py +++ b/server/www/packages/packages-common/tornado/locale.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +# # Copyright 2009 Facebook # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/server/www/packages/packages-common/tornado/locks.py b/server/www/packages/packages-common/tornado/locks.py index 4f9ecf6..9566a45 100644 --- a/server/www/packages/packages-common/tornado/locks.py +++ b/server/www/packages/packages-common/tornado/locks.py @@ -15,9 +15,10 @@ from __future__ import absolute_import, division, print_function import collections +from concurrent.futures import CancelledError from tornado import gen, ioloop -from tornado.concurrent import Future +from tornado.concurrent import Future, future_set_result_unless_cancelled __all__ = ['Condition', 'Event', 'Semaphore', 'BoundedSemaphore', 'Lock'] @@ -60,22 +61,19 @@ class Condition(_TimeoutGarbageCollector): condition = Condition() - @gen.coroutine - def waiter(): + async def waiter(): print("I'll wait right here") - yield condition.wait() # Yield a Future. + await condition.wait() print("I'm done waiting") - @gen.coroutine - def notifier(): + async def notifier(): print("About to notify") condition.notify() print("Done notifying") - @gen.coroutine - def runner(): - # Yield two Futures; wait for waiter() and notifier() to finish. - yield [waiter(), notifier()] + async def runner(): + # Wait for waiter() and notifier() in parallel + await gen.multi([waiter(), notifier()]) IOLoop.current().run_sync(runner) @@ -92,15 +90,19 @@ class Condition(_TimeoutGarbageCollector): io_loop = IOLoop.current() # Wait up to 1 second for a notification. - yield condition.wait(timeout=io_loop.time() + 1) + await condition.wait(timeout=io_loop.time() + 1) ...or a `datetime.timedelta` for a timeout relative to the current time:: # Wait up to 1 second. - yield condition.wait(timeout=datetime.timedelta(seconds=1)) + await condition.wait(timeout=datetime.timedelta(seconds=1)) - The method raises `tornado.gen.TimeoutError` if there's no notification - before the deadline. + The method returns False if there's no notification before the deadline. + + .. versionchanged:: 5.0 + Previously, waiters could be notified synchronously from within + `notify`. Now, the notification will always be received on the + next iteration of the `.IOLoop`. """ def __init__(self): @@ -123,7 +125,8 @@ class Condition(_TimeoutGarbageCollector): self._waiters.append(waiter) if timeout: def on_timeout(): - waiter.set_result(False) + if not waiter.done(): + future_set_result_unless_cancelled(waiter, False) self._garbage_collect() io_loop = ioloop.IOLoop.current() timeout_handle = io_loop.add_timeout(timeout, on_timeout) @@ -141,7 +144,7 @@ class Condition(_TimeoutGarbageCollector): waiters.append(waiter) for waiter in waiters: - waiter.set_result(True) + future_set_result_unless_cancelled(waiter, True) def notify_all(self): """Wake all waiters.""" @@ -164,22 +167,19 @@ class Event(object): event = Event() - @gen.coroutine - def waiter(): + async def waiter(): print("Waiting for event") - yield event.wait() + await event.wait() print("Not waiting this time") - yield event.wait() + await event.wait() print("Done") - @gen.coroutine - def setter(): + async def setter(): print("About to set the event") event.set() - @gen.coroutine - def runner(): - yield [waiter(), setter()] + async def runner(): + await gen.multi([waiter(), setter()]) IOLoop.current().run_sync(runner) @@ -191,7 +191,8 @@ class Event(object): Done """ def __init__(self): - self._future = Future() + self._value = False + self._waiters = set() def __repr__(self): return '<%s %s>' % ( @@ -199,34 +200,48 @@ class Event(object): def is_set(self): """Return ``True`` if the internal flag is true.""" - return self._future.done() + return self._value def set(self): """Set the internal flag to ``True``. All waiters are awakened. Calling `.wait` once the flag is set will not block. """ - if not self._future.done(): - self._future.set_result(None) + if not self._value: + self._value = True + + for fut in self._waiters: + if not fut.done(): + fut.set_result(None) def clear(self): """Reset the internal flag to ``False``. Calls to `.wait` will block until `.set` is called. """ - if self._future.done(): - self._future = Future() + self._value = False def wait(self, timeout=None): """Block until the internal flag is true. - Returns a Future, which raises `tornado.gen.TimeoutError` after a + Returns a Future, which raises `tornado.util.TimeoutError` after a timeout. """ + fut = Future() + if self._value: + fut.set_result(None) + return fut + self._waiters.add(fut) + fut.add_done_callback(lambda fut: self._waiters.remove(fut)) if timeout is None: - return self._future + return fut else: - return gen.with_timeout(timeout, self._future) + timeout_fut = gen.with_timeout(timeout, fut, quiet_exceptions=(CancelledError,)) + # This is a slightly clumsy workaround for the fact that + # gen.with_timeout doesn't cancel its futures. Cancelling + # fut will remove it from the waiters list. + timeout_fut.add_done_callback(lambda tf: fut.cancel() if not fut.done() else None) + return timeout_fut class _ReleasingContextManager(object): @@ -269,10 +284,11 @@ class Semaphore(_TimeoutGarbageCollector): # Ensure reliable doctest output: resolve Futures one at a time. futures_q = deque([Future() for _ in range(3)]) - @gen.coroutine - def simulator(futures): + async def simulator(futures): for f in futures: - yield gen.moment + # simulate the asynchronous passage of time + await gen.sleep(0) + await gen.sleep(0) f.set_result(None) IOLoop.current().add_callback(simulator, list(futures_q)) @@ -288,20 +304,18 @@ class Semaphore(_TimeoutGarbageCollector): sem = Semaphore(2) - @gen.coroutine - def worker(worker_id): - yield sem.acquire() + async def worker(worker_id): + await sem.acquire() try: print("Worker %d is working" % worker_id) - yield use_some_resource() + await use_some_resource() finally: print("Worker %d is done" % worker_id) sem.release() - @gen.coroutine - def runner(): + async def runner(): # Join all workers. - yield [worker(i) for i in range(3)] + await gen.multi([worker(i) for i in range(3)]) IOLoop.current().run_sync(runner) @@ -317,7 +331,18 @@ class Semaphore(_TimeoutGarbageCollector): Workers 0 and 1 are allowed to run concurrently, but worker 2 waits until the semaphore has been released once, by worker 0. - `.acquire` is a context manager, so ``worker`` could be written as:: + The semaphore can be used as an async context manager:: + + async def worker(worker_id): + async with sem: + print("Worker %d is working" % worker_id) + await use_some_resource() + + # Now the semaphore has been released. + print("Worker %d is done" % worker_id) + + For compatibility with older versions of Python, `.acquire` is a + context manager, so ``worker`` could also be written as:: @gen.coroutine def worker(worker_id): @@ -328,19 +353,9 @@ class Semaphore(_TimeoutGarbageCollector): # Now the semaphore has been released. print("Worker %d is done" % worker_id) - In Python 3.5, the semaphore itself can be used as an async context - manager:: - - async def worker(worker_id): - async with sem: - print("Worker %d is working" % worker_id) - await use_some_resource() - - # Now the semaphore has been released. - print("Worker %d is done" % worker_id) - .. versionchanged:: 4.3 Added ``async with`` support in Python 3.5. + """ def __init__(self, value=1): super(Semaphore, self).__init__() @@ -388,7 +403,8 @@ class Semaphore(_TimeoutGarbageCollector): self._waiters.append(waiter) if timeout: def on_timeout(): - waiter.set_exception(gen.TimeoutError()) + if not waiter.done(): + waiter.set_exception(gen.TimeoutError()) self._garbage_collect() io_loop = ioloop.IOLoop.current() timeout_handle = io_loop.add_timeout(timeout, on_timeout) @@ -440,26 +456,24 @@ class Lock(object): Releasing an unlocked lock raises `RuntimeError`. - `acquire` supports the context manager protocol in all Python versions: + A Lock can be used as an async context manager with the ``async + with`` statement: - >>> from tornado import gen, locks + >>> from tornado import locks >>> lock = locks.Lock() >>> - >>> @gen.coroutine - ... def f(): - ... with (yield lock.acquire()): + >>> async def f(): + ... async with lock: ... # Do something holding the lock. ... pass ... ... # Now the lock is released. - In Python 3.5, `Lock` also supports the async context manager - protocol. Note that in this case there is no `acquire`, because - ``async with`` includes both the ``yield`` and the ``acquire`` - (just as it does with `threading.Lock`): + For compatibility with older versions of Python, the `.acquire` + method asynchronously returns a regular context manager: - >>> async def f(): # doctest: +SKIP - ... async with lock: + >>> async def f2(): + ... with (yield lock.acquire()): ... # Do something holding the lock. ... pass ... @@ -480,7 +494,7 @@ class Lock(object): def acquire(self, timeout=None): """Attempt to lock. Returns a Future. - Returns a Future, which raises `tornado.gen.TimeoutError` after a + Returns a Future, which raises `tornado.util.TimeoutError` after a timeout. """ return self._block.acquire(timeout) diff --git a/server/www/packages/packages-common/tornado/log.py b/server/www/packages/packages-common/tornado/log.py index 654afc0..cda905c 100644 --- a/server/www/packages/packages-common/tornado/log.py +++ b/server/www/packages/packages-common/tornado/log.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2012 Facebook # @@ -102,7 +101,8 @@ class LogFormatter(logging.Formatter): Added support for ``colorama``. Changed the constructor signature to be compatible with `logging.config.dictConfig`. """ - DEFAULT_FORMAT = '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s' + DEFAULT_FORMAT = \ + '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s' DEFAULT_DATE_FORMAT = '%y%m%d %H:%M:%S' DEFAULT_COLORS = { logging.DEBUG: 4, # Blue @@ -115,13 +115,13 @@ class LogFormatter(logging.Formatter): style='%', color=True, colors=DEFAULT_COLORS): r""" :arg bool color: Enables color support. - :arg string fmt: Log message format. + :arg str fmt: Log message format. It will be applied to the attributes dict of log records. The text between ``%(color)s`` and ``%(end_color)s`` will be colored depending on the level if color support is on. :arg dict colors: color mappings from logging level to terminal color code - :arg string datefmt: Datetime format. + :arg str datefmt: Datetime format. Used for formatting ``(asctime)`` placeholder in ``prefix_fmt``. .. versionchanged:: 3.2 @@ -177,7 +177,7 @@ class LogFormatter(logging.Formatter): # bytestrings. This is a bit of a hacky place to do this, but # it's worth it since the encoding errors that would otherwise # result are so useless (and tornado is fond of using utf8-encoded - # byte strings whereever possible). + # byte strings wherever possible). record.message = _safe_unicode(message) except Exception as e: record.message = "Bad message (%r): %r" % (e, record.__dict__) diff --git a/server/www/packages/packages-common/tornado/netutil.py b/server/www/packages/packages-common/tornado/netutil.py index c34c8c8..e63683a 100644 --- a/server/www/packages/packages-common/tornado/netutil.py +++ b/server/www/packages/packages-common/tornado/netutil.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2011 Facebook # @@ -25,6 +24,7 @@ import socket import stat from tornado.concurrent import dummy_executor, run_on_executor +from tornado import gen from tornado.ioloop import IOLoop from tornado.platform.auto import set_close_exec from tornado.util import PY3, Configurable, errno_from_exception @@ -35,54 +35,20 @@ except ImportError: # ssl is not available on Google App Engine ssl = None -try: - import certifi -except ImportError: - # certifi is optional as long as we have ssl.create_default_context. - if ssl is None or hasattr(ssl, 'create_default_context'): - certifi = None - else: - raise - if PY3: xrange = range -if hasattr(ssl, 'match_hostname') and hasattr(ssl, 'CertificateError'): # python 3.2+ - ssl_match_hostname = ssl.match_hostname - SSLCertificateError = ssl.CertificateError -elif ssl is None: - ssl_match_hostname = SSLCertificateError = None # type: ignore -else: - import backports.ssl_match_hostname - ssl_match_hostname = backports.ssl_match_hostname.match_hostname - SSLCertificateError = backports.ssl_match_hostname.CertificateError # type: ignore - -if hasattr(ssl, 'SSLContext'): - if hasattr(ssl, 'create_default_context'): - # Python 2.7.9+, 3.4+ - # Note that the naming of ssl.Purpose is confusing; the purpose - # of a context is to authentiate the opposite side of the connection. - _client_ssl_defaults = ssl.create_default_context( - ssl.Purpose.SERVER_AUTH) - _server_ssl_defaults = ssl.create_default_context( - ssl.Purpose.CLIENT_AUTH) - else: - # Python 3.2-3.3 - _client_ssl_defaults = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - _client_ssl_defaults.verify_mode = ssl.CERT_REQUIRED - _client_ssl_defaults.load_verify_locations(certifi.where()) - _server_ssl_defaults = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - if hasattr(ssl, 'OP_NO_COMPRESSION'): - # Disable TLS compression to avoid CRIME and related attacks. - # This constant wasn't added until python 3.3. - _client_ssl_defaults.options |= ssl.OP_NO_COMPRESSION - _server_ssl_defaults.options |= ssl.OP_NO_COMPRESSION - -elif ssl: - # Python 2.6-2.7.8 - _client_ssl_defaults = dict(cert_reqs=ssl.CERT_REQUIRED, - ca_certs=certifi.where()) - _server_ssl_defaults = {} +if ssl is not None: + # Note that the naming of ssl.Purpose is confusing; the purpose + # of a context is to authentiate the opposite side of the connection. + _client_ssl_defaults = ssl.create_default_context( + ssl.Purpose.SERVER_AUTH) + _server_ssl_defaults = ssl.create_default_context( + ssl.Purpose.CLIENT_AUTH) + if hasattr(ssl, 'OP_NO_COMPRESSION'): + # See netutil.ssl_options_to_context + _client_ssl_defaults.options |= ssl.OP_NO_COMPRESSION + _server_ssl_defaults.options |= ssl.OP_NO_COMPRESSION else: # Google App Engine _client_ssl_defaults = dict(cert_reqs=None, @@ -172,7 +138,12 @@ def bind_sockets(port, address=None, family=socket.AF_UNSPEC, raise set_close_exec(sock.fileno()) if os.name != 'nt': - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + except socket.error as e: + if errno_from_exception(e) != errno.ENOPROTOOPT: + # Hurd doesn't support SO_REUSEADDR. + raise if reuse_port: sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) if af == socket.AF_INET6: @@ -214,7 +185,12 @@ if hasattr(socket, 'AF_UNIX'): """ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) set_close_exec(sock.fileno()) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + except socket.error as e: + if errno_from_exception(e) != errno.ENOPROTOOPT: + # Hurd doesn't support SO_REUSEADDR + raise sock.setblocking(0) try: st = os.stat(file) @@ -232,7 +208,7 @@ if hasattr(socket, 'AF_UNIX'): return sock -def add_accept_handler(sock, callback, io_loop=None): +def add_accept_handler(sock, callback): """Adds an `.IOLoop` event handler to accept new connections on ``sock``. When a connection is accepted, ``callback(connection, address)`` will @@ -241,11 +217,17 @@ def add_accept_handler(sock, callback, io_loop=None): is different from the ``callback(fd, events)`` signature used for `.IOLoop` handlers. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + A callable is returned which, when called, will remove the `.IOLoop` + event handler and stop processing further incoming connections. + + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + + .. versionchanged:: 5.0 + A callable is returned (``None`` was returned before). """ - if io_loop is None: - io_loop = IOLoop.current() + io_loop = IOLoop.current() + removed = [False] def accept_handler(fd, events): # More connections may come in while we're handling callbacks; @@ -260,6 +242,9 @@ def add_accept_handler(sock, callback, io_loop=None): # heuristic for the number of connections we can reasonably # accept at once. for i in xrange(_DEFAULT_BACKLOG): + if removed[0]: + # The socket was probably closed + return try: connection, address = sock.accept() except socket.error as e: @@ -273,8 +258,15 @@ def add_accept_handler(sock, callback, io_loop=None): if errno_from_exception(e) == errno.ECONNABORTED: continue raise + set_close_exec(connection.fileno()) callback(connection, address) + + def remove_handler(): + io_loop.remove_handler(sock) + removed[0] = True + io_loop.add_handler(sock, accept_handler, IOLoop.READ) + return remove_handler def is_valid_ip(ip): @@ -310,11 +302,16 @@ class Resolver(Configurable): The implementations of this interface included with Tornado are - * `tornado.netutil.BlockingResolver` - * `tornado.netutil.ThreadedResolver` + * `tornado.netutil.DefaultExecutorResolver` + * `tornado.netutil.BlockingResolver` (deprecated) + * `tornado.netutil.ThreadedResolver` (deprecated) * `tornado.netutil.OverrideResolver` * `tornado.platform.twisted.TwistedResolver` * `tornado.platform.caresresolver.CaresResolver` + + .. versionchanged:: 5.0 + The default implementation has changed from `BlockingResolver` to + `DefaultExecutorResolver`. """ @classmethod def configurable_base(cls): @@ -322,7 +319,7 @@ class Resolver(Configurable): @classmethod def configurable_default(cls): - return BlockingResolver + return DefaultExecutorResolver def resolve(self, host, port, family=socket.AF_UNSPEC, callback=None): """Resolves an address. @@ -341,6 +338,10 @@ class Resolver(Configurable): .. versionchanged:: 4.4 Standardized all implementations to raise `IOError`. + + .. deprecated:: 5.1 + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ raise NotImplementedError() @@ -353,6 +354,31 @@ class Resolver(Configurable): pass +def _resolve_addr(host, port, family=socket.AF_UNSPEC): + # On Solaris, getaddrinfo fails if the given port is not found + # in /etc/services and no socket type is given, so we must pass + # one here. The socket type used here doesn't seem to actually + # matter (we discard the one we get back in the results), + # so the addresses we return should still be usable with SOCK_DGRAM. + addrinfo = socket.getaddrinfo(host, port, family, socket.SOCK_STREAM) + results = [] + for family, socktype, proto, canonname, address in addrinfo: + results.append((family, address)) + return results + + +class DefaultExecutorResolver(Resolver): + """Resolver implementation using `.IOLoop.run_in_executor`. + + .. versionadded:: 5.0 + """ + @gen.coroutine + def resolve(self, host, port, family=socket.AF_UNSPEC): + result = yield IOLoop.current().run_in_executor( + None, _resolve_addr, host, port, family) + raise gen.Return(result) + + class ExecutorResolver(Resolver): """Resolver implementation using a `concurrent.futures.Executor`. @@ -363,11 +389,15 @@ class ExecutorResolver(Resolver): ``close_resolver=False``; use this if you want to reuse the same executor elsewhere. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + + .. deprecated:: 5.0 + The default `Resolver` now uses `.IOLoop.run_in_executor`; use that instead + of this class. """ - def initialize(self, io_loop=None, executor=None, close_executor=True): - self.io_loop = io_loop or IOLoop.current() + def initialize(self, executor=None, close_executor=True): + self.io_loop = IOLoop.current() if executor is not None: self.executor = executor self.close_executor = close_executor @@ -382,16 +412,7 @@ class ExecutorResolver(Resolver): @run_on_executor def resolve(self, host, port, family=socket.AF_UNSPEC): - # On Solaris, getaddrinfo fails if the given port is not found - # in /etc/services and no socket type is given, so we must pass - # one here. The socket type used here doesn't seem to actually - # matter (we discard the one we get back in the results), - # so the addresses we return should still be usable with SOCK_DGRAM. - addrinfo = socket.getaddrinfo(host, port, family, socket.SOCK_STREAM) - results = [] - for family, socktype, proto, canonname, address in addrinfo: - results.append((family, address)) - return results + return _resolve_addr(host, port, family) class BlockingResolver(ExecutorResolver): @@ -399,9 +420,13 @@ class BlockingResolver(ExecutorResolver): The `.IOLoop` will be blocked during the resolution, although the callback will not be run until the next `.IOLoop` iteration. + + .. deprecated:: 5.0 + The default `Resolver` now uses `.IOLoop.run_in_executor`; use that instead + of this class. """ - def initialize(self, io_loop=None): - super(BlockingResolver, self).initialize(io_loop=io_loop) + def initialize(self): + super(BlockingResolver, self).initialize() class ThreadedResolver(ExecutorResolver): @@ -419,14 +444,18 @@ class ThreadedResolver(ExecutorResolver): .. versionchanged:: 3.1 All ``ThreadedResolvers`` share a single thread pool, whose size is set by the first one to be created. + + .. deprecated:: 5.0 + The default `Resolver` now uses `.IOLoop.run_in_executor`; use that instead + of this class. """ _threadpool = None # type: ignore _threadpool_pid = None # type: int - def initialize(self, io_loop=None, num_threads=10): + def initialize(self, num_threads=10): threadpool = ThreadedResolver._create_threadpool(num_threads) super(ThreadedResolver, self).initialize( - io_loop=io_loop, executor=threadpool, close_executor=False) + executor=threadpool, close_executor=False) @classmethod def _create_threadpool(cls, num_threads): @@ -448,7 +477,21 @@ class OverrideResolver(Resolver): This can be used to make local DNS changes (e.g. for testing) without modifying system-wide settings. - The mapping can contain either host strings or host-port pairs. + The mapping can be in three formats:: + + { + # Hostname to host or ip + "example.com": "127.0.1.1", + + # Host+port to host+port + ("login.example.com", 443): ("localhost", 1443), + + # Host+port+address family to host+port + ("login.example.com", 443, socket.AF_INET6): ("::1", 1443), + } + + .. versionchanged:: 5.0 + Added support for host-port-family triplets. """ def initialize(self, resolver, mapping): self.resolver = resolver @@ -457,12 +500,14 @@ class OverrideResolver(Resolver): def close(self): self.resolver.close() - def resolve(self, host, port, *args, **kwargs): - if (host, port) in self.mapping: + def resolve(self, host, port, family=socket.AF_UNSPEC, *args, **kwargs): + if (host, port, family) in self.mapping: + host, port = self.mapping[(host, port, family)] + elif (host, port) in self.mapping: host, port = self.mapping[(host, port)] elif host in self.mapping: host = self.mapping[host] - return self.resolver.resolve(host, port, *args, **kwargs) + return self.resolver.resolve(host, port, family, *args, **kwargs) # These are the keyword arguments to ssl.wrap_socket that must be translated @@ -483,11 +528,12 @@ def ssl_options_to_context(ssl_options): accepts both forms needs to upgrade to the `~ssl.SSLContext` version to use features like SNI or NPN. """ - if isinstance(ssl_options, dict): - assert all(k in _SSL_CONTEXT_KEYWORDS for k in ssl_options), ssl_options - if (not hasattr(ssl, 'SSLContext') or - isinstance(ssl_options, ssl.SSLContext)): + if isinstance(ssl_options, ssl.SSLContext): return ssl_options + assert isinstance(ssl_options, dict) + assert all(k in _SSL_CONTEXT_KEYWORDS for k in ssl_options), ssl_options + # Can't use create_default_context since this interface doesn't + # tell us client vs server. context = ssl.SSLContext( ssl_options.get('ssl_version', ssl.PROTOCOL_SSLv23)) if 'certfile' in ssl_options: @@ -500,7 +546,9 @@ def ssl_options_to_context(ssl_options): context.set_ciphers(ssl_options['ciphers']) if hasattr(ssl, 'OP_NO_COMPRESSION'): # Disable TLS compression to avoid CRIME and related attacks. - # This constant wasn't added until python 3.3. + # This constant depends on openssl version 1.0. + # TODO: Do we need to do this ourselves or can we trust + # the defaults? context.options |= ssl.OP_NO_COMPRESSION return context @@ -515,14 +563,13 @@ def ssl_wrap_socket(socket, ssl_options, server_hostname=None, **kwargs): appropriate). """ context = ssl_options_to_context(ssl_options) - if hasattr(ssl, 'SSLContext') and isinstance(context, ssl.SSLContext): - if server_hostname is not None and getattr(ssl, 'HAS_SNI'): - # Python doesn't have server-side SNI support so we can't - # really unittest this, but it can be manually tested with - # python3.2 -m tornado.httpclient https://sni.velox.ch - return context.wrap_socket(socket, server_hostname=server_hostname, - **kwargs) - else: - return context.wrap_socket(socket, **kwargs) + if ssl.HAS_SNI: + # In python 3.4, wrap_socket only accepts the server_hostname + # argument if HAS_SNI is true. + # TODO: add a unittest (python added server-side SNI support in 3.4) + # In the meantime it can be manually tested with + # python3 -m tornado.httpclient https://sni.velox.ch + return context.wrap_socket(socket, server_hostname=server_hostname, + **kwargs) else: - return ssl.wrap_socket(socket, **dict(context, **kwargs)) # type: ignore + return context.wrap_socket(socket, **kwargs) diff --git a/server/www/packages/packages-common/tornado/options.py b/server/www/packages/packages-common/tornado/options.py index 0a72cc6..0a4b965 100644 --- a/server/www/packages/packages-common/tornado/options.py +++ b/server/www/packages/packages-common/tornado/options.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -16,9 +15,19 @@ """A command line parsing module that lets modules define their own options. -Each module defines its own options which are added to the global -option namespace, e.g.:: +This module is inspired by Google's `gflags +`_. The primary difference +with libraries such as `argparse` is that a global registry is used so +that options may be defined in any module (it also enables +`tornado.log` by default). The rest of Tornado does not depend on this +module, so feel free to use `argparse` or other configuration +libraries if you prefer them. +Options must be defined with `tornado.options.define` before use, +generally at the top level of a module. The options are then +accessible as attributes of `tornado.options.options`:: + + # myapp/db.py from tornado.options import define, options define("mysql_host", default="127.0.0.1:3306", help="Main user DB") @@ -29,34 +38,36 @@ option namespace, e.g.:: db = database.Connection(options.mysql_host) ... + # myapp/server.py + from tornado.options import define, options + + define("port", default=8080, help="port to listen on") + + def start_server(): + app = make_app() + app.listen(options.port) + The ``main()`` method of your application does not need to be aware of all of the options used throughout your program; they are all automatically loaded when the modules are loaded. However, all modules that define options must have been imported before the command line is parsed. Your ``main()`` method can parse the command line or parse a config file with -either:: +either `parse_command_line` or `parse_config_file`:: - tornado.options.parse_command_line() - # or - tornado.options.parse_config_file("/etc/server.conf") + import myapp.db, myapp.server + import tornado.options -.. note: + if __name__ == '__main__': + tornado.options.parse_command_line() + # or + tornado.options.parse_config_file("/etc/server.conf") - When using tornado.options.parse_command_line or - tornado.options.parse_config_file, the only options that are set are - ones that were previously defined with tornado.options.define. +.. note:: -Command line formats are what you would expect (``--myoption=myvalue``). -Config files are just Python files. Global names become options, e.g.:: - - myoption = "myvalue" - myotheroption = "myothervalue" - -We support `datetimes `, `timedeltas -`, ints, and floats (just pass a ``type`` kwarg to -`define`). We also accept multi-value options. See the documentation for -`define()` below. + When using multiple ``parse_*`` functions, pass ``final=False`` to all + but the last one, or side effects may occur twice (in particular, + this can result in log messages being doubled). `tornado.options.options` is a singleton instance of `OptionParser`, and the top-level functions in this module (`define`, `parse_command_line`, etc) @@ -190,13 +201,13 @@ class OptionParser(object): multiple=False, group=None, callback=None): """Defines a new command line option. - If ``type`` is given (one of str, float, int, datetime, or timedelta) - or can be inferred from the ``default``, we parse the command line - arguments based on the given type. If ``multiple`` is True, we accept - comma-separated values, and the option value is always a list. + ``type`` can be any of `str`, `int`, `float`, `bool`, + `~datetime.datetime`, or `~datetime.timedelta`. If no ``type`` + is given but a ``default`` is, ``type`` is the type of + ``default``. Otherwise, ``type`` defaults to `str`. - For multi-value integers, we also accept the syntax ``x:y``, which - turns into ``range(x, y)`` - very useful for long integer ranges. + If ``multiple`` is True, the option value is a list of ``type`` + instead of an instance of ``type``. ``help`` and ``metavar`` are used to construct the automatically generated command line help string. The help @@ -208,9 +219,7 @@ class OptionParser(object): groups. By default, command line options are grouped by the file in which they are defined. - Command line option names must be unique globally. They can be parsed - from the command line with `parse_command_line` or parsed from a - config file with `parse_config_file`. + Command line option names must be unique globally. If a ``callback`` is given, it will be run with the new value whenever the option is changed. This can be used to combine command-line @@ -222,10 +231,12 @@ class OptionParser(object): With this definition, options in the file specified by ``--config`` will override options set earlier on the command line, but can be overridden by later flags. + """ - if name in self._options: + normalized = self._normalize_name(name) + if normalized in self._options: raise Error("Option %r already defined in %s" % - (name, self._options[name].file_name)) + (normalized, self._options[normalized].file_name)) frame = sys._getframe(0) options_file = frame.f_code.co_filename @@ -247,7 +258,6 @@ class OptionParser(object): group_name = group else: group_name = file_name - normalized = self._normalize_name(name) option = _Option(name, file_name=file_name, default=default, type=type, help=help, metavar=metavar, multiple=multiple, @@ -259,6 +269,14 @@ class OptionParser(object): """Parses all options given on the command line (defaults to `sys.argv`). + Options look like ``--option=value`` and are parsed according + to their ``type``. For boolean options, ``--option`` is + equivalent to ``--option=true`` + + If the option has ``multiple=True``, comma-separated values + are accepted. For multi-value integer options, the syntax + ``x:y`` is also accepted and equivalent to ``range(x, y)``. + Note that ``args[0]`` is ignored since it is the program name in `sys.argv`. @@ -267,6 +285,7 @@ class OptionParser(object): If ``final`` is ``False``, parse callbacks will not be run. This is useful for applications that wish to combine configurations from multiple sources. + """ if args is None: args = sys.argv @@ -299,12 +318,39 @@ class OptionParser(object): return remaining def parse_config_file(self, path, final=True): - """Parses and loads the Python config file at the given path. + """Parses and loads the config file at the given path. + + The config file contains Python code that will be executed (so + it is **not safe** to use untrusted config files). Anything in + the global namespace that matches a defined option will be + used to set that option's value. + + Options may either be the specified type for the option or + strings (in which case they will be parsed the same way as in + `.parse_command_line`) + + Example (using the options defined in the top-level docs of + this module):: + + port = 80 + mysql_host = 'mydb.example.com:3306' + # Both lists and comma-separated strings are allowed for + # multiple=True. + memcache_hosts = ['cache1.example.com:11011', + 'cache2.example.com:11011'] + memcache_hosts = 'cache1.example.com:11011,cache2.example.com:11011' If ``final`` is ``False``, parse callbacks will not be run. This is useful for applications that wish to combine configurations from multiple sources. + .. note:: + + `tornado.options` is primarily a command-line library. + Config file support is provided for applications that wish + to use it, but applications that prefer config files may + wish to look at other libraries instead. + .. versionchanged:: 4.1 Config files are now always interpreted as utf-8 instead of the system default encoding. @@ -312,6 +358,10 @@ class OptionParser(object): .. versionchanged:: 4.4 The special variable ``__file__`` is available inside config files, specifying the absolute path to the config file itself. + + .. versionchanged:: 5.1 + Added the ability to set options via strings in config files. + """ config = {'__file__': os.path.abspath(path)} with open(path, 'rb') as f: @@ -319,7 +369,17 @@ class OptionParser(object): for name in config: normalized = self._normalize_name(name) if normalized in self._options: - self._options[normalized].set(config[name]) + option = self._options[normalized] + if option.multiple: + if not isinstance(config[name], (list, str)): + raise Error("Option %r is required to be a list of %s " + "or a comma-separated string" % + (option.name, option.type.__name__)) + + if type(config[name]) == str and option.type != str: + option.parse(config[name]) + else: + option.set(config[name]) if final: self.run_parse_callbacks() diff --git a/server/www/packages/packages-common/tornado/platform/asyncio.py b/server/www/packages/packages-common/tornado/platform/asyncio.py index 830ee1f..e0042e1 100644 --- a/server/www/packages/packages-common/tornado/platform/asyncio.py +++ b/server/www/packages/packages-common/tornado/platform/asyncio.py @@ -3,14 +3,14 @@ .. versionadded:: 3.2 This module integrates Tornado with the ``asyncio`` module introduced -in Python 3.4 (and available `as a separate download -`_ for Python 3.3). This makes -it possible to combine the two libraries on the same event loop. +in Python 3.4. This makes it possible to combine the two libraries on +the same event loop. -Most applications should use `AsyncIOMainLoop` to run Tornado on the -default ``asyncio`` event loop. Applications that need to run event -loops on multiple threads may use `AsyncIOLoop` to create multiple -loops. +.. deprecated:: 5.0 + + While the code in this module is still used, it is now enabled + automatically when `asyncio` is available, so applications should + no longer need to refer to this module directly. .. note:: @@ -22,35 +22,38 @@ loops. from __future__ import absolute_import, division, print_function import functools -import tornado.concurrent from tornado.gen import convert_yielded from tornado.ioloop import IOLoop from tornado import stack_context -try: - # Import the real asyncio module for py33+ first. Older versions of the - # trollius backport also use this name. - import asyncio # type: ignore -except ImportError as e: - # Asyncio itself isn't available; see if trollius is (backport to py26+). - try: - import trollius as asyncio # type: ignore - except ImportError: - # Re-raise the original asyncio error, not the trollius one. - raise e +import asyncio class BaseAsyncIOLoop(IOLoop): - def initialize(self, asyncio_loop, close_loop=False, **kwargs): - super(BaseAsyncIOLoop, self).initialize(**kwargs) + def initialize(self, asyncio_loop, **kwargs): self.asyncio_loop = asyncio_loop - self.close_loop = close_loop # Maps fd to (fileobj, handler function) pair (as in IOLoop.add_handler) self.handlers = {} # Set of fds listening for reads/writes self.readers = set() self.writers = set() self.closing = False + # If an asyncio loop was closed through an asyncio interface + # instead of IOLoop.close(), we'd never hear about it and may + # have left a dangling reference in our map. In case an + # application (or, more likely, a test suite) creates and + # destroys a lot of event loops in this way, check here to + # ensure that we don't have a lot of dead loops building up in + # the map. + # + # TODO(bdarnell): consider making self.asyncio_loop a weakref + # for AsyncIOMainLoop and make _ioloop_for_asyncio a + # WeakKeyDictionary. + for loop in list(IOLoop._ioloop_for_asyncio): + if loop.is_closed(): + del IOLoop._ioloop_for_asyncio[loop] + IOLoop._ioloop_for_asyncio[asyncio_loop] = self + super(BaseAsyncIOLoop, self).initialize(**kwargs) def close(self, all_fds=False): self.closing = True @@ -59,8 +62,13 @@ class BaseAsyncIOLoop(IOLoop): self.remove_handler(fd) if all_fds: self.close_fd(fileobj) - if self.close_loop: - self.asyncio_loop.close() + # Remove the mapping before closing the asyncio loop. If this + # happened in the other order, we could race against another + # initialize() call which would see the closed asyncio loop, + # assume it was closed from the asyncio side, and do this + # cleanup for us, leading to a KeyError. + del IOLoop._ioloop_for_asyncio[self.asyncio_loop] + self.asyncio_loop.close() def add_handler(self, fd, handler, events): fd, fileobj = self.split_fd(fd) @@ -114,16 +122,16 @@ class BaseAsyncIOLoop(IOLoop): handler_func(fileobj, events) def start(self): - old_current = IOLoop.current(instance=False) + try: + old_loop = asyncio.get_event_loop() + except (RuntimeError, AssertionError): + old_loop = None try: self._setup_logging() - self.make_current() + asyncio.set_event_loop(self.asyncio_loop) self.asyncio_loop.run_forever() finally: - if old_current is None: - IOLoop.clear_current() - else: - old_current.make_current() + asyncio.set_event_loop(old_loop) def stop(self): self.asyncio_loop.stop() @@ -140,67 +148,110 @@ class BaseAsyncIOLoop(IOLoop): timeout.cancel() def add_callback(self, callback, *args, **kwargs): - if self.closing: - # TODO: this is racy; we need a lock to ensure that the - # loop isn't closed during call_soon_threadsafe. - raise RuntimeError("IOLoop is closing") - self.asyncio_loop.call_soon_threadsafe( - self._run_callback, - functools.partial(stack_context.wrap(callback), *args, **kwargs)) + try: + self.asyncio_loop.call_soon_threadsafe( + self._run_callback, + functools.partial(stack_context.wrap(callback), *args, **kwargs)) + except RuntimeError: + # "Event loop is closed". Swallow the exception for + # consistency with PollIOLoop (and logical consistency + # with the fact that we can't guarantee that an + # add_callback that completes without error will + # eventually execute). + pass add_callback_from_signal = add_callback + def run_in_executor(self, executor, func, *args): + return self.asyncio_loop.run_in_executor(executor, func, *args) + + def set_default_executor(self, executor): + return self.asyncio_loop.set_default_executor(executor) + class AsyncIOMainLoop(BaseAsyncIOLoop): """``AsyncIOMainLoop`` creates an `.IOLoop` that corresponds to the current ``asyncio`` event loop (i.e. the one returned by - ``asyncio.get_event_loop()``). Recommended usage:: + ``asyncio.get_event_loop()``). - from tornado.platform.asyncio import AsyncIOMainLoop - import asyncio - AsyncIOMainLoop().install() - asyncio.get_event_loop().run_forever() + .. deprecated:: 5.0 - See also :meth:`tornado.ioloop.IOLoop.install` for general notes on - installing alternative IOLoops. + Now used automatically when appropriate; it is no longer necessary + to refer to this class directly. + + .. versionchanged:: 5.0 + + Closing an `AsyncIOMainLoop` now closes the underlying asyncio loop. """ def initialize(self, **kwargs): - super(AsyncIOMainLoop, self).initialize(asyncio.get_event_loop(), - close_loop=False, **kwargs) + super(AsyncIOMainLoop, self).initialize(asyncio.get_event_loop(), **kwargs) + + def make_current(self): + # AsyncIOMainLoop already refers to the current asyncio loop so + # nothing to do here. + pass class AsyncIOLoop(BaseAsyncIOLoop): """``AsyncIOLoop`` is an `.IOLoop` that runs on an ``asyncio`` event loop. This class follows the usual Tornado semantics for creating new ``IOLoops``; these loops are not necessarily related to the - ``asyncio`` default event loop. Recommended usage:: - - from tornado.ioloop import IOLoop - IOLoop.configure('tornado.platform.asyncio.AsyncIOLoop') - IOLoop.current().start() + ``asyncio`` default event loop. Each ``AsyncIOLoop`` creates a new ``asyncio.EventLoop``; this object can be accessed with the ``asyncio_loop`` attribute. + + .. versionchanged:: 5.0 + + When an ``AsyncIOLoop`` becomes the current `.IOLoop`, it also sets + the current `asyncio` event loop. + + .. deprecated:: 5.0 + + Now used automatically when appropriate; it is no longer necessary + to refer to this class directly. """ def initialize(self, **kwargs): + self.is_current = False loop = asyncio.new_event_loop() try: - super(AsyncIOLoop, self).initialize(loop, close_loop=True, **kwargs) + super(AsyncIOLoop, self).initialize(loop, **kwargs) except Exception: # If initialize() does not succeed (taking ownership of the loop), # we have to close it. loop.close() raise + def close(self, all_fds=False): + if self.is_current: + self.clear_current() + super(AsyncIOLoop, self).close(all_fds=all_fds) + + def make_current(self): + if not self.is_current: + try: + self.old_asyncio = asyncio.get_event_loop() + except (RuntimeError, AssertionError): + self.old_asyncio = None + self.is_current = True + asyncio.set_event_loop(self.asyncio_loop) + + def _clear_current_hook(self): + if self.is_current: + asyncio.set_event_loop(self.old_asyncio) + self.is_current = False + def to_tornado_future(asyncio_future): """Convert an `asyncio.Future` to a `tornado.concurrent.Future`. .. versionadded:: 4.1 + + .. deprecated:: 5.0 + Tornado ``Futures`` have been merged with `asyncio.Future`, + so this method is now a no-op. """ - tf = tornado.concurrent.Future() - tornado.concurrent.chain_future(asyncio_future, tf) - return tf + return asyncio_future def to_asyncio_future(tornado_future): @@ -211,12 +262,38 @@ def to_asyncio_future(tornado_future): .. versionchanged:: 4.3 Now accepts any yieldable object, not just `tornado.concurrent.Future`. + + .. deprecated:: 5.0 + Tornado ``Futures`` have been merged with `asyncio.Future`, + so this method is now equivalent to `tornado.gen.convert_yielded`. """ - tornado_future = convert_yielded(tornado_future) - af = asyncio.Future() - tornado.concurrent.chain_future(tornado_future, af) - return af + return convert_yielded(tornado_future) -if hasattr(convert_yielded, 'register'): - convert_yielded.register(asyncio.Future, to_tornado_future) # type: ignore +class AnyThreadEventLoopPolicy(asyncio.DefaultEventLoopPolicy): + """Event loop policy that allows loop creation on any thread. + + The default `asyncio` event loop policy only automatically creates + event loops in the main threads. Other threads must create event + loops explicitly or `asyncio.get_event_loop` (and therefore + `.IOLoop.current`) will fail. Installing this policy allows event + loops to be created automatically on any thread, matching the + behavior of Tornado versions prior to 5.0 (or 5.0 on Python 2). + + Usage:: + + asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy()) + + .. versionadded:: 5.0 + + """ + def get_event_loop(self): + try: + return super().get_event_loop() + except (RuntimeError, AssertionError): + # This was an AssertionError in python 3.4.2 (which ships with debian jessie) + # and changed to a RuntimeError in 3.4.3. + # "There is no current event loop in thread %r" + loop = self.new_event_loop() + self.set_event_loop(loop) + return loop diff --git a/server/www/packages/packages-common/tornado/platform/auto.py b/server/www/packages/packages-common/tornado/platform/auto.py index 1f4d700..1a9133f 100644 --- a/server/www/packages/packages-common/tornado/platform/auto.py +++ b/server/www/packages/packages-common/tornado/platform/auto.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2011 Facebook # diff --git a/server/www/packages/packages-common/tornado/platform/caresresolver.py b/server/www/packages/packages-common/tornado/platform/caresresolver.py index fd6e9d2..768cb62 100644 --- a/server/www/packages/packages-common/tornado/platform/caresresolver.py +++ b/server/www/packages/packages-common/tornado/platform/caresresolver.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, division, print_function import pycares # type: ignore import socket +from tornado.concurrent import Future from tornado import gen from tornado.ioloop import IOLoop from tornado.netutil import Resolver, is_valid_ip @@ -19,11 +20,11 @@ class CaresResolver(Resolver): the default for ``tornado.simple_httpclient``, but other libraries may default to ``AF_UNSPEC``. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def initialize(self, io_loop=None): - self.io_loop = io_loop or IOLoop.current() + def initialize(self): + self.io_loop = IOLoop.current() self.channel = pycares.Channel(sock_state_cb=self._sock_state_cb) self.fds = {} @@ -55,11 +56,10 @@ class CaresResolver(Resolver): addresses = [host] else: # gethostbyname doesn't take callback as a kwarg - self.channel.gethostbyname(host, family, (yield gen.Callback(1))) - callback_args = yield gen.Wait(1) - assert isinstance(callback_args, gen.Arguments) - assert not callback_args.kwargs - result, error = callback_args.args + fut = Future() + self.channel.gethostbyname(host, family, + lambda result, error: fut.set_result((result, error))) + result, error = yield fut if error: raise IOError('C-Ares returned error %s: %s while resolving %s' % (error, pycares.errno.strerror(error), host)) diff --git a/server/www/packages/packages-common/tornado/platform/common.py b/server/www/packages/packages-common/tornado/platform/common.py index a73f8db..b597748 100644 --- a/server/www/packages/packages-common/tornado/platform/common.py +++ b/server/www/packages/packages-common/tornado/platform/common.py @@ -32,10 +32,12 @@ class Waker(interface.Waker): and Jython. """ def __init__(self): + from .auto import set_close_exec # Based on Zope select_trigger.py: # https://github.com/zopefoundation/Zope/blob/master/src/ZServer/medusa/thread/select_trigger.py self.writer = socket.socket() + set_close_exec(self.writer.fileno()) # Disable buffering -- pulling the trigger sends 1 byte, # and we want that sent immediately, to wake up ASAP. self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) @@ -54,6 +56,7 @@ class Waker(interface.Waker): # http://mail.zope.org/pipermail/zope/2005-July/160433.html # for hideous details. a = socket.socket() + set_close_exec(a.fileno()) a.bind(("127.0.0.1", 0)) a.listen(1) connect_address = a.getsockname() # assigned (host, port) pair @@ -78,6 +81,7 @@ class Waker(interface.Waker): a.close() self.reader, addr = a.accept() + set_close_exec(self.reader.fileno()) self.reader.setblocking(0) self.writer.setblocking(0) a.close() diff --git a/server/www/packages/packages-common/tornado/platform/epoll.py b/server/www/packages/packages-common/tornado/platform/epoll.py index 80bfd8a..4e34617 100644 --- a/server/www/packages/packages-common/tornado/platform/epoll.py +++ b/server/www/packages/packages-common/tornado/platform/epoll.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2012 Facebook # diff --git a/server/www/packages/packages-common/tornado/platform/interface.py b/server/www/packages/packages-common/tornado/platform/interface.py index c0ef290..cac5326 100644 --- a/server/www/packages/packages-common/tornado/platform/interface.py +++ b/server/www/packages/packages-common/tornado/platform/interface.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2011 Facebook # diff --git a/server/www/packages/packages-common/tornado/platform/kqueue.py b/server/www/packages/packages-common/tornado/platform/kqueue.py index 3a5d417..4e0aee0 100644 --- a/server/www/packages/packages-common/tornado/platform/kqueue.py +++ b/server/www/packages/packages-common/tornado/platform/kqueue.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2012 Facebook # diff --git a/server/www/packages/packages-common/tornado/platform/posix.py b/server/www/packages/packages-common/tornado/platform/posix.py index 9bf1f18..6fe1fa8 100644 --- a/server/www/packages/packages-common/tornado/platform/posix.py +++ b/server/www/packages/packages-common/tornado/platform/posix.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2011 Facebook # diff --git a/server/www/packages/packages-common/tornado/platform/select.py b/server/www/packages/packages-common/tornado/platform/select.py index a18049f..14e8a47 100644 --- a/server/www/packages/packages-common/tornado/platform/select.py +++ b/server/www/packages/packages-common/tornado/platform/select.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2012 Facebook # diff --git a/server/www/packages/packages-common/tornado/platform/twisted.py b/server/www/packages/packages-common/tornado/platform/twisted.py index 0f9787e..b38a755 100644 --- a/server/www/packages/packages-common/tornado/platform/twisted.py +++ b/server/www/packages/packages-common/tornado/platform/twisted.py @@ -32,7 +32,7 @@ import sys import twisted.internet.abstract # type: ignore from twisted.internet.defer import Deferred # type: ignore from twisted.internet.posixbase import PosixReactorBase # type: ignore -from twisted.internet.interfaces import IReactorFDSet, IDelayedCall, IReactorTime, IReadDescriptor, IWriteDescriptor # type: ignore +from twisted.internet.interfaces import IReactorFDSet, IDelayedCall, IReactorTime, IReadDescriptor, IWriteDescriptor # type: ignore # noqa: E501 from twisted.python import failure, log # type: ignore from twisted.internet import error # type: ignore import twisted.names.cache # type: ignore @@ -42,7 +42,7 @@ import twisted.names.resolve # type: ignore from zope.interface import implementer # type: ignore -from tornado.concurrent import Future +from tornado.concurrent import Future, future_set_exc_info from tornado.escape import utf8 from tornado import gen import tornado.ioloop @@ -112,7 +112,7 @@ class TornadoReactor(PosixReactorBase): instead of ``reactor.run()``. It is also possible to create a non-global reactor by calling - ``tornado.platform.twisted.TornadoReactor(io_loop)``. However, if + ``tornado.platform.twisted.TornadoReactor()``. However, if the `.IOLoop` and reactor are to be short-lived (such as those used in unit tests), additional cleanup may be required. Specifically, it is recommended to call:: @@ -122,13 +122,18 @@ class TornadoReactor(PosixReactorBase): before closing the `.IOLoop`. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + + .. deprecated:: 5.1 + + This class will be removed in Tornado 6.0. Use + ``twisted.internet.asyncioreactor.AsyncioSelectorReactor`` + instead. + """ - def __init__(self, io_loop=None): - if not io_loop: - io_loop = tornado.ioloop.IOLoop.current() - self._io_loop = io_loop + def __init__(self): + self._io_loop = tornado.ioloop.IOLoop.current() self._readers = {} # map of reader objects to fd self._writers = {} # map of writer objects to fd self._fds = {} # a map of fd to a (reader, writer) tuple @@ -319,7 +324,10 @@ class _TestReactor(TornadoReactor): """ def __init__(self): # always use a new ioloop - super(_TestReactor, self).__init__(IOLoop()) + IOLoop.clear_current() + IOLoop(make_current=True) + super(_TestReactor, self).__init__() + IOLoop.clear_current() def listenTCP(self, port, factory, backlog=50, interface=''): # default to localhost to avoid firewall prompts on the mac @@ -335,7 +343,7 @@ class _TestReactor(TornadoReactor): port, protocol, interface=interface, maxPacketSize=maxPacketSize) -def install(io_loop=None): +def install(): """Install this package as the default Twisted reactor. ``install()`` must be called very early in the startup process, @@ -346,13 +354,15 @@ def install(io_loop=None): in multi-process mode, and an external process manager such as ``supervisord`` is recommended instead. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + .. deprecated:: 5.1 + + This functio will be removed in Tornado 6.0. Use + ``twisted.internet.asyncioreactor.install`` instead. """ - if not io_loop: - io_loop = tornado.ioloop.IOLoop.current() - reactor = TornadoReactor(io_loop) + reactor = TornadoReactor() from twisted.internet.main import installReactor # type: ignore installReactor(reactor) return reactor @@ -384,6 +394,8 @@ class _FD(object): self.handler(self.fileobj, tornado.ioloop.IOLoop.ERROR) self.lost = True + writeConnectionLost = readConnectionLost = connectionLost + def logPrefix(self): return '' @@ -410,6 +422,11 @@ class TwistedIOLoop(tornado.ioloop.IOLoop): See also :meth:`tornado.ioloop.IOLoop.install` for general notes on installing alternative IOLoops. + + .. deprecated:: 5.1 + + The `asyncio` event loop will be the only available implementation in + Tornado 6.0. """ def initialize(self, reactor=None, **kwargs): super(TwistedIOLoop, self).initialize(**kwargs) @@ -519,21 +536,20 @@ class TwistedResolver(Resolver): recommended only when threads cannot be used, since it has limitations compared to the standard ``getaddrinfo``-based `~tornado.netutil.Resolver` and - `~tornado.netutil.ThreadedResolver`. Specifically, it returns at + `~tornado.netutil.DefaultExecutorResolver`. Specifically, it returns at most one result, and arguments other than ``host`` and ``family`` are ignored. It may fail to resolve when ``family`` is not ``socket.AF_UNSPEC``. Requires Twisted 12.1 or newer. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def initialize(self, io_loop=None): - self.io_loop = io_loop or IOLoop.current() + def initialize(self): # partial copy of twisted.names.client.createResolver, which doesn't # allow for a reactor to be passed in. - self.reactor = tornado.platform.twisted.TornadoReactor(io_loop) + self.reactor = tornado.platform.twisted.TornadoReactor() host_resolver = twisted.names.hosts.Resolver('/etc/hosts') cache_resolver = twisted.names.cache.CacheResolver(reactor=self.reactor) @@ -554,7 +570,9 @@ class TwistedResolver(Resolver): resolved_family = socket.AF_INET6 else: deferred = self.resolver.getHostByName(utf8(host)) - resolved = yield gen.Task(deferred.addBoth) + fut = Future() + deferred.addBoth(fut.set_result) + resolved = yield fut if isinstance(resolved, failure.Failure): try: resolved.raiseException() @@ -586,6 +604,6 @@ if hasattr(gen.convert_yielded, 'register'): # Should never happen, but just in case raise Exception("errback called without error") except: - f.set_exc_info(sys.exc_info()) + future_set_exc_info(f, sys.exc_info()) d.addCallbacks(f.set_result, errback) return f diff --git a/server/www/packages/packages-common/tornado/platform/windows.py b/server/www/packages/packages-common/tornado/platform/windows.py index e94a0cf..4127700 100644 --- a/server/www/packages/packages-common/tornado/platform/windows.py +++ b/server/www/packages/packages-common/tornado/platform/windows.py @@ -8,7 +8,7 @@ import ctypes.wintypes # type: ignore # See: http://msdn.microsoft.com/en-us/library/ms724935(VS.85).aspx SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation -SetHandleInformation.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD) +SetHandleInformation.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD) # noqa: E501 SetHandleInformation.restype = ctypes.wintypes.BOOL HANDLE_FLAG_INHERIT = 0x00000001 diff --git a/server/www/packages/packages-common/tornado/process.py b/server/www/packages/packages-common/tornado/process.py index fae94f3..122fd7e 100644 --- a/server/www/packages/packages-common/tornado/process.py +++ b/server/www/packages/packages-common/tornado/process.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2011 Facebook # @@ -29,7 +28,7 @@ import time from binascii import hexlify -from tornado.concurrent import Future +from tornado.concurrent import Future, future_set_result_unless_cancelled from tornado import ioloop from tornado.iostream import PipeIOStream from tornado.log import gen_log @@ -126,10 +125,6 @@ def fork_processes(num_processes, max_restarts=100): assert _task_id is None if num_processes is None or num_processes <= 0: num_processes = cpu_count() - if ioloop.IOLoop.initialized(): - raise RuntimeError("Cannot run in multiple processes: IOLoop instance " - "has already been initialized. You cannot call " - "IOLoop.instance() before calling start_processes()") gen_log.info("Starting %d processes", num_processes) children = {} @@ -199,16 +194,17 @@ class Subprocess(object): * ``stdin``, ``stdout``, and ``stderr`` may have the value ``tornado.process.Subprocess.STREAM``, which will make the corresponding - attribute of the resulting Subprocess a `.PipeIOStream`. - * A new keyword argument ``io_loop`` may be used to pass in an IOLoop. + attribute of the resulting Subprocess a `.PipeIOStream`. If this option + is used, the caller is responsible for closing the streams when done + with them. The ``Subprocess.STREAM`` option and the ``set_exit_callback`` and ``wait_for_exit`` methods do not work on Windows. There is therefore no reason to use this class instead of ``subprocess.Popen`` on that platform. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ STREAM = object() @@ -217,7 +213,7 @@ class Subprocess(object): _waiting = {} # type: ignore def __init__(self, *args, **kwargs): - self.io_loop = kwargs.pop('io_loop', None) or ioloop.IOLoop.current() + self.io_loop = ioloop.IOLoop.current() # All FDs we create should be closed on error; those in to_close # should be closed in the parent process on success. pipe_fds = [] @@ -227,19 +223,19 @@ class Subprocess(object): kwargs['stdin'] = in_r pipe_fds.extend((in_r, in_w)) to_close.append(in_r) - self.stdin = PipeIOStream(in_w, io_loop=self.io_loop) + self.stdin = PipeIOStream(in_w) if kwargs.get('stdout') is Subprocess.STREAM: out_r, out_w = _pipe_cloexec() kwargs['stdout'] = out_w pipe_fds.extend((out_r, out_w)) to_close.append(out_w) - self.stdout = PipeIOStream(out_r, io_loop=self.io_loop) + self.stdout = PipeIOStream(out_r) if kwargs.get('stderr') is Subprocess.STREAM: err_r, err_w = _pipe_cloexec() kwargs['stderr'] = err_w pipe_fds.extend((err_r, err_w)) to_close.append(err_w) - self.stderr = PipeIOStream(err_r, io_loop=self.io_loop) + self.stderr = PipeIOStream(err_r) try: self.proc = subprocess.Popen(*args, **kwargs) except: @@ -270,7 +266,7 @@ class Subprocess(object): signal handler is causing a problem. """ self._exit_callback = stack_context.wrap(callback) - Subprocess.initialize(self.io_loop) + Subprocess.initialize() Subprocess._waiting[self.pid] = self Subprocess._try_cleanup_process(self.pid) @@ -297,12 +293,12 @@ class Subprocess(object): # Unfortunately we don't have the original args any more. future.set_exception(CalledProcessError(ret, None)) else: - future.set_result(ret) + future_set_result_unless_cancelled(future, ret) self.set_exit_callback(callback) return future @classmethod - def initialize(cls, io_loop=None): + def initialize(cls): """Initializes the ``SIGCHLD`` handler. The signal handler is run on an `.IOLoop` to avoid locking issues. @@ -310,13 +306,13 @@ class Subprocess(object): same one used by individual Subprocess objects (as long as the ``IOLoops`` are each running in separate threads). - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been + removed. """ if cls._initialized: return - if io_loop is None: - io_loop = ioloop.IOLoop.current() + io_loop = ioloop.IOLoop.current() cls._old_sigchld = signal.signal( signal.SIGCHLD, lambda sig, frame: io_loop.add_callback_from_signal(cls._cleanup)) diff --git a/server/www/packages/packages-common/tornado/queues.py b/server/www/packages/packages-common/tornado/queues.py index 0041a80..7cb96bf 100644 --- a/server/www/packages/packages-common/tornado/queues.py +++ b/server/www/packages/packages-common/tornado/queues.py @@ -12,7 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. -"""Asynchronous queues for coroutines. +"""Asynchronous queues for coroutines. These classes are very similar +to those provided in the standard library's `asyncio package +`_. .. warning:: @@ -20,6 +22,7 @@ are *not* thread-safe. To use these queues from another thread, use `.IOLoop.add_callback` to transfer control to the `.IOLoop` thread before calling any queue methods. + """ from __future__ import absolute_import, division, print_function @@ -28,7 +31,7 @@ import collections import heapq from tornado import gen, ioloop -from tornado.concurrent import Future +from tornado.concurrent import Future, future_set_result_unless_cancelled from tornado.locks import Event __all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty'] @@ -47,7 +50,8 @@ class QueueFull(Exception): def _set_timeout(future, timeout): if timeout: def on_timeout(): - future.set_exception(gen.TimeoutError()) + if not future.done(): + future.set_exception(gen.TimeoutError()) io_loop = ioloop.IOLoop.current() timeout_handle = io_loop.add_timeout(timeout, on_timeout) future.add_done_callback( @@ -75,28 +79,24 @@ class Queue(object): q = Queue(maxsize=2) - @gen.coroutine - def consumer(): - while True: - item = yield q.get() + async def consumer(): + async for item in q: try: print('Doing work on %s' % item) - yield gen.sleep(0.01) + await gen.sleep(0.01) finally: q.task_done() - @gen.coroutine - def producer(): + async def producer(): for item in range(5): - yield q.put(item) + await q.put(item) print('Put %s' % item) - @gen.coroutine - def main(): + async def main(): # Start consumer without waiting (since it never finishes). IOLoop.current().spawn_callback(consumer) - yield producer() # Wait for producer to put all tasks. - yield q.join() # Wait for consumer to finish all tasks. + await producer() # Wait for producer to put all tasks. + await q.join() # Wait for consumer to finish all tasks. print('Done') IOLoop.current().run_sync(main) @@ -115,11 +115,14 @@ class Queue(object): Doing work on 4 Done - In Python 3.5, `Queue` implements the async iterator protocol, so - ``consumer()`` could be rewritten as:: - async def consumer(): - async for item in q: + In versions of Python without native coroutines (before 3.5), + ``consumer()`` could be written as:: + + @gen.coroutine + def consumer(): + while True: + item = yield q.get() try: print('Doing work on %s' % item) yield gen.sleep(0.01) @@ -166,18 +169,23 @@ class Queue(object): def put(self, item, timeout=None): """Put an item into the queue, perhaps waiting until there is room. - Returns a Future, which raises `tornado.gen.TimeoutError` after a + Returns a Future, which raises `tornado.util.TimeoutError` after a timeout. + + ``timeout`` may be a number denoting a time (on the same + scale as `tornado.ioloop.IOLoop.time`, normally `time.time`), or a + `datetime.timedelta` object for a deadline relative to the + current time. """ + future = Future() try: self.put_nowait(item) except QueueFull: - future = Future() self._putters.append((item, future)) _set_timeout(future, timeout) - return future else: - return gen._null_future + future.set_result(None) + return future def put_nowait(self, item): """Put an item into the queue without blocking. @@ -189,7 +197,7 @@ class Queue(object): assert self.empty(), "queue non-empty, why are getters waiting?" getter = self._getters.popleft() self.__put_internal(item) - getter.set_result(self._get()) + future_set_result_unless_cancelled(getter, self._get()) elif self.full(): raise QueueFull else: @@ -199,7 +207,12 @@ class Queue(object): """Remove and return an item from the queue. Returns a Future which resolves once an item is available, or raises - `tornado.gen.TimeoutError` after a timeout. + `tornado.util.TimeoutError` after a timeout. + + ``timeout`` may be a number denoting a time (on the same + scale as `tornado.ioloop.IOLoop.time`, normally `time.time`), or a + `datetime.timedelta` object for a deadline relative to the + current time. """ future = Future() try: @@ -220,7 +233,7 @@ class Queue(object): assert self.full(), "queue not full, why are putters waiting?" item, putter = self._putters.popleft() self.__put_internal(item) - putter.set_result(None) + future_set_result_unless_cancelled(putter, None) return self._get() elif self.qsize(): return self._get() @@ -248,12 +261,11 @@ class Queue(object): def join(self, timeout=None): """Block until all items in the queue are processed. - Returns a Future, which raises `tornado.gen.TimeoutError` after a + Returns a Future, which raises `tornado.util.TimeoutError` after a timeout. """ return self._finished.wait(timeout) - @gen.coroutine def __aiter__(self): return _QueueIterator(self) diff --git a/server/www/packages/packages-common/tornado/routing.py b/server/www/packages/packages-common/tornado/routing.py index 6762dc0..e56d1a7 100644 --- a/server/www/packages/packages-common/tornado/routing.py +++ b/server/www/packages/packages-common/tornado/routing.py @@ -242,6 +242,11 @@ class _RoutingDelegate(httputil.HTTPMessageDelegate): start_line=start_line, headers=headers) self.delegate = self.router.find_handler(request) + if self.delegate is None: + app_log.debug("Delegate for %s %s request not found", + start_line.method, start_line.path) + self.delegate = _DefaultMessageDelegate(self.request_conn) + return self.delegate.headers_received(start_line, headers) def data_received(self, chunk): @@ -254,6 +259,16 @@ class _RoutingDelegate(httputil.HTTPMessageDelegate): self.delegate.on_connection_close() +class _DefaultMessageDelegate(httputil.HTTPMessageDelegate): + def __init__(self, connection): + self.connection = connection + + def finish(self): + self.connection.write_headers( + httputil.ResponseStartLine("HTTP/1.1", 404, "Not Found"), httputil.HTTPHeaders()) + self.connection.finish() + + class RuleRouter(Router): """Rule-based router implementation.""" @@ -278,7 +293,8 @@ class RuleRouter(Router): ]) In the examples above, ``Target`` can be a nested `Router` instance, an instance of - `~.httputil.HTTPServerConnectionDelegate` or an old-style callable, accepting a request argument. + `~.httputil.HTTPServerConnectionDelegate` or an old-style callable, + accepting a request argument. :arg rules: a list of `Rule` instances or tuples of `Rule` constructor arguments. @@ -567,7 +583,7 @@ class PathMatches(Matcher): else: try: unescaped_fragment = re_unescape(fragment) - except ValueError as exc: + except ValueError: # If we can't unescape part of it, we can't # reverse this url. return (None, None) @@ -589,7 +605,7 @@ class URLSpec(Rule): * ``pattern``: Regular expression to be matched. Any capturing groups in the regex will be passed in to the handler's get/post/etc methods as arguments (by keyword if named, by - position if unnamed. Named and unnamed capturing groups may + position if unnamed. Named and unnamed capturing groups may not be mixed in the same rule). * ``handler``: `~.web.RequestHandler` subclass to be invoked. diff --git a/server/www/packages/packages-common/tornado/simple_httpclient.py b/server/www/packages/packages-common/tornado/simple_httpclient.py index 8fb7070..60b7956 100644 --- a/server/www/packages/packages-common/tornado/simple_httpclient.py +++ b/server/www/packages/packages-common/tornado/simple_httpclient.py @@ -1,11 +1,11 @@ -#!/usr/bin/env python from __future__ import absolute_import, division, print_function -from tornado.escape import utf8, _unicode +from tornado.escape import _unicode from tornado import gen from tornado.httpclient import HTTPResponse, HTTPError, AsyncHTTPClient, main, _RequestProxy from tornado import httputil from tornado.http1connection import HTTP1Connection, HTTP1ConnectionParameters +from tornado.ioloop import IOLoop from tornado.iostream import StreamClosedError from tornado.netutil import Resolver, OverrideResolver, _client_ssl_defaults from tornado.log import gen_log @@ -20,6 +20,7 @@ import functools import re import socket import sys +import time from io import BytesIO @@ -34,17 +35,38 @@ except ImportError: # ssl is not available on Google App Engine. ssl = None -try: - import certifi -except ImportError: - certifi = None + +class HTTPTimeoutError(HTTPError): + """Error raised by SimpleAsyncHTTPClient on timeout. + + For historical reasons, this is a subclass of `.HTTPClientError` + which simulates a response code of 599. + + .. versionadded:: 5.1 + """ + def __init__(self, message): + super(HTTPTimeoutError, self).__init__(599, message=message) + + def __str__(self): + return self.message -def _default_ca_certs(): - if certifi is None: - raise Exception("The 'certifi' package is required to use https " - "in simple_httpclient") - return certifi.where() +class HTTPStreamClosedError(HTTPError): + """Error raised by SimpleAsyncHTTPClient when the underlying stream is closed. + + When a more specific exception is available (such as `ConnectionResetError`), + it may be raised instead of this one. + + For historical reasons, this is a subclass of `.HTTPClientError` + which simulates a response code of 599. + + .. versionadded:: 5.1 + """ + def __init__(self, message): + super(HTTPStreamClosedError, self).__init__(599, message=message) + + def __str__(self): + return self.message class SimpleAsyncHTTPClient(AsyncHTTPClient): @@ -56,7 +78,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): are not reused, and callers cannot select the network interface to be used. """ - def initialize(self, io_loop, max_clients=10, + def initialize(self, max_clients=10, hostname_mapping=None, max_buffer_size=104857600, resolver=None, defaults=None, max_header_size=None, max_body_size=None): @@ -92,8 +114,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): .. versionchanged:: 4.2 Added the ``max_body_size`` argument. """ - super(SimpleAsyncHTTPClient, self).initialize(io_loop, - defaults=defaults) + super(SimpleAsyncHTTPClient, self).initialize(defaults=defaults) self.max_clients = max_clients self.queue = collections.deque() self.active = {} @@ -107,12 +128,12 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): self.resolver = resolver self.own_resolver = False else: - self.resolver = Resolver(io_loop=io_loop) + self.resolver = Resolver() self.own_resolver = True if hostname_mapping is not None: self.resolver = OverrideResolver(resolver=self.resolver, mapping=hostname_mapping) - self.tcp_client = TCPClient(resolver=self.resolver, io_loop=io_loop) + self.tcp_client = TCPClient(resolver=self.resolver) def close(self): super(SimpleAsyncHTTPClient, self).close() @@ -153,7 +174,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): def _handle_request(self, request, release_callback, final_callback): self._connection_class()( - self.io_loop, self, request, release_callback, + self, request, release_callback, final_callback, self.max_buffer_size, self.tcp_client, self.max_header_size, self.max_body_size) @@ -181,7 +202,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): error_message = "Timeout {0}".format(info) if info else "Timeout" timeout_response = HTTPResponse( - request, 599, error=HTTPError(599, error_message), + request, 599, error=HTTPTimeoutError(error_message), request_time=self.io_loop.time() - request.start_time) self.io_loop.add_callback(callback, timeout_response) del self.waiting[key] @@ -190,11 +211,12 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): class _HTTPConnection(httputil.HTTPMessageDelegate): _SUPPORTED_METHODS = set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]) - def __init__(self, io_loop, client, request, release_callback, + def __init__(self, client, request, release_callback, final_callback, max_buffer_size, tcp_client, max_header_size, max_body_size): - self.start_time = io_loop.time() - self.io_loop = io_loop + self.io_loop = IOLoop.current() + self.start_time = self.io_loop.time() + self.start_wall_time = time.time() self.client = client self.request = request self.release_callback = release_callback @@ -210,7 +232,11 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): # Timeout handle returned by IOLoop.add_timeout self._timeout = None self._sockaddr = None - with stack_context.ExceptionStackContext(self._handle_exception): + IOLoop.current().add_callback(self.run) + + @gen.coroutine + def run(self): + try: self.parsed = urlparse.urlsplit(_unicode(self.request.url)) if self.parsed.scheme not in ("http", "https"): raise ValueError("Unsupported url scheme: %s" % @@ -228,7 +254,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): host = host[1:-1] self.parsed_hostname = host # save final host for _on_connect - if request.allow_ipv6 is False: + if self.request.allow_ipv6 is False: af = socket.AF_INET else: af = socket.AF_UNSPEC @@ -240,10 +266,93 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): self._timeout = self.io_loop.add_timeout( self.start_time + timeout, stack_context.wrap(functools.partial(self._on_timeout, "while connecting"))) - self.tcp_client.connect(host, port, af=af, - ssl_options=ssl_options, - max_buffer_size=self.max_buffer_size, - callback=self._on_connect) + stream = yield self.tcp_client.connect( + host, port, af=af, + ssl_options=ssl_options, + max_buffer_size=self.max_buffer_size) + + if self.final_callback is None: + # final_callback is cleared if we've hit our timeout. + stream.close() + return + self.stream = stream + self.stream.set_close_callback(self.on_connection_close) + self._remove_timeout() + if self.final_callback is None: + return + if self.request.request_timeout: + self._timeout = self.io_loop.add_timeout( + self.start_time + self.request.request_timeout, + stack_context.wrap(functools.partial(self._on_timeout, "during request"))) + if (self.request.method not in self._SUPPORTED_METHODS and + not self.request.allow_nonstandard_methods): + raise KeyError("unknown method %s" % self.request.method) + for key in ('network_interface', + 'proxy_host', 'proxy_port', + 'proxy_username', 'proxy_password', + 'proxy_auth_mode'): + if getattr(self.request, key, None): + raise NotImplementedError('%s not supported' % key) + if "Connection" not in self.request.headers: + self.request.headers["Connection"] = "close" + if "Host" not in self.request.headers: + if '@' in self.parsed.netloc: + self.request.headers["Host"] = self.parsed.netloc.rpartition('@')[-1] + else: + self.request.headers["Host"] = self.parsed.netloc + username, password = None, None + if self.parsed.username is not None: + username, password = self.parsed.username, self.parsed.password + elif self.request.auth_username is not None: + username = self.request.auth_username + password = self.request.auth_password or '' + if username is not None: + if self.request.auth_mode not in (None, "basic"): + raise ValueError("unsupported auth_mode %s", + self.request.auth_mode) + self.request.headers["Authorization"] = ( + b"Basic " + base64.b64encode( + httputil.encode_username_password(username, password))) + if self.request.user_agent: + self.request.headers["User-Agent"] = self.request.user_agent + if not self.request.allow_nonstandard_methods: + # Some HTTP methods nearly always have bodies while others + # almost never do. Fail in this case unless the user has + # opted out of sanity checks with allow_nonstandard_methods. + body_expected = self.request.method in ("POST", "PATCH", "PUT") + body_present = (self.request.body is not None or + self.request.body_producer is not None) + if ((body_expected and not body_present) or + (body_present and not body_expected)): + raise ValueError( + 'Body must %sbe None for method %s (unless ' + 'allow_nonstandard_methods is true)' % + ('not ' if body_expected else '', self.request.method)) + if self.request.expect_100_continue: + self.request.headers["Expect"] = "100-continue" + if self.request.body is not None: + # When body_producer is used the caller is responsible for + # setting Content-Length (or else chunked encoding will be used). + self.request.headers["Content-Length"] = str(len( + self.request.body)) + if (self.request.method == "POST" and + "Content-Type" not in self.request.headers): + self.request.headers["Content-Type"] = "application/x-www-form-urlencoded" + if self.request.decompress_response: + self.request.headers["Accept-Encoding"] = "gzip" + req_path = ((self.parsed.path or '/') + + (('?' + self.parsed.query) if self.parsed.query else '')) + self.connection = self._create_connection(stream) + start_line = httputil.RequestStartLine(self.request.method, + req_path, '') + self.connection.write_headers(start_line, self.request.headers) + if self.request.expect_100_continue: + yield self.connection.read_response(self) + else: + yield self._write_body(True) + except Exception: + if not self._handle_exception(*sys.exc_info()): + raise def _get_ssl_options(self, scheme): if scheme == "https": @@ -256,142 +365,39 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): self.request.client_cert is None and self.request.client_key is None): return _client_ssl_defaults - ssl_options = {} - if self.request.validate_cert: - ssl_options["cert_reqs"] = ssl.CERT_REQUIRED - if self.request.ca_certs is not None: - ssl_options["ca_certs"] = self.request.ca_certs - elif not hasattr(ssl, 'create_default_context'): - # When create_default_context is present, - # we can omit the "ca_certs" parameter entirely, - # which avoids the dependency on "certifi" for py34. - ssl_options["ca_certs"] = _default_ca_certs() - if self.request.client_key is not None: - ssl_options["keyfile"] = self.request.client_key + ssl_ctx = ssl.create_default_context( + ssl.Purpose.SERVER_AUTH, + cafile=self.request.ca_certs) + if not self.request.validate_cert: + ssl_ctx.check_hostname = False + ssl_ctx.verify_mode = ssl.CERT_NONE if self.request.client_cert is not None: - ssl_options["certfile"] = self.request.client_cert - - # SSL interoperability is tricky. We want to disable - # SSLv2 for security reasons; it wasn't disabled by default - # until openssl 1.0. The best way to do this is to use - # the SSL_OP_NO_SSLv2, but that wasn't exposed to python - # until 3.2. Python 2.7 adds the ciphers argument, which - # can also be used to disable SSLv2. As a last resort - # on python 2.6, we set ssl_version to TLSv1. This is - # more narrow than we'd like since it also breaks - # compatibility with servers configured for SSLv3 only, - # but nearly all servers support both SSLv3 and TLSv1: - # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html - if sys.version_info >= (2, 7): - # In addition to disabling SSLv2, we also exclude certain - # classes of insecure ciphers. - ssl_options["ciphers"] = "DEFAULT:!SSLv2:!EXPORT:!DES" - else: - # This is really only necessary for pre-1.0 versions - # of openssl, but python 2.6 doesn't expose version - # information. - ssl_options["ssl_version"] = ssl.PROTOCOL_TLSv1 - return ssl_options + ssl_ctx.load_cert_chain(self.request.client_cert, + self.request.client_key) + if hasattr(ssl, 'OP_NO_COMPRESSION'): + # See netutil.ssl_options_to_context + ssl_ctx.options |= ssl.OP_NO_COMPRESSION + return ssl_ctx return None def _on_timeout(self, info=None): """Timeout callback of _HTTPConnection instance. - Raise a timeout HTTPError when a timeout occurs. + Raise a `HTTPTimeoutError` when a timeout occurs. :info string key: More detailed timeout information. """ self._timeout = None error_message = "Timeout {0}".format(info) if info else "Timeout" if self.final_callback is not None: - raise HTTPError(599, error_message) + self._handle_exception(HTTPTimeoutError, HTTPTimeoutError(error_message), + None) def _remove_timeout(self): if self._timeout is not None: self.io_loop.remove_timeout(self._timeout) self._timeout = None - def _on_connect(self, stream): - if self.final_callback is None: - # final_callback is cleared if we've hit our timeout. - stream.close() - return - self.stream = stream - self.stream.set_close_callback(self.on_connection_close) - self._remove_timeout() - if self.final_callback is None: - return - if self.request.request_timeout: - self._timeout = self.io_loop.add_timeout( - self.start_time + self.request.request_timeout, - stack_context.wrap(functools.partial(self._on_timeout, "during request"))) - if (self.request.method not in self._SUPPORTED_METHODS and - not self.request.allow_nonstandard_methods): - raise KeyError("unknown method %s" % self.request.method) - for key in ('network_interface', - 'proxy_host', 'proxy_port', - 'proxy_username', 'proxy_password', - 'proxy_auth_mode'): - if getattr(self.request, key, None): - raise NotImplementedError('%s not supported' % key) - if "Connection" not in self.request.headers: - self.request.headers["Connection"] = "close" - if "Host" not in self.request.headers: - if '@' in self.parsed.netloc: - self.request.headers["Host"] = self.parsed.netloc.rpartition('@')[-1] - else: - self.request.headers["Host"] = self.parsed.netloc - username, password = None, None - if self.parsed.username is not None: - username, password = self.parsed.username, self.parsed.password - elif self.request.auth_username is not None: - username = self.request.auth_username - password = self.request.auth_password or '' - if username is not None: - if self.request.auth_mode not in (None, "basic"): - raise ValueError("unsupported auth_mode %s", - self.request.auth_mode) - auth = utf8(username) + b":" + utf8(password) - self.request.headers["Authorization"] = (b"Basic " + - base64.b64encode(auth)) - if self.request.user_agent: - self.request.headers["User-Agent"] = self.request.user_agent - if not self.request.allow_nonstandard_methods: - # Some HTTP methods nearly always have bodies while others - # almost never do. Fail in this case unless the user has - # opted out of sanity checks with allow_nonstandard_methods. - body_expected = self.request.method in ("POST", "PATCH", "PUT") - body_present = (self.request.body is not None or - self.request.body_producer is not None) - if ((body_expected and not body_present) or - (body_present and not body_expected)): - raise ValueError( - 'Body must %sbe None for method %s (unless ' - 'allow_nonstandard_methods is true)' % - ('not ' if body_expected else '', self.request.method)) - if self.request.expect_100_continue: - self.request.headers["Expect"] = "100-continue" - if self.request.body is not None: - # When body_producer is used the caller is responsible for - # setting Content-Length (or else chunked encoding will be used). - self.request.headers["Content-Length"] = str(len( - self.request.body)) - if (self.request.method == "POST" and - "Content-Type" not in self.request.headers): - self.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - if self.request.decompress_response: - self.request.headers["Accept-Encoding"] = "gzip" - req_path = ((self.parsed.path or '/') + - (('?' + self.parsed.query) if self.parsed.query else '')) - self.connection = self._create_connection(stream) - start_line = httputil.RequestStartLine(self.request.method, - req_path, '') - self.connection.write_headers(start_line, self.request.headers) - if self.request.expect_100_continue: - self._read_response() - else: - self._write_body(True) - def _create_connection(self, stream): stream.set_nodelay(True) connection = HTTP1Connection( @@ -404,31 +410,21 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): self._sockaddr) return connection + @gen.coroutine def _write_body(self, start_read): if self.request.body is not None: self.connection.write(self.request.body) elif self.request.body_producer is not None: fut = self.request.body_producer(self.connection.write) if fut is not None: - fut = gen.convert_yielded(fut) - - def on_body_written(fut): - fut.result() - self.connection.finish() - if start_read: - self._read_response() - self.io_loop.add_future(fut, on_body_written) - return + yield fut self.connection.finish() if start_read: - self._read_response() - - def _read_response(self): - # Ensure that any exception raised in read_response ends up in our - # stack context. - self.io_loop.add_future( - self.connection.read_response(self), - lambda f: f.result()) + try: + yield self.connection.read_response(self) + except StreamClosedError: + if not self._handle_exception(*sys.exc_info()): + raise def _release(self): if self.release_callback is not None: @@ -448,11 +444,12 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): self._remove_timeout() if isinstance(value, StreamClosedError): if value.real_error is None: - value = HTTPError(599, "Stream closed") + value = HTTPStreamClosedError("Stream closed") else: value = value.real_error self._run_callback(HTTPResponse(self.request, 599, error=value, request_time=self.io_loop.time() - self.start_time, + start_time=self.start_wall_time, )) if hasattr(self, "stream"): @@ -474,8 +471,8 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): if self.stream.error: raise self.stream.error try: - raise HTTPError(599, message) - except HTTPError: + raise HTTPStreamClosedError(message) + except HTTPStreamClosedError: self._handle_exception(*sys.exc_info()) def headers_received(self, first_line, headers): @@ -533,7 +530,8 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): final_callback = self.final_callback self.final_callback = None self._release() - self.client.fetch(new_request, final_callback) + fut = self.client.fetch(new_request, raise_error=False) + fut.add_done_callback(lambda f: final_callback(f.result())) self._on_end_request() return if self.request.streaming_callback: @@ -544,6 +542,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): self.code, reason=getattr(self, 'reason', None), headers=self.headers, request_time=self.io_loop.time() - self.start_time, + start_time=self.start_wall_time, buffer=buffer, effective_url=self.request.url) self._run_callback(response) diff --git a/server/www/packages/packages-common/tornado/speedups.cp37-win32.pyd b/server/www/packages/packages-common/tornado/speedups.cp37-win32.pyd new file mode 100644 index 0000000000000000000000000000000000000000..71a5eabd87d4fa96b2d1cc5220d58edd7c69e8f1 GIT binary patch literal 9216 zcmeHMe{@vUoxhXJBoj!;fJqICGU#BSN;=64`85*^BqLB07)=NS3`5AgFcUH}*_rn= zv0$;2Y#AR>dKNq$4|S!{N?Uslx~zir$KW6dU4O9akFqPA#g*#Qq&5W#sY`kL`QA4p z0d3FO{ioYg@5%Rm@At?3-h03Id%yS1O~dN#ES)iC1ZWy#`+=#{@cPeJW&>kWX1*|m z?aO*&)_z0%8?%~x{)n|Z9NG|W3s~FRg29kvT`yY0a?t7zTI-fKS_2`kSd^19$(A&| z^z9W7<~-{-kpkl{_ngQDT{c>EobbBe>bPvQ;&?XaFF2mb@vX-*fJ@%3Iz9zB=h>1PDZ}-tySFX(MVyxbf!RpMntx3sFvb0%~4O6g4 zaK52)r(XqZ0a!V0;q5fWGB|k&vu-fRsVHfz2A)DE>h}fKNedit7r0%(UJ|<*8z+2a zSqBlU#I20YxKcKOJ_&iv1e$^Fn@C^LE|SC^3B0}>R5U+Ys}V4vSQ%Sa6!x}BZH!f! zApnC-0!#x;C^ZK zfp54yEAWI;!}Y|j5ERKrY#o5?-2j+SY8YEIf&97&4>)p+c4j#(r=3om{-hC^V1+WO zxU!=vlZ2>hkgQZqrOG74Yewwqe`8}uOzOKpxzEK%W@@rUlg(-YY_*J7qMI!&cV`?D zw|X_UqNVlKY}RStyO&6Zm~`Ia7##auVItYhi1v>%)ICY;FBGDqdjG z>U{!YQOfMhRL3$I8!{118>_mZ+838Z^$g%v7%)6_aJ`rgm&uP34f zhLy4C0w!JGtQP4@k*?C@?9Md!K`B$-RDX`SY42&K?eHv|rhW!G@j&axn*5>q_tYcN zneE$49(fRw-K5qZ|E^Jpk1Ss@NR*m|8E$o*y5x*B?u-vJ{rxZ4!x)jXqnbg!q5qtG zeWRPK>;=EEnOfV>QE#n7uYOH3MYVK!iEcG?$*MG8XH`K<85^-F4Wo+T4$bbHYGH^# z{AH6lKXxyAs34(;s&EdoOu9%ptopEV2}F0ZGJh|&9CP6jJq>-8HDg{GP1aqZ$Zvvl(xCT`+OP+m zSF4BN^!~VH>P%~SWA5N1#mo}R*+F&wcB-%2M)mxyR9E+*?%0;Um!q5~IJ#~NN2X02 z&Fb(A=4fp#l;49acmrX9C*NG9(EW+~*hO4ct+XeiV(2jbn4tPdna|rYjBEj&Em&Cn<}}>5H-*!{O}ct8*Oh z$)5`GwXF%|)sa7_eb_l1-1L%o!n>OiP4mn9kq{KOam462D&dSNzZ}bbW(su1O5$r1 zdkt$7>T=#m%2f9t)J6(a2WYqYcc_sBB(kM;g4khoM* z%J#j8C8&QOc0$dBz5aM^-#L&ppR>gNJ5)a|C*VL(2+GJ106D>UOyYs<~U(P8cFVZlVQnCooJH6C+ac=E|7U!ndw z16{z|YXH}?mI9&Eq|Qe8yxwW{jZyO1L0JsBet*Mi#yTpoN6aF(?sfv*zn=*DAd~A4 zOh(%8sN9NOx5x_+N(V@G^Fj9=>Tcu)O6XEyw8zFa%}Sp1y@rvQifdG1!jbzcU^bq+ z1BsCGK~kY4uC`)uI+f}-p#TfHTQ68$W;aMwgjy5ZQVGmx|6l zwj{Z0c~S8!oHNe2>E@NMEc>YD7cXOI%`qh9^dFY8&L175^ET2k;5v&mGsjBjeq5lv zxS-|RKo(QOsy7B)qfnYbN)2NJt_woLsL*gh7QV9wOVj2%2_ znLHfh=llG>#`w9`w~&V-GUBvoH6>6u4D;9WZ$TTk93@2GF}Og>H-eMkZS@2^-ICaU z68yw|m1_03Sg^9h7&RMXON{ErDJl(AVm~W|3I@{iWn(ikCPfPN$fPuw-54TYL&zq=zsRwn(ww+IKH1G&VKa@D? z@8;;qE{=Zg1KRaa|1KcKWsLRjKx2R!kE1cfXFxerskzYUj`eTn(ml;?^(gj!|Rt%Y8ULzo5!-CQ`6cS%51uOL>gumxjD8nTX7vz8ctzy_y5ix6qhQllk}iA;udc8A-0Sf9^hONA67gaKLy44;a%*jFYw+s}?z$Y?jR#)NSM=B-PjS0paSuSUGwV zV=n;Wvl%-M_#7|=^bLRofK`AXpbzjEfXa+Q{PYK$PSR86fC*RvUK3zFKmt4n*b8_a zpaQ5o4Ex^$_yA1+Dit#j*8ht_pR4p4o9dE!v!R6J#CfQj1)z5t6nb0vzZS|(HM8_z zo_&ai%j_TzQ9-(7i))+eNlI@h{5{1M2y&qnJT!{@^eAHEITd#J^GcE3-rlhRzw%Oa z?VU}wRkaJD&bD37!v_*$+b`oS<$60V=W)G9F5|hm-mc4eT<`JAcuidI3GlKR=F8{O z#Px8~v+cx7zW=}<`usU*40Qq}QbD;UR%-q51HEZ9QnR)Eions85F8(%ht@`@Mv8UIdTcnvy($ zct^qOyTmIc9>wHGv<|&*8S&^Hi~AtC*6pCBbm**)-~|h%CTW|$Y1w)?4-;6227kY@ z*^7y{4!lP$@%X%mKe5n*1JOs5I7R!X>hYJN-?>75>d(jzOkXpQZ zXJMpK3j2dN2!%$EyLVxDgU8(#j)+ZicbDjC^xrEsv2zA@Z$ro{gHan6+awWjA$(!s zws0t*+gKR%QU})EEBQh}p}ff3)y3GOrWHY7ThQAjdR;y3Vz=ZE1#k0rNn)6>HKs;U z`jg^mX^TavRt|^7pyUpR+C>C&uc=842mC?IBE@3gNnaXC5~1*In4lbnP>i4(TVT9H z7Q?-6G29Uf2ik(|Vr@vq2UeI}^=0czz3l1<+$JAZ>jjg2K-|XOh$IG@`~h)c1Pc(U z#jY{b`6F%XL2>1J|N3xSxVN^gt1H4*rBi(Q+q&SC#(IB5S^{%8mrEmc;(B?*1~HtP zI~y&1W8w`_!X* zI9%#!4+R3DAZxC@bH%czr46p)QoC-og29$w!qNk*@>1I)vW3hO5q+Kxz9}A>!gK~Z z!4Cfhc+wMW3x`AZc-q1n?&c$s6@5`Dkr=$&9}Wcr! zaRU}1hCNA1ha7CDkYF}ii`XtpVoIcUnu)oDB@Z?nhS=4hc!RZd`{xBBbe!iwJ`exF zk+322x{Bu&&r2@(tB&8-yuUIJJTv{3I(lBfb-?ePRIZQQ7{N`;*gfLH zk&TzKJ;_M-%3@D`myx~h3EyZbJu7%|eD6`;3-m+p>+%=%0Da&r27DVp-+uIOy|2sP zss{`V53K}SF86?e9wg{9_)C2J+W=h%0w=T$;RTyWAiiRbf72{v;2B89 zY4#2FhwVSMzhr;Y{-5?!_CMOwigSzaD()?g7XP4luy}v*xngt4t0liLsTJylmBL!# zKA}%|K-exkEbI~ng`Wz~2>XRsgu}uc!n?u=;n%|NgwF*{FqP((PA{EXT3NcZ^v=@f zOYfckv-zLT&ndH(-BRW(YbcA9Z7qAKY-ib1WzUr5md_}!Ex*0oTmD%2f%4bN-zh&) z{%QI2idhw96^kmCRWwzsuIQ-fs(7d(Ua_(Afyy0~PgXu#`F!Px%Kxg&teRR?RP~*z zEmi+ewY%!Ys-ddoj#Z9zj;9>YIbL#{aa?d@IrE&?IqgoTbCGk2bD6Wrx!SqT+2QPR zhMhgm`<#8w2b@24KJEOK^8+WVE~rLSSot68v+uL-x6dfH7SAc(BMb|t1XVDWnoH?G U0j*+dGXMYp literal 0 HcmV?d00001 diff --git a/server/www/packages/packages-common/tornado/stack_context.py b/server/www/packages/packages-common/tornado/stack_context.py index 61ae51f..a1eca4c 100644 --- a/server/www/packages/packages-common/tornado/stack_context.py +++ b/server/www/packages/packages-common/tornado/stack_context.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2010 Facebook # @@ -65,12 +64,18 @@ Here are a few rules of thumb for when it's necessary: persist across asynchronous calls, create a new `StackContext` (or `ExceptionStackContext`), and make your asynchronous calls in a ``with`` block that references your `StackContext`. + +.. deprecated:: 5.1 + + The ``stack_context`` package is deprecated and will be removed in + Tornado 6.0. """ from __future__ import absolute_import, division, print_function import sys import threading +import warnings from tornado.util import raise_exc_info @@ -108,6 +113,8 @@ class StackContext(object): and not necessary in most applications. """ def __init__(self, context_factory): + warnings.warn("StackContext is deprecated and will be removed in Tornado 6.0", + DeprecationWarning) self.context_factory = context_factory self.contexts = [] self.active = True @@ -175,8 +182,20 @@ class ExceptionStackContext(object): If the exception handler returns true, the exception will be consumed and will not be propagated to other exception handlers. + + .. versionadded:: 5.1 + + The ``delay_warning`` argument can be used to delay the emission + of DeprecationWarnings until an exception is caught by the + ``ExceptionStackContext``, which facilitates certain transitional + use cases. """ - def __init__(self, exception_handler): + def __init__(self, exception_handler, delay_warning=False): + self.delay_warning = delay_warning + if not self.delay_warning: + warnings.warn( + "StackContext is deprecated and will be removed in Tornado 6.0", + DeprecationWarning) self.exception_handler = exception_handler self.active = True @@ -185,6 +204,10 @@ class ExceptionStackContext(object): def exit(self, type, value, traceback): if type is not None: + if self.delay_warning: + warnings.warn( + "StackContext is deprecated and will be removed in Tornado 6.0", + DeprecationWarning) return self.exception_handler(type, value, traceback) def __enter__(self): diff --git a/server/www/packages/packages-common/tornado/tcpclient.py b/server/www/packages/packages-common/tornado/tcpclient.py index 33074bd..3a1b58c 100644 --- a/server/www/packages/packages-common/tornado/tcpclient.py +++ b/server/www/packages/packages-common/tornado/tcpclient.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2014 Facebook # @@ -20,12 +19,17 @@ from __future__ import absolute_import, division, print_function import functools import socket +import numbers +import datetime -from tornado.concurrent import Future +from tornado.concurrent import Future, future_add_done_callback from tornado.ioloop import IOLoop from tornado.iostream import IOStream from tornado import gen from tornado.netutil import Resolver +from tornado.platform.auto import set_close_exec +from tornado.gen import TimeoutError +from tornado.util import timedelta_to_seconds _INITIAL_CONNECT_TIMEOUT = 0.3 @@ -47,15 +51,17 @@ class _Connector(object): http://tools.ietf.org/html/rfc6555 """ - def __init__(self, addrinfo, io_loop, connect): - self.io_loop = io_loop + def __init__(self, addrinfo, connect): + self.io_loop = IOLoop.current() self.connect = connect self.future = Future() self.timeout = None + self.connect_timeout = None self.last_error = None self.remaining = len(addrinfo) self.primary_addrs, self.secondary_addrs = self.split(addrinfo) + self.streams = set() @staticmethod def split(addrinfo): @@ -77,9 +83,11 @@ class _Connector(object): secondary.append((af, addr)) return primary, secondary - def start(self, timeout=_INITIAL_CONNECT_TIMEOUT): + def start(self, timeout=_INITIAL_CONNECT_TIMEOUT, connect_timeout=None): self.try_connect(iter(self.primary_addrs)) - self.set_timout(timeout) + self.set_timeout(timeout) + if connect_timeout is not None: + self.set_connect_timeout(connect_timeout) return self.future def try_connect(self, addrs): @@ -93,9 +101,10 @@ class _Connector(object): self.future.set_exception(self.last_error or IOError("connection failed")) return - future = self.connect(af, addr) - future.add_done_callback(functools.partial(self.on_connect_done, - addrs, af, addr)) + stream, future = self.connect(af, addr) + self.streams.add(stream) + future_add_done_callback( + future, functools.partial(self.on_connect_done, addrs, af, addr)) def on_connect_done(self, addrs, af, addr, future): self.remaining -= 1 @@ -114,39 +123,60 @@ class _Connector(object): self.io_loop.remove_timeout(self.timeout) self.on_timeout() return - self.clear_timeout() + self.clear_timeouts() if self.future.done(): # This is a late arrival; just drop it. stream.close() else: + self.streams.discard(stream) self.future.set_result((af, addr, stream)) + self.close_streams() - def set_timout(self, timeout): + def set_timeout(self, timeout): self.timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, self.on_timeout) def on_timeout(self): self.timeout = None - self.try_connect(iter(self.secondary_addrs)) + if not self.future.done(): + self.try_connect(iter(self.secondary_addrs)) def clear_timeout(self): if self.timeout is not None: self.io_loop.remove_timeout(self.timeout) + def set_connect_timeout(self, connect_timeout): + self.connect_timeout = self.io_loop.add_timeout( + connect_timeout, self.on_connect_timeout) + + def on_connect_timeout(self): + if not self.future.done(): + self.future.set_exception(TimeoutError()) + self.close_streams() + + def clear_timeouts(self): + if self.timeout is not None: + self.io_loop.remove_timeout(self.timeout) + if self.connect_timeout is not None: + self.io_loop.remove_timeout(self.connect_timeout) + + def close_streams(self): + for stream in self.streams: + stream.close() + class TCPClient(object): """A non-blocking TCP connection factory. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def __init__(self, resolver=None, io_loop=None): - self.io_loop = io_loop or IOLoop.current() + def __init__(self, resolver=None): if resolver is not None: self.resolver = resolver self._own_resolver = False else: - self.resolver = Resolver(io_loop=io_loop) + self.resolver = Resolver() self._own_resolver = True def close(self): @@ -155,7 +185,8 @@ class TCPClient(object): @gen.coroutine def connect(self, host, port, af=socket.AF_UNSPEC, ssl_options=None, - max_buffer_size=None, source_ip=None, source_port=None): + max_buffer_size=None, source_ip=None, source_port=None, + timeout=None): """Connect to the given host and port. Asynchronously returns an `.IOStream` (or `.SSLIOStream` if @@ -167,25 +198,48 @@ class TCPClient(object): use a specific interface, it has to be handled outside of Tornado as this depends very much on the platform. + Raises `TimeoutError` if the input future does not complete before + ``timeout``, which may be specified in any form allowed by + `.IOLoop.add_timeout` (i.e. a `datetime.timedelta` or an absolute time + relative to `.IOLoop.time`) + Similarly, when the user requires a certain source port, it can be specified using the ``source_port`` arg. .. versionchanged:: 4.5 Added the ``source_ip`` and ``source_port`` arguments. + + .. versionchanged:: 5.0 + Added the ``timeout`` argument. """ - addrinfo = yield self.resolver.resolve(host, port, af) + if timeout is not None: + if isinstance(timeout, numbers.Real): + timeout = IOLoop.current().time() + timeout + elif isinstance(timeout, datetime.timedelta): + timeout = IOLoop.current().time() + timedelta_to_seconds(timeout) + else: + raise TypeError("Unsupported timeout %r" % timeout) + if timeout is not None: + addrinfo = yield gen.with_timeout( + timeout, self.resolver.resolve(host, port, af)) + else: + addrinfo = yield self.resolver.resolve(host, port, af) connector = _Connector( - addrinfo, self.io_loop, + addrinfo, functools.partial(self._create_stream, max_buffer_size, source_ip=source_ip, source_port=source_port) ) - af, addr, stream = yield connector.start() + af, addr, stream = yield connector.start(connect_timeout=timeout) # TODO: For better performance we could cache the (af, addr) # information here and re-use it on subsequent connections to # the same host. (http://tools.ietf.org/html/rfc6555#section-4.2) if ssl_options is not None: - stream = yield stream.start_tls(False, ssl_options=ssl_options, - server_hostname=host) + if timeout is not None: + stream = yield gen.with_timeout(timeout, stream.start_tls( + False, ssl_options=ssl_options, server_hostname=host)) + else: + stream = yield stream.start_tls(False, ssl_options=ssl_options, + server_hostname=host) raise gen.Return(stream) def _create_stream(self, max_buffer_size, af, addr, source_ip=None, @@ -202,6 +256,7 @@ class TCPClient(object): # - 127.0.0.1 for IPv4 # - ::1 for IPv6 socket_obj = socket.socket(af) + set_close_exec(socket_obj.fileno()) if source_port_bind or source_ip_bind: # If the user requires binding also to a specific IP/port. try: @@ -212,11 +267,10 @@ class TCPClient(object): raise try: stream = IOStream(socket_obj, - io_loop=self.io_loop, max_buffer_size=max_buffer_size) except socket.error as e: fu = Future() fu.set_exception(e) return fu else: - return stream.connect(addr) + return stream, stream.connect(addr) diff --git a/server/www/packages/packages-common/tornado/tcpserver.py b/server/www/packages/packages-common/tornado/tcpserver.py index f47ec89..4f5d6f0 100644 --- a/server/www/packages/packages-common/tornado/tcpserver.py +++ b/server/www/packages/packages-common/tornado/tcpserver.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2011 Facebook # @@ -47,12 +46,11 @@ class TCPServer(object): from tornado import gen class EchoServer(TCPServer): - @gen.coroutine - def handle_stream(self, stream, address): + async def handle_stream(self, stream, address): while True: try: - data = yield stream.read_until(b"\n") - yield stream.write(data) + data = await stream.read_until(b"\n") + await stream.write(data) except StreamClosedError: break @@ -102,12 +100,15 @@ class TCPServer(object): .. versionadded:: 3.1 The ``max_buffer_size`` argument. + + .. versionchanged:: 5.0 + The ``io_loop`` argument has been removed. """ - def __init__(self, io_loop=None, ssl_options=None, max_buffer_size=None, + def __init__(self, ssl_options=None, max_buffer_size=None, read_chunk_size=None): - self.io_loop = io_loop self.ssl_options = ssl_options - self._sockets = {} # fd -> socket object + self._sockets = {} # fd -> socket object + self._handlers = {} # fd -> remove_handler callable self._pending_sockets = [] self._started = False self._stopped = False @@ -151,13 +152,10 @@ class TCPServer(object): method and `tornado.process.fork_processes` to provide greater control over the initialization of a multi-process server. """ - if self.io_loop is None: - self.io_loop = IOLoop.current() - for sock in sockets: self._sockets[sock.fileno()] = sock - add_accept_handler(sock, self._handle_connection, - io_loop=self.io_loop) + self._handlers[sock.fileno()] = add_accept_handler( + sock, self._handle_connection) def add_socket(self, socket): """Singular version of `add_sockets`. Takes a single socket object.""" @@ -234,7 +232,8 @@ class TCPServer(object): self._stopped = True for fd, sock in self._sockets.items(): assert sock.fileno() == fd - self.io_loop.remove_handler(fd) + # Unregister socket from IOLoop + self._handlers.pop(fd)() sock.close() def handle_stream(self, stream, address): @@ -284,17 +283,17 @@ class TCPServer(object): raise try: if self.ssl_options is not None: - stream = SSLIOStream(connection, io_loop=self.io_loop, + stream = SSLIOStream(connection, max_buffer_size=self.max_buffer_size, read_chunk_size=self.read_chunk_size) else: - stream = IOStream(connection, io_loop=self.io_loop, + stream = IOStream(connection, max_buffer_size=self.max_buffer_size, read_chunk_size=self.read_chunk_size) future = self.handle_stream(stream, address) if future is not None: - self.io_loop.add_future(gen.convert_yielded(future), - lambda f: f.result()) + IOLoop.current().add_future(gen.convert_yielded(future), + lambda f: f.result()) except Exception: app_log.error("Error in connection callback", exc_info=True) diff --git a/server/www/packages/packages-common/tornado/template.py b/server/www/packages/packages-common/tornado/template.py index 3b2fa3f..61b9874 100644 --- a/server/www/packages/packages-common/tornado/template.py +++ b/server/www/packages/packages-common/tornado/template.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -260,9 +259,8 @@ class Template(object): :arg str template_string: the contents of the template file. :arg str name: the filename from which the template was loaded (used for error message). - :arg tornado.template.BaseLoader loader: the `~tornado.template.BaseLoader` responsible for this template, - used to resolve ``{% include %}`` and ``{% extend %}`` - directives. + :arg tornado.template.BaseLoader loader: the `~tornado.template.BaseLoader` responsible + for this template, used to resolve ``{% include %}`` and ``{% extend %}`` directives. :arg bool compress_whitespace: Deprecated since Tornado 4.3. Equivalent to ``whitespace="single"`` if true and ``whitespace="all"`` if false. diff --git a/server/www/packages/packages-common/tornado/testing.py b/server/www/packages/packages-common/tornado/testing.py index 74d04b6..d6e5e94 100644 --- a/server/www/packages/packages-common/tornado/testing.py +++ b/server/www/packages/packages-common/tornado/testing.py @@ -1,10 +1,9 @@ -#!/usr/bin/env python """Support classes for automated testing. * `AsyncTestCase` and `AsyncHTTPTestCase`: Subclasses of unittest.TestCase with additional support for testing asynchronous (`.IOLoop`-based) code. -* `ExpectLog` and `LogTrapTestCase`: Make test logs less spammy. +* `ExpectLog`: Make test logs less spammy. * `main()`: A simple test runner (wrapper around unittest.main()) with support for the tornado.autoreload module to rerun the tests when code changes. @@ -22,7 +21,7 @@ try: from tornado.process import Subprocess except ImportError: # These modules are not importable on app engine. Parts of this module - # won't work, but e.g. LogTrapTestCase and main() will. + # won't work, but e.g. main() will. AsyncHTTPClient = None # type: ignore gen = None # type: ignore HTTPServer = None # type: ignore @@ -30,7 +29,7 @@ except ImportError: netutil = None # type: ignore SimpleAsyncHTTPClient = None # type: ignore Subprocess = None # type: ignore -from tornado.log import gen_log, app_log +from tornado.log import app_log from tornado.stack_context import ExceptionStackContext from tornado.util import raise_exc_info, basestring_type, PY3 import functools @@ -42,10 +41,11 @@ import signal import socket import sys -if PY3: - from io import StringIO -else: - from cStringIO import StringIO +try: + import asyncio +except ImportError: + asyncio = None + try: from collections.abc import Generator as GeneratorType # type: ignore @@ -73,23 +73,12 @@ else: except ImportError: import unittest # type: ignore -_next_port = 10000 - -def get_unused_port(): - """Returns a (hopefully) unused port number. - - This function does not guarantee that the port it returns is available, - only that a series of get_unused_port calls in a single process return - distinct ports. - - .. deprecated:: - Use bind_unused_port instead, which is guaranteed to find an unused port. - """ - global _next_port - port = _next_port - _next_port = _next_port + 1 - return port +if asyncio is None: + _NON_OWNED_IOLOOPS = () +else: + import tornado.platform.asyncio + _NON_OWNED_IOLOOPS = tornado.platform.asyncio.AsyncIOMainLoop def bind_unused_port(reuse_port=False): @@ -155,19 +144,19 @@ class AsyncTestCase(unittest.TestCase): asynchronous code. The unittest framework is synchronous, so the test must be - complete by the time the test method returns. This means that - asynchronous code cannot be used in quite the same way as usual. - To write test functions that use the same ``yield``-based patterns - used with the `tornado.gen` module, decorate your test methods - with `tornado.testing.gen_test` instead of - `tornado.gen.coroutine`. This class also provides the `stop()` - and `wait()` methods for a more manual style of testing. The test - method itself must call ``self.wait()``, and asynchronous - callbacks should call ``self.stop()`` to signal completion. + complete by the time the test method returns. This means that + asynchronous code cannot be used in quite the same way as usual + and must be adapted to fit. To write your tests with coroutines, + decorate your test methods with `tornado.testing.gen_test` instead + of `tornado.gen.coroutine`. + + This class also provides the (deprecated) `stop()` and `wait()` + methods for a more manual style of testing. The test method itself + must call ``self.wait()``, and asynchronous callbacks should call + ``self.stop()`` to signal completion. By default, a new `.IOLoop` is constructed for each test and is available - as ``self.io_loop``. This `.IOLoop` should be used in the construction of - HTTP clients/servers, etc. If the code being tested requires a + as ``self.io_loop``. If the code being tested requires a global `.IOLoop`, subclasses should override `get_new_ioloop` to return it. The `.IOLoop`'s ``start`` and ``stop`` methods should not be @@ -182,7 +171,7 @@ class AsyncTestCase(unittest.TestCase): class MyTestCase(AsyncTestCase): @tornado.testing.gen_test def test_http_fetch(self): - client = AsyncHTTPClient(self.io_loop) + client = AsyncHTTPClient() response = yield client.fetch("http://www.tornadoweb.org") # Test contents of response self.assertIn("FriendFeed", response.body) @@ -190,27 +179,11 @@ class AsyncTestCase(unittest.TestCase): # This test uses argument passing between self.stop and self.wait. class MyTestCase2(AsyncTestCase): def test_http_fetch(self): - client = AsyncHTTPClient(self.io_loop) + client = AsyncHTTPClient() client.fetch("http://www.tornadoweb.org/", self.stop) response = self.wait() # Test contents of response self.assertIn("FriendFeed", response.body) - - # This test uses an explicit callback-based style. - class MyTestCase3(AsyncTestCase): - def test_http_fetch(self): - client = AsyncHTTPClient(self.io_loop) - client.fetch("http://www.tornadoweb.org/", self.handle_fetch) - self.wait() - - def handle_fetch(self, response): - # Test contents of response (failures and exceptions here - # will cause self.wait() to throw an exception and end the - # test). - # Exceptions thrown here are magically propagated to - # self.wait() in test_http_fetch() via stack_context. - self.assertIn("FriendFeed", response.body) - self.stop() """ def __init__(self, methodName='runTest'): super(AsyncTestCase, self).__init__(methodName) @@ -235,8 +208,7 @@ class AsyncTestCase(unittest.TestCase): # Clean up Subprocess, so it can be used again with a new ioloop. Subprocess.uninitialize() self.io_loop.clear_current() - if (not IOLoop.initialized() or - self.io_loop is not IOLoop.instance()): + if not isinstance(self.io_loop, _NON_OWNED_IOLOOPS): # Try to clean up any file descriptors left open in the ioloop. # This avoids leaks, especially when tests are run repeatedly # in the same process with autoreload (because curl does not @@ -250,9 +222,15 @@ class AsyncTestCase(unittest.TestCase): self.__rethrow() def get_new_ioloop(self): - """Creates a new `.IOLoop` for this test. May be overridden in - subclasses for tests that require a specific `.IOLoop` (usually - the singleton `.IOLoop.instance()`). + """Returns the `.IOLoop` to use for this test. + + By default, a new `.IOLoop` is created for each test. + Subclasses may override this method to return + `.IOLoop.current()` if it is not appropriate to use a new + `.IOLoop` in each tests (for example, if there are global + singletons using the default `.IOLoop`) or if a per-test event + loop is being provided by another system (such as + ``pytest-asyncio``). """ return IOLoop() @@ -272,7 +250,7 @@ class AsyncTestCase(unittest.TestCase): raise_exc_info(failure) def run(self, result=None): - with ExceptionStackContext(self._handle_exception): + with ExceptionStackContext(self._handle_exception, delay_warning=True): super(AsyncTestCase, self).run(result) # As a last resort, if an exception escaped super.run() and wasn't # re-raised in tearDown, raise it here. This will cause the @@ -286,6 +264,10 @@ class AsyncTestCase(unittest.TestCase): Keyword arguments or a single positional argument passed to `stop()` are saved and will be returned by `wait()`. + + .. deprecated:: 5.1 + + `stop` and `wait` are deprecated; use ``@gen_test`` instead. """ assert _arg is None or not kwargs self.__stop_args = kwargs or _arg @@ -307,6 +289,10 @@ class AsyncTestCase(unittest.TestCase): .. versionchanged:: 3.1 Added the ``ASYNC_TEST_TIMEOUT`` environment variable. + + .. deprecated:: 5.1 + + `stop` and `wait` are deprecated; use ``@gen_test`` instead. """ if timeout is None: timeout = get_async_test_timeout() @@ -321,7 +307,8 @@ class AsyncTestCase(unittest.TestCase): except Exception: self.__failure = sys.exc_info() self.stop() - self.__timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, timeout_func) + self.__timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, + timeout_func) while True: self.__running = True self.io_loop.start() @@ -382,11 +369,10 @@ class AsyncHTTPTestCase(AsyncTestCase): self.http_server.add_sockets([sock]) def get_http_client(self): - return AsyncHTTPClient(io_loop=self.io_loop) + return AsyncHTTPClient() def get_http_server(self): - return HTTPServer(self._app, io_loop=self.io_loop, - **self.get_httpserver_options()) + return HTTPServer(self._app, **self.get_httpserver_options()) def get_app(self): """Should be overridden by subclasses to return a @@ -394,16 +380,47 @@ class AsyncHTTPTestCase(AsyncTestCase): """ raise NotImplementedError() - def fetch(self, path, **kwargs): - """Convenience method to synchronously fetch a url. + def fetch(self, path, raise_error=False, **kwargs): + """Convenience method to synchronously fetch a URL. The given path will be appended to the local server's host and port. Any additional kwargs will be passed directly to `.AsyncHTTPClient.fetch` (and so could be used to pass ``method="POST"``, ``body="..."``, etc). + + If the path begins with http:// or https://, it will be treated as a + full URL and will be fetched as-is. + + If ``raise_error`` is True, a `tornado.httpclient.HTTPError` will + be raised if the response code is not 200. This is the same behavior + as the ``raise_error`` argument to `.AsyncHTTPClient.fetch`, but + the default is False here (it's True in `.AsyncHTTPClient`) because + tests often need to deal with non-200 response codes. + + .. versionchanged:: 5.0 + Added support for absolute URLs. + + .. versionchanged:: 5.1 + + Added the ``raise_error`` argument. + + .. deprecated:: 5.1 + + This method currently turns any exception into an + `.HTTPResponse` with status code 599. In Tornado 6.0, + errors other than `tornado.httpclient.HTTPError` will be + passed through, and ``raise_error=False`` will only + suppress errors that would be raised due to non-200 + response codes. + """ - self.http_client.fetch(self.get_url(path), self.stop, **kwargs) - return self.wait() + if path.lower().startswith(('http://', 'https://')): + url = path + else: + url = self.get_url(path) + return self.io_loop.run_sync( + lambda: self.http_client.fetch(url, raise_error=raise_error, **kwargs), + timeout=get_async_test_timeout()) def get_httpserver_options(self): """May be overridden by subclasses to return additional @@ -423,16 +440,14 @@ class AsyncHTTPTestCase(AsyncTestCase): def get_url(self, path): """Returns an absolute url for the given path on the test server.""" - return '%s://localhost:%s%s' % (self.get_protocol(), + return '%s://127.0.0.1:%s%s' % (self.get_protocol(), self.get_http_port(), path) def tearDown(self): self.http_server.stop() self.io_loop.run_sync(self.http_server.close_all_connections, timeout=get_async_test_timeout()) - if (not IOLoop.initialized() or - self.http_client.io_loop is not IOLoop.instance()): - self.http_client.close() + self.http_client.close() super(AsyncHTTPTestCase, self).tearDown() @@ -442,7 +457,7 @@ class AsyncHTTPSTestCase(AsyncHTTPTestCase): Interface is generally the same as `AsyncHTTPTestCase`. """ def get_http_client(self): - return AsyncHTTPClient(io_loop=self.io_loop, force_instance=True, + return AsyncHTTPClient(force_instance=True, defaults=dict(validate_cert=False)) def get_httpserver_options(self): @@ -454,7 +469,8 @@ class AsyncHTTPSTestCase(AsyncHTTPTestCase): By default includes a self-signed testing certificate. """ # Testing keys were generated with: - # openssl req -new -keyout tornado/test/test.key -out tornado/test/test.crt -nodes -days 3650 -x509 + # openssl req -new -keyout tornado/test/test.key \ + # -out tornado/test/test.crt -nodes -days 3650 -x509 module_dir = os.path.dirname(__file__) return dict( certfile=os.path.join(module_dir, 'test', 'test.crt'), @@ -476,7 +492,7 @@ def gen_test(func=None, timeout=None): class MyTest(AsyncHTTPTestCase): @gen_test def test_something(self): - response = yield gen.Task(self.fetch('/')) + response = yield self.http_client.fetch(self.get_url('/')) By default, ``@gen_test`` times out after 5 seconds. The timeout may be overridden globally with the ``ASYNC_TEST_TIMEOUT`` environment variable, @@ -485,7 +501,11 @@ def gen_test(func=None, timeout=None): class MyTest(AsyncHTTPTestCase): @gen_test(timeout=10) def test_something_slow(self): - response = yield gen.Task(self.fetch('/')) + response = yield self.http_client.fetch(self.get_url('/')) + + Note that ``@gen_test`` is incompatible with `AsyncTestCase.stop`, + `AsyncTestCase.wait`, and `AsyncHTTPTestCase.fetch`. Use ``yield + self.http_client.fetch(self.get_url())`` as shown above instead. .. versionadded:: 3.1 The ``timeout`` argument and ``ASYNC_TEST_TIMEOUT`` environment @@ -494,6 +514,7 @@ def gen_test(func=None, timeout=None): .. versionchanged:: 4.0 The wrapper now passes along ``*args, **kwargs`` so it can be used on functions with arguments. + """ if timeout is None: timeout = get_async_test_timeout() @@ -529,12 +550,17 @@ def gen_test(func=None, timeout=None): timeout=timeout) except TimeoutError as e: # run_sync raises an error with an unhelpful traceback. - # Throw it back into the generator or coroutine so the stack - # trace is replaced by the point where the test is stopped. - self._test_generator.throw(e) - # In case the test contains an overly broad except clause, - # we may get back here. In this case re-raise the original - # exception, which is better than nothing. + # If the underlying generator is still running, we can throw the + # exception back into it so the stack trace is replaced by the + # point where the test is stopped. The only reason the generator + # would not be running would be if it were cancelled, which means + # a native coroutine, so we can rely on the cr_running attribute. + if getattr(self._test_generator, 'cr_running', True): + self._test_generator.throw(e) + # In case the test contains an overly broad except + # clause, we may get back here. + # Coroutine was stopped or didn't raise a useful stack trace, + # so re-raise the original exception which is better than nothing. raise return post_coroutine @@ -554,49 +580,6 @@ def gen_test(func=None, timeout=None): gen_test.__test__ = False # type: ignore -class LogTrapTestCase(unittest.TestCase): - """A test case that captures and discards all logging output - if the test passes. - - Some libraries can produce a lot of logging output even when - the test succeeds, so this class can be useful to minimize the noise. - Simply use it as a base class for your test case. It is safe to combine - with AsyncTestCase via multiple inheritance - (``class MyTestCase(AsyncHTTPTestCase, LogTrapTestCase):``) - - This class assumes that only one log handler is configured and - that it is a `~logging.StreamHandler`. This is true for both - `logging.basicConfig` and the "pretty logging" configured by - `tornado.options`. It is not compatible with other log buffering - mechanisms, such as those provided by some test runners. - - .. deprecated:: 4.1 - Use the unittest module's ``--buffer`` option instead, or `.ExpectLog`. - """ - def run(self, result=None): - logger = logging.getLogger() - if not logger.handlers: - logging.basicConfig() - handler = logger.handlers[0] - if (len(logger.handlers) > 1 or - not isinstance(handler, logging.StreamHandler)): - # Logging has been configured in a way we don't recognize, - # so just leave it alone. - super(LogTrapTestCase, self).run(result) - return - old_stream = handler.stream - try: - handler.stream = StringIO() - gen_log.info("RUNNING TEST: " + str(self)) - old_error_count = len(result.failures) + len(result.errors) - super(LogTrapTestCase, self).run(result) - new_error_count = len(result.failures) + len(result.errors) - if new_error_count != old_error_count: - old_stream.write(handler.stream.getvalue()) - finally: - handler.stream = old_stream - - class ExpectLog(logging.Filter): """Context manager to capture and suppress expected log output. @@ -684,6 +667,12 @@ def main(**kwargs): to show many test details as they are run. See http://docs.python.org/library/unittest.html#unittest.main for full argument list. + + .. versionchanged:: 5.0 + + This function produces no output of its own; only that produced + by the `unittest` module (Previously it would add a PASS or FAIL + log message). """ from tornado.options import define, options, parse_command_line @@ -719,23 +708,16 @@ def main(**kwargs): if __name__ == '__main__' and len(argv) == 1: print("No tests specified", file=sys.stderr) sys.exit(1) - try: - # In order to be able to run tests by their fully-qualified name - # on the command line without importing all tests here, - # module must be set to None. Python 3.2's unittest.main ignores - # defaultTest if no module is given (it tries to do its own - # test discovery, which is incompatible with auto2to3), so don't - # set module if we're not asking for a specific test. - if len(argv) > 1: - unittest.main(module=None, argv=argv, **kwargs) - else: - unittest.main(defaultTest="all", argv=argv, **kwargs) - except SystemExit as e: - if e.code == 0: - gen_log.info('PASS') - else: - gen_log.error('FAIL') - raise + # In order to be able to run tests by their fully-qualified name + # on the command line without importing all tests here, + # module must be set to None. Python 3.2's unittest.main ignores + # defaultTest if no module is given (it tries to do its own + # test discovery, which is incompatible with auto2to3), so don't + # set module if we're not asking for a specific test. + if len(argv) > 1: + unittest.main(module=None, argv=argv, **kwargs) + else: + unittest.main(defaultTest="all", argv=argv, **kwargs) if __name__ == '__main__': diff --git a/server/www/packages/packages-common/tornado/util.py b/server/www/packages/packages-common/tornado/util.py index 981b94c..a42ebeb 100644 --- a/server/www/packages/packages-common/tornado/util.py +++ b/server/www/packages/packages-common/tornado/util.py @@ -84,6 +84,16 @@ except ImportError: is_finalizing = _get_emulated_is_finalizing() +class TimeoutError(Exception): + """Exception raised by `.with_timeout` and `.IOLoop.run_sync`. + + .. versionchanged:: 5.0: + Unified ``tornado.gen.TimeoutError`` and + ``tornado.ioloop.TimeoutError`` as ``tornado.util.TimeoutError``. + Both former names remain as aliases. + """ + + class ObjectDict(_ObjectDictBase): """Makes a dictionary behave like an object, with attribute-style access. """ @@ -272,6 +282,12 @@ class Configurable(object): Configurable subclasses must define the class methods `configurable_base` and `configurable_default`, and use the instance method `initialize` instead of ``__init__``. + + .. versionchanged:: 5.0 + + It is now possible for configuration to be specified at + multiple levels of a class hierarchy. + """ __impl_class = None # type: type __impl_kwargs = None # type: Dict[str, Any] @@ -286,6 +302,9 @@ class Configurable(object): else: impl = cls init_kwargs.update(kwargs) + if impl.configurable_base() is not base: + # The impl class is itself configurable, so recurse. + return impl(*args, **init_kwargs) instance = super(Configurable, cls).__new__(impl) # initialize vs __init__ chosen for compatibility with AsyncHTTPClient # singleton magic. If we get rid of that we can switch to __init__ @@ -343,7 +362,10 @@ class Configurable(object): # type: () -> type """Returns the currently configured class.""" base = cls.configurable_base() - if cls.__impl_class is None: + # Manually mangle the private name to see whether this base + # has been configured (and not another base higher in the + # hierarchy). + if base.__dict__.get('_Configurable__impl_class') is None: base.__impl_class = cls.configurable_default() return base.__impl_class diff --git a/server/www/packages/packages-common/tornado/web.py b/server/www/packages/packages-common/tornado/web.py index d79889f..6760b0b 100644 --- a/server/www/packages/packages-common/tornado/web.py +++ b/server/www/packages/packages-common/tornado/web.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -47,12 +46,14 @@ Thread-safety notes ------------------- In general, methods on `RequestHandler` and elsewhere in Tornado are -not thread-safe. In particular, methods such as +not thread-safe. In particular, methods such as `~RequestHandler.write()`, `~RequestHandler.finish()`, and -`~RequestHandler.flush()` must only be called from the main thread. If +`~RequestHandler.flush()` must only be called from the main thread. If you use multiple threads it is important to use `.IOLoop.add_callback` to transfer control back to the main thread before finishing the -request. +request, or to limit your use of other threads to +`.IOLoop.run_in_executor` and ensure that your callbacks running in +the executor do not refer to Tornado objects. """ @@ -77,10 +78,11 @@ import time import tornado import traceback import types +import warnings from inspect import isclass from io import BytesIO -from tornado.concurrent import Future +from tornado.concurrent import Future, future_set_result_unless_cancelled from tornado import escape from tornado import gen from tornado import httputil @@ -245,7 +247,7 @@ class RequestHandler(object): of the request method. Asynchronous support: Decorate this method with `.gen.coroutine` - or `.return_future` to make it asynchronous (the + or use ``async def`` to make it asynchronous (the `asynchronous` decorator cannot be used on `prepare`). If this method returns a `.Future` execution will not proceed until the `.Future` is done. @@ -309,20 +311,21 @@ class RequestHandler(object): def set_status(self, status_code, reason=None): """Sets the status code for our response. - :arg int status_code: Response status code. If ``reason`` is ``None``, - it must be present in `httplib.responses `. - :arg string reason: Human-readable reason phrase describing the status + :arg int status_code: Response status code. + :arg str reason: Human-readable reason phrase describing the status code. If ``None``, it will be filled in from - `httplib.responses `. + `http.client.responses` or "Unknown". + + .. versionchanged:: 5.0 + + No longer validates that the response code is in + `http.client.responses`. """ self._status_code = status_code if reason is not None: self._reason = escape.native_str(reason) else: - try: - self._reason = httputil.responses[status_code] - except KeyError: - raise ValueError("unknown status code %d" % status_code) + self._reason = httputil.responses.get(status_code, "Unknown") def get_status(self): """Returns the status code for our response.""" @@ -521,18 +524,32 @@ class RequestHandler(object): return self.request.cookies def get_cookie(self, name, default=None): - """Gets the value of the cookie with the given name, else default.""" + """Returns the value of the request cookie with the given name. + + If the named cookie is not present, returns ``default``. + + This method only returns cookies that were present in the request. + It does not see the outgoing cookies set by `set_cookie` in this + handler. + """ if self.request.cookies is not None and name in self.request.cookies: return self.request.cookies[name].value return default def set_cookie(self, name, value, domain=None, expires=None, path="/", expires_days=None, **kwargs): - """Sets the given cookie name/value with the given options. + """Sets an outgoing cookie name/value with the given options. - Additional keyword arguments are set on the Cookie.Morsel + Newly-set cookies are not immediately visible via `get_cookie`; + they are not present until the next request. + + expires may be a numeric timestamp as returned by `time.time`, + a time tuple as returned by `time.gmtime`, or a + `datetime.datetime` object. + + Additional keyword arguments are set on the cookies.Morsel directly. - See https://docs.python.org/2/library/cookie.html#Cookie.Morsel + See https://docs.python.org/3/library/http.cookies.html#http.cookies.Morsel for available attributes. """ # The cookie library only accepts type str, in both python 2 and 3 @@ -574,6 +591,9 @@ class RequestHandler(object): path and domain to clear a cookie as were used when that cookie was set (but there is no way to find out on the server side which values were used for a given cookie). + + Similar to `set_cookie`, the effect of this method will not be + seen until the following request. """ expires = datetime.datetime.utcnow() - datetime.timedelta(days=365) self.set_cookie(name, value="", path=path, expires=expires, @@ -585,6 +605,9 @@ class RequestHandler(object): See `clear_cookie` for more information on the path and domain parameters. + Similar to `set_cookie`, the effect of this method will not be + seen until the following request. + .. versionchanged:: 3.2 Added the ``path`` and ``domain`` parameters. @@ -609,6 +632,9 @@ class RequestHandler(object): Secure cookies may contain arbitrary byte values, not just unicode strings (unlike regular cookies) + Similar to `set_cookie`, the effect of this method will not be + seen until the following request. + .. versionchanged:: 3.2.1 Added the ``version`` argument. Introduced cookie version 2 @@ -648,6 +674,10 @@ class RequestHandler(object): The decoded cookie value is returned as a byte string (unlike `get_cookie`). + Similar to `get_cookie`, this method only returns cookies that + were present in the request. It does not see outgoing cookies set by + `set_secure_cookie` in this handler. + .. versionchanged:: 3.2.1 Added the ``min_version`` argument. Introduced cookie version 2; @@ -709,7 +739,8 @@ class RequestHandler(object): if not isinstance(chunk, (bytes, unicode_type, dict)): message = "write() only accepts bytes, unicode, and dict objects" if isinstance(chunk, list): - message += ". Lists not accepted for security reasons; see http://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.write" + message += ". Lists not accepted for security reasons; see " + \ + "http://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.write" raise TypeError(message) if isinstance(chunk, dict): chunk = escape.json_encode(chunk) @@ -718,7 +749,18 @@ class RequestHandler(object): self._write_buffer.append(chunk) def render(self, template_name, **kwargs): - """Renders the template with the given arguments as the response.""" + """Renders the template with the given arguments as the response. + + ``render()`` calls ``finish()``, so no other output methods can be called + after it. + + Returns a `.Future` with the same semantics as the one returned by `finish`. + Awaiting this `.Future` is optional. + + .. versionchanged:: 5.1 + + Now returns a `.Future` instead of ``None``. + """ if self._finished: raise RuntimeError("Cannot render() after finish()") html = self.render_string(template_name, **kwargs) @@ -779,7 +821,7 @@ class RequestHandler(object): if html_bodies: hloc = html.index(b'') html = html[:hloc] + b''.join(html_bodies) + b'\n' + html[hloc:] - self.finish(html) + return self.finish(html) def render_linked_js(self, js_files): """Default method used to render the final js links for the @@ -919,6 +961,11 @@ class RequestHandler(object): .. versionchanged:: 4.0 Now returns a `.Future` if no callback is given. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in + Tornado 6.0. """ chunk = b"".join(self._write_buffer) self._write_buffer = [] @@ -957,7 +1004,20 @@ class RequestHandler(object): return future def finish(self, chunk=None): - """Finishes this response, ending the HTTP request.""" + """Finishes this response, ending the HTTP request. + + Passing a ``chunk`` to ``finish()`` is equivalent to passing that + chunk to ``write()`` and then calling ``finish()`` with no arguments. + + Returns a `.Future` which may optionally be awaited to track the sending + of the response to the client. This `.Future` resolves when all the response + data has been sent, and raises an error if the connection is closed before all + data can be sent. + + .. versionchanged:: 5.1 + + Now returns a `.Future` instead of ``None``. + """ if self._finished: raise RuntimeError("finish() called twice") @@ -974,7 +1034,8 @@ class RequestHandler(object): if self.check_etag_header(): self._write_buffer = [] self.set_status(304) - if self._status_code in (204, 304): + if (self._status_code in (204, 304) or + (self._status_code >= 100 and self._status_code < 200)): assert not self._write_buffer, "Cannot send body with %s" % self._status_code self._clear_headers_for_304() elif "Content-Length" not in self._headers: @@ -988,12 +1049,27 @@ class RequestHandler(object): # are keepalive connections) self.request.connection.set_close_callback(None) - self.flush(include_footers=True) - self.request.finish() + future = self.flush(include_footers=True) + self.request.connection.finish() self._log() self._finished = True self.on_finish() self._break_cycles() + return future + + def detach(self): + """Take control of the underlying stream. + + Returns the underlying `.IOStream` object and stops all + further HTTP processing. Intended for implementing protocols + like websockets that tunnel over an HTTP handshake. + + This method is only supported when HTTP/1.1 is used. + + .. versionadded:: 5.1 + """ + self._finished = True + return self.request.connection.detach() def _break_cycles(self): # Break up a reference cycle between this handler and the @@ -1195,6 +1271,11 @@ class RequestHandler(object): See http://en.wikipedia.org/wiki/Cross-site_request_forgery + This property is of type `bytes`, but it contains only ASCII + characters. If a character string is required, there is no + need to base64-encode it; just decode the byte string as + UTF-8. + .. versionchanged:: 3.2.2 The xsrf token will now be have a random mask applied in every request, which makes it safe to include the token in pages @@ -1491,7 +1572,7 @@ class RequestHandler(object): if self._prepared_future is not None: # Tell the Application we've finished with prepare() # and are ready for the body to arrive. - self._prepared_future.set_result(None) + future_set_result_unless_cancelled(self._prepared_future, None) if self._finished: return @@ -1516,6 +1597,9 @@ class RequestHandler(object): self._handle_request_exception(e) except Exception: app_log.error("Exception in exception handler", exc_info=True) + finally: + # Unset result to avoid circular references + result = None if (self._prepared_future is not None and not self._prepared_future.done()): # In case we failed before setting _prepared_future, do it @@ -1561,11 +1645,7 @@ class RequestHandler(object): # send a response. return if isinstance(e, HTTPError): - if e.status_code not in httputil.responses and not e.reason: - gen_log.error("Bad HTTP status code: %d", e.status_code) - self.send_error(500, exc_info=sys.exc_info()) - else: - self.send_error(e.status_code, exc_info=sys.exc_info()) + self.send_error(e.status_code, exc_info=sys.exc_info()) else: self.send_error(500, exc_info=sys.exc_info()) @@ -1657,7 +1737,14 @@ def asynchronous(method): .. versionchanged:: 4.3 Returning anything but ``None`` or a yieldable object from a method decorated with ``@asynchronous`` is an error. Such return values were previously ignored silently. + + .. deprecated:: 5.1 + + This decorator is deprecated and will be removed in Tornado 6.0. + Use coroutines instead. """ + warnings.warn("@asynchronous is deprecated, use coroutines instead", + DeprecationWarning) # Delay the IOLoop import because it's not available on app engine. from tornado.ioloop import IOLoop @@ -1665,7 +1752,7 @@ def asynchronous(method): def wrapper(self, *args, **kwargs): self._auto_finish = False with stack_context.ExceptionStackContext( - self._stack_context_handle_exception): + self._stack_context_handle_exception, delay_warning=True): result = method(self, *args, **kwargs) if result is not None: result = gen.convert_yielded(result) @@ -1711,7 +1798,7 @@ def stream_request_body(cls): See the `file receiver demo `_ for example usage. - """ + """ # noqa: E501 if not issubclass(cls, RequestHandler): raise TypeError("expected subclass of RequestHandler, got %r", cls) cls._stream_request_body = True @@ -1859,6 +1946,17 @@ class Application(ReversibleRouter): If there's no match for the current request's host, then ``default_host`` parameter value is matched against host regular expressions. + + .. warning:: + + Applications that do not use TLS may be vulnerable to :ref:`DNS + rebinding ` attacks. This attack is especially + relevant to applications that only listen on ``127.0.0.1` or + other private networks. Appropriate host patterns must be used + (instead of the default of ``r'.*'``) to prevent this risk. The + ``default_host`` argument must not be used in applications that + may be vulnerable to DNS rebinding. + You can serve static files by sending the ``static_path`` setting as a keyword argument. We will serve those files from the ``/static/`` URI (this is configurable with the @@ -1869,6 +1967,7 @@ class Application(ReversibleRouter): .. versionchanged:: 4.5 Integration with the new `tornado.routing` module. + """ def __init__(self, handlers=None, default_host=None, transforms=None, **settings): @@ -2089,7 +2188,7 @@ class _HandlerDelegate(httputil.HTTPMessageDelegate): def finish(self): if self.stream_request_body: - self.request.body.set_result(None) + future_set_result_unless_cancelled(self.request.body, None) else: self.request.body = b''.join(self.chunks) self.request._parse_body() @@ -2146,11 +2245,11 @@ class HTTPError(Exception): :arg int status_code: HTTP status code. Must be listed in `httplib.responses ` unless the ``reason`` keyword argument is given. - :arg string log_message: Message to be written to the log for this error + :arg str log_message: Message to be written to the log for this error (will not be shown to the user unless the `Application` is in debug mode). May contain ``%s``-style placeholders, which will be filled in with remaining positional parameters. - :arg string reason: Keyword-only argument. The HTTP "reason" phrase + :arg str reason: Keyword-only argument. The HTTP "reason" phrase to pass in the status line along with ``status_code``. Normally determined automatically from ``status_code``, but can be used to use a non-standard numeric code. @@ -2256,13 +2355,21 @@ class RedirectHandler(RequestHandler): .. versionchanged:: 4.5 Added support for substitutions into the destination URL. + + .. versionchanged:: 5.0 + If any query arguments are present, they will be copied to the + destination URL. """ def initialize(self, url, permanent=True): self._url = url self._permanent = permanent def get(self, *args): - self.redirect(self._url.format(*args), permanent=self._permanent) + to_url = self._url.format(*args) + if self.request.query_arguments: + to_url = httputil.url_concat( + to_url, list(httputil.qs_to_qsl(self.request.query_arguments))) + self.redirect(to_url, permanent=self._permanent) class StaticFileHandler(RequestHandler): @@ -2467,8 +2574,9 @@ class StaticFileHandler(RequestHandler): .. versionadded:: 3.1 """ - if self.check_etag_header(): - return True + # If client sent If-None-Match, use it, ignore If-Modified-Since + if self.request.headers.get('If-None-Match'): + return self.check_etag_header() # Check the If-Modified-Since, and don't send the result if the # content has not been modified @@ -2773,6 +2881,7 @@ class FallbackHandler(RequestHandler): def prepare(self): self.fallback(self.request) self._finished = True + self.on_finish() class OutputTransform(object): @@ -2786,7 +2895,7 @@ class OutputTransform(object): pass def transform_first_chunk(self, status_code, headers, chunk, finishing): - # type: (int, httputil.HTTPHeaders, bytes, bool) -> typing.Tuple[int, httputil.HTTPHeaders, bytes] + # type: (int, httputil.HTTPHeaders, bytes, bool) -> typing.Tuple[int, httputil.HTTPHeaders, bytes] # noqa: E501 return status_code, headers, chunk def transform_chunk(self, chunk, finishing): @@ -2827,7 +2936,7 @@ class GZipContentEncoding(OutputTransform): return ctype.startswith('text/') or ctype in self.CONTENT_TYPES def transform_first_chunk(self, status_code, headers, chunk, finishing): - # type: (int, httputil.HTTPHeaders, bytes, bool) -> typing.Tuple[int, httputil.HTTPHeaders, bytes] + # type: (int, httputil.HTTPHeaders, bytes, bool) -> typing.Tuple[int, httputil.HTTPHeaders, bytes] # noqa: E501 # TODO: can/should this type be inherited from the superclass? if 'Vary' in headers: headers['Vary'] += ', Accept-Encoding' diff --git a/server/www/packages/packages-common/tornado/websocket.py b/server/www/packages/packages-common/tornado/websocket.py index 69437ee..0b994fc 100644 --- a/server/www/packages/packages-common/tornado/websocket.py +++ b/server/www/packages/packages-common/tornado/websocket.py @@ -17,24 +17,24 @@ the protocol (known as "draft 76") and are not compatible with this module. """ from __future__ import absolute_import, division, print_function -# Author: Jacob Kristhammar, 2010 import base64 -import collections import hashlib import os +import sys import struct import tornado.escape import tornado.web import zlib -from tornado.concurrent import TracebackFuture +from tornado.concurrent import Future, future_set_result_unless_cancelled from tornado.escape import utf8, native_str, to_unicode from tornado import gen, httpclient, httputil from tornado.ioloop import IOLoop, PeriodicCallback from tornado.iostream import StreamClosedError -from tornado.log import gen_log, app_log +from tornado.log import gen_log from tornado import simple_httpclient +from tornado.queues import Queue from tornado.tcpclient import TCPClient from tornado.util import _websocket_mask, PY3 @@ -44,6 +44,8 @@ if PY3: else: from urlparse import urlparse # py3 +_default_max_message_size = 10 * 1024 * 1024 + class WebSocketError(Exception): pass @@ -57,6 +59,10 @@ class WebSocketClosedError(WebSocketError): pass +class _DecompressTooLargeError(Exception): + pass + + class WebSocketHandler(tornado.web.RequestHandler): """Subclass this class to create a basic WebSocket handler. @@ -146,7 +152,6 @@ class WebSocketHandler(tornado.web.RequestHandler): self.stream = None self._on_close_called = False - @tornado.web.asynchronous def get(self, *args, **kwargs): self.open_args = args self.open_kwargs = kwargs @@ -226,7 +231,7 @@ class WebSocketHandler(tornado.web.RequestHandler): Default is 10MiB. """ - return self.settings.get('websocket_max_message_size', None) + return self.settings.get('websocket_max_message_size', _default_max_message_size) def write_message(self, message, binary=False): """Sends the given message to the client of this Web Socket. @@ -237,6 +242,7 @@ class WebSocketHandler(tornado.web.RequestHandler): is allowed. If the connection is already closed, raises `WebSocketClosedError`. + Returns a `.Future` which can be used for flow control. .. versionchanged:: 3.2 `WebSocketClosedError` was added (previously a closed connection @@ -244,6 +250,10 @@ class WebSocketHandler(tornado.web.RequestHandler): .. versionchanged:: 4.3 Returns a `.Future` which can be used for flow control. + + .. versionchanged:: 5.0 + Consistently raises `WebSocketClosedError`. Previously could + sometimes raise `.StreamClosedError`. """ if self.ws_connection is None: raise WebSocketClosedError() @@ -252,18 +262,38 @@ class WebSocketHandler(tornado.web.RequestHandler): return self.ws_connection.write_message(message, binary=binary) def select_subprotocol(self, subprotocols): - """Invoked when a new WebSocket requests specific subprotocols. + """Override to implement subprotocol negotiation. ``subprotocols`` is a list of strings identifying the subprotocols proposed by the client. This method may be overridden to return one of those strings to select it, or - ``None`` to not select a subprotocol. Failure to select a - subprotocol does not automatically abort the connection, - although clients may close the connection if none of their - proposed subprotocols was selected. + ``None`` to not select a subprotocol. + + Failure to select a subprotocol does not automatically abort + the connection, although clients may close the connection if + none of their proposed subprotocols was selected. + + The list may be empty, in which case this method must return + None. This method is always called exactly once even if no + subprotocols were proposed so that the handler can be advised + of this fact. + + .. versionchanged:: 5.1 + + Previously, this method was called with a list containing + an empty string instead of an empty list if no subprotocols + were proposed by the client. """ return None + @property + def selected_subprotocol(self): + """The subprotocol returned by `select_subprotocol`. + + .. versionadded:: 5.1 + """ + return self.ws_connection.selected_subprotocol + def get_compression_options(self): """Override to return compression options for the connection. @@ -294,6 +324,13 @@ class WebSocketHandler(tornado.web.RequestHandler): The arguments to `open` are extracted from the `tornado.web.URLSpec` regular expression, just like the arguments to `tornado.web.RequestHandler.get`. + + `open` may be a coroutine. `on_message` will not be called until + `open` has returned. + + .. versionchanged:: 5.1 + + ``open`` may be a coroutine. """ pass @@ -308,8 +345,23 @@ class WebSocketHandler(tornado.web.RequestHandler): """ raise NotImplementedError - def ping(self, data): - """Send ping frame to the remote end.""" + def ping(self, data=b''): + """Send ping frame to the remote end. + + The data argument allows a small amount of data (up to 125 + bytes) to be sent as a part of the ping message. Note that not + all websocket implementations expose this data to + applications. + + Consider using the ``websocket_ping_interval`` application + setting instead of sending pings manually. + + .. versionchanged:: 5.1 + + The data argument is now optional. + + """ + data = utf8(data) if self.ws_connection is None: raise WebSocketClosedError() self.ws_connection.write_ping(data) @@ -462,7 +514,7 @@ class WebSocketHandler(tornado.web.RequestHandler): self, compression_options=self.get_compression_options()) def _attach_stream(self): - self.stream = self.request.connection.detach() + self.stream = self.detach() self.stream.set_close_callback(self.on_connection_close) # disable non-WS methods for method in ["write", "redirect", "set_header", "set_cookie", @@ -493,8 +545,7 @@ class WebSocketProtocol(object): try: result = callback(*args, **kwargs) except Exception: - app_log.error("Uncaught exception in %s", - getattr(self.request, 'path', None), exc_info=True) + self.handler.log_exception(*sys.exc_info()) self._abort() else: if result is not None: @@ -539,7 +590,8 @@ class _PerMessageDeflateCompressor(object): self._compressor = None def _create_compressor(self): - return zlib.compressobj(self._compression_level, zlib.DEFLATED, -self._max_wbits, self._mem_level) + return zlib.compressobj(self._compression_level, + zlib.DEFLATED, -self._max_wbits, self._mem_level) def compress(self, data): compressor = self._compressor or self._create_compressor() @@ -550,7 +602,8 @@ class _PerMessageDeflateCompressor(object): class _PerMessageDeflateDecompressor(object): - def __init__(self, persistent, max_wbits, compression_options=None): + def __init__(self, persistent, max_wbits, max_message_size, compression_options=None): + self._max_message_size = max_message_size if max_wbits is None: max_wbits = zlib.MAX_WBITS if not (8 <= max_wbits <= zlib.MAX_WBITS): @@ -567,7 +620,10 @@ class _PerMessageDeflateDecompressor(object): def decompress(self, data): decompressor = self._decompressor or self._create_decompressor() - return decompressor.decompress(data + b'\x00\x00\xff\xff') + result = decompressor.decompress(data + b'\x00\x00\xff\xff', self._max_message_size) + if decompressor.unconsumed_tail: + raise _DecompressTooLargeError() + return result class WebSocketProtocol13(WebSocketProtocol): @@ -616,6 +672,14 @@ class WebSocketProtocol13(WebSocketProtocol): def accept_connection(self): try: self._handle_websocket_headers() + except ValueError: + self.handler.set_status(400) + log_msg = "Missing/Invalid WebSocket headers" + self.handler.finish(log_msg) + gen_log.debug(log_msg) + return + + try: self._accept_connection() except ValueError: gen_log.debug("Malformed WebSocket request received", @@ -647,14 +711,17 @@ class WebSocketProtocol13(WebSocketProtocol): return WebSocketProtocol13.compute_accept_value( self.request.headers.get("Sec-Websocket-Key")) + @gen.coroutine def _accept_connection(self): - subprotocols = self.request.headers.get("Sec-WebSocket-Protocol", '') - subprotocols = [s.strip() for s in subprotocols.split(',')] - if subprotocols: - selected = self.handler.select_subprotocol(subprotocols) - if selected: - assert selected in subprotocols - self.handler.set_header("Sec-WebSocket-Protocol", selected) + subprotocol_header = self.request.headers.get("Sec-WebSocket-Protocol") + if subprotocol_header: + subprotocols = [s.strip() for s in subprotocol_header.split(',')] + else: + subprotocols = [] + self.selected_subprotocol = self.handler.select_subprotocol(subprotocols) + if self.selected_subprotocol: + assert self.selected_subprotocol in subprotocols + self.handler.set_header("Sec-WebSocket-Protocol", self.selected_subprotocol) extensions = self._parse_extensions_header(self.request.headers) for ext in extensions: @@ -684,9 +751,11 @@ class WebSocketProtocol13(WebSocketProtocol): self.stream = self.handler.stream self.start_pinging() - self._run_callback(self.handler.open, *self.handler.open_args, - **self.handler.open_kwargs) - self._receive_frame() + open_result = self._run_callback(self.handler.open, *self.handler.open_args, + **self.handler.open_kwargs) + if open_result is not None: + yield open_result + yield self._receive_frame_loop() def _parse_extensions_header(self, headers): extensions = headers.get("Sec-WebSocket-Extensions", '') @@ -713,6 +782,8 @@ class WebSocketProtocol13(WebSocketProtocol): else: raise ValueError("unsupported extension %r", ext) + self.selected_subprotocol = headers.get('Sec-WebSocket-Protocol', None) + def _get_compressor_options(self, side, agreed_parameters, compression_options=None): """Converts a websocket agreed_parameters set to keyword arguments for our compressor objects. @@ -740,34 +811,39 @@ class WebSocketProtocol13(WebSocketProtocol): self._compressor = _PerMessageDeflateCompressor( **self._get_compressor_options(side, agreed_parameters, compression_options)) self._decompressor = _PerMessageDeflateDecompressor( + max_message_size=self.handler.max_message_size, **self._get_compressor_options(other_side, agreed_parameters, compression_options)) def _write_frame(self, fin, opcode, data, flags=0): + data_len = len(data) + if opcode & 0x8: + # All control frames MUST have a payload length of 125 + # bytes or less and MUST NOT be fragmented. + if not fin: + raise ValueError("control frames may not be fragmented") + if data_len > 125: + raise ValueError("control frame payloads may not exceed 125 bytes") if fin: finbit = self.FIN else: finbit = 0 frame = struct.pack("B", finbit | opcode | flags) - l = len(data) if self.mask_outgoing: mask_bit = 0x80 else: mask_bit = 0 - if l < 126: - frame += struct.pack("B", l | mask_bit) - elif l <= 0xFFFF: - frame += struct.pack("!BH", 126 | mask_bit, l) + if data_len < 126: + frame += struct.pack("B", data_len | mask_bit) + elif data_len <= 0xFFFF: + frame += struct.pack("!BH", 126 | mask_bit, data_len) else: - frame += struct.pack("!BQ", 127 | mask_bit, l) + frame += struct.pack("!BQ", 127 | mask_bit, data_len) if self.mask_outgoing: mask = os.urandom(4) data = mask + _websocket_mask(mask, data) frame += data self._wire_bytes_out += len(frame) - try: - return self.stream.write(frame) - except StreamClosedError: - self._abort() + return self.stream.write(frame) def write_message(self, message, binary=False): """Sends the given message to the client of this Web Socket.""" @@ -782,118 +858,107 @@ class WebSocketProtocol13(WebSocketProtocol): if self._compressor: message = self._compressor.compress(message) flags |= self.RSV1 - return self._write_frame(True, opcode, message, flags=flags) + # For historical reasons, write methods in Tornado operate in a semi-synchronous + # mode in which awaiting the Future they return is optional (But errors can + # still be raised). This requires us to go through an awkward dance here + # to transform the errors that may be returned while presenting the same + # semi-synchronous interface. + try: + fut = self._write_frame(True, opcode, message, flags=flags) + except StreamClosedError: + raise WebSocketClosedError() + + @gen.coroutine + def wrapper(): + try: + yield fut + except StreamClosedError: + raise WebSocketClosedError() + return wrapper() def write_ping(self, data): """Send ping frame.""" assert isinstance(data, bytes) self._write_frame(True, 0x9, data) - def _receive_frame(self): + @gen.coroutine + def _receive_frame_loop(self): try: - self.stream.read_bytes(2, self._on_frame_start) + while not self.client_terminated: + yield self._receive_frame() except StreamClosedError: self._abort() - def _on_frame_start(self, data): - self._wire_bytes_in += len(data) - header, payloadlen = struct.unpack("BB", data) - self._final_frame = header & self.FIN + def _read_bytes(self, n): + self._wire_bytes_in += n + return self.stream.read_bytes(n) + + @gen.coroutine + def _receive_frame(self): + # Read the frame header. + data = yield self._read_bytes(2) + header, mask_payloadlen = struct.unpack("BB", data) + is_final_frame = header & self.FIN reserved_bits = header & self.RSV_MASK - self._frame_opcode = header & self.OPCODE_MASK - self._frame_opcode_is_control = self._frame_opcode & 0x8 - if self._decompressor is not None and self._frame_opcode != 0: + opcode = header & self.OPCODE_MASK + opcode_is_control = opcode & 0x8 + if self._decompressor is not None and opcode != 0: + # Compression flag is present in the first frame's header, + # but we can't decompress until we have all the frames of + # the message. self._frame_compressed = bool(reserved_bits & self.RSV1) reserved_bits &= ~self.RSV1 if reserved_bits: # client is using as-yet-undefined extensions; abort self._abort() return - self._masked_frame = bool(payloadlen & 0x80) - payloadlen = payloadlen & 0x7f - if self._frame_opcode_is_control and payloadlen >= 126: + is_masked = bool(mask_payloadlen & 0x80) + payloadlen = mask_payloadlen & 0x7f + + # Parse and validate the length. + if opcode_is_control and payloadlen >= 126: # control frames must have payload < 126 self._abort() return - try: - if payloadlen < 126: - self._frame_length = payloadlen - if self._masked_frame: - self.stream.read_bytes(4, self._on_masking_key) - else: - self._read_frame_data(False) - elif payloadlen == 126: - self.stream.read_bytes(2, self._on_frame_length_16) - elif payloadlen == 127: - self.stream.read_bytes(8, self._on_frame_length_64) - except StreamClosedError: - self._abort() - - def _read_frame_data(self, masked): - new_len = self._frame_length + if payloadlen < 126: + self._frame_length = payloadlen + elif payloadlen == 126: + data = yield self._read_bytes(2) + payloadlen = struct.unpack("!H", data)[0] + elif payloadlen == 127: + data = yield self._read_bytes(8) + payloadlen = struct.unpack("!Q", data)[0] + new_len = payloadlen if self._fragmented_message_buffer is not None: new_len += len(self._fragmented_message_buffer) - if new_len > (self.handler.max_message_size or 10 * 1024 * 1024): + if new_len > self.handler.max_message_size: self.close(1009, "message too big") + self._abort() return - self.stream.read_bytes( - self._frame_length, - self._on_masked_frame_data if masked else self._on_frame_data) - def _on_frame_length_16(self, data): - self._wire_bytes_in += len(data) - self._frame_length = struct.unpack("!H", data)[0] - try: - if self._masked_frame: - self.stream.read_bytes(4, self._on_masking_key) - else: - self._read_frame_data(False) - except StreamClosedError: - self._abort() + # Read the payload, unmasking if necessary. + if is_masked: + self._frame_mask = yield self._read_bytes(4) + data = yield self._read_bytes(payloadlen) + if is_masked: + data = _websocket_mask(self._frame_mask, data) - def _on_frame_length_64(self, data): - self._wire_bytes_in += len(data) - self._frame_length = struct.unpack("!Q", data)[0] - try: - if self._masked_frame: - self.stream.read_bytes(4, self._on_masking_key) - else: - self._read_frame_data(False) - except StreamClosedError: - self._abort() - - def _on_masking_key(self, data): - self._wire_bytes_in += len(data) - self._frame_mask = data - try: - self._read_frame_data(True) - except StreamClosedError: - self._abort() - - def _on_masked_frame_data(self, data): - # Don't touch _wire_bytes_in; we'll do it in _on_frame_data. - self._on_frame_data(_websocket_mask(self._frame_mask, data)) - - def _on_frame_data(self, data): - handled_future = None - - self._wire_bytes_in += len(data) - if self._frame_opcode_is_control: + # Decide what to do with this frame. + if opcode_is_control: # control frames may be interleaved with a series of fragmented # data frames, so control frames must not interact with # self._fragmented_* - if not self._final_frame: + if not is_final_frame: # control frames must not be fragmented self._abort() return - opcode = self._frame_opcode - elif self._frame_opcode == 0: # continuation frame + elif opcode == 0: # continuation frame if self._fragmented_message_buffer is None: # nothing to continue self._abort() return self._fragmented_message_buffer += data - if self._final_frame: + if is_final_frame: opcode = self._fragmented_message_opcode data = self._fragmented_message_buffer self._fragmented_message_buffer = None @@ -902,22 +967,14 @@ class WebSocketProtocol13(WebSocketProtocol): # can't start new message until the old one is finished self._abort() return - if self._final_frame: - opcode = self._frame_opcode - else: - self._fragmented_message_opcode = self._frame_opcode + if not is_final_frame: + self._fragmented_message_opcode = opcode self._fragmented_message_buffer = data - if self._final_frame: + if is_final_frame: handled_future = self._handle_message(opcode, data) - - if not self.client_terminated: - if handled_future: - # on_message is a coroutine, process more frames once it's done. - handled_future.add_done_callback( - lambda future: self._receive_frame()) - else: - self._receive_frame() + if handled_future is not None: + yield handled_future def _handle_message(self, opcode, data): """Execute on_message, returning its Future if it is a coroutine.""" @@ -925,7 +982,12 @@ class WebSocketProtocol13(WebSocketProtocol): return if self._frame_compressed: - data = self._decompressor.decompress(data) + try: + data = self._decompressor.decompress(data) + except _DecompressTooLargeError: + self.close(1009, "message too big after decompression") + self._abort() + return if opcode == 0x1: # UTF-8 data @@ -951,7 +1013,10 @@ class WebSocketProtocol13(WebSocketProtocol): self.close(self.handler.close_code) elif opcode == 0x9: # Ping - self._write_frame(True, 0xA, data) + try: + self._write_frame(True, 0xA, data) + except StreamClosedError: + self._abort() self._run_callback(self.handler.on_ping, data) elif opcode == 0xA: # Pong @@ -972,7 +1037,10 @@ class WebSocketProtocol13(WebSocketProtocol): close_data = struct.pack('>H', code) if reason is not None: close_data += utf8(reason) - self._write_frame(True, 0x8, close_data) + try: + self._write_frame(True, 0x8, close_data) + except StreamClosedError: + self._abort() self.server_terminated = True if self.client_terminated: if self._waiting is not None: @@ -1037,14 +1105,13 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): This class should not be instantiated directly; use the `websocket_connect` function instead. """ - def __init__(self, io_loop, request, on_message_callback=None, + def __init__(self, request, on_message_callback=None, compression_options=None, ping_interval=None, ping_timeout=None, - max_message_size=None): + max_message_size=None, subprotocols=[]): self.compression_options = compression_options - self.connect_future = TracebackFuture() + self.connect_future = Future() self.protocol = None - self.read_future = None - self.read_queue = collections.deque() + self.read_queue = Queue(1) self.key = base64.b64encode(os.urandom(16)) self._on_message_callback = on_message_callback self.close_code = self.close_reason = None @@ -1061,6 +1128,8 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): 'Sec-WebSocket-Key': self.key, 'Sec-WebSocket-Version': '13', }) + if subprotocols is not None: + request.headers['Sec-WebSocket-Protocol'] = ','.join(subprotocols) if self.compression_options is not None: # Always offer to let the server set our max_wbits (and even though # we don't offer it, we will accept a client_no_context_takeover @@ -1070,9 +1139,9 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): request.headers['Sec-WebSocket-Extensions'] = ( 'permessage-deflate; client_max_window_bits') - self.tcp_client = TCPClient(io_loop=io_loop) + self.tcp_client = TCPClient() super(WebSocketClientConnection, self).__init__( - io_loop, None, request, lambda: None, self._on_http_response, + None, request, lambda: None, self._on_http_response, 104857600, self.tcp_client, 65536, 104857600) def close(self, code=None, reason=None): @@ -1115,7 +1184,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): self.protocol = self.get_websocket_protocol() self.protocol._process_server_headers(self.key, self.headers) self.protocol.start_pinging() - self.protocol._receive_frame() + IOLoop.current().add_callback(self.protocol._receive_frame_loop) if self._timeout is not None: self.io_loop.remove_timeout(self._timeout) @@ -1129,11 +1198,19 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): # ability to see exceptions. self.final_callback = None - self.connect_future.set_result(self) + future_set_result_unless_cancelled(self.connect_future, self) def write_message(self, message, binary=False): - """Sends a message to the WebSocket server.""" - return self.protocol.write_message(message, binary) + """Sends a message to the WebSocket server. + + If the stream is closed, raises `WebSocketClosedError`. + Returns a `.Future` which can be used for flow control. + + .. versionchanged:: 5.0 + Exception raised on a closed stream changed from `.StreamClosedError` + to `WebSocketClosedError`. + """ + return self.protocol.write_message(message, binary=binary) def read_message(self, callback=None): """Reads a message from the WebSocket server. @@ -1146,12 +1223,8 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): is given it will be called with the future when it is ready. """ - assert self.read_future is None - future = TracebackFuture() - if self.read_queue: - future.set_result(self.read_queue.popleft()) - else: - self.read_future = future + + future = self.read_queue.get() if callback is not None: self.io_loop.add_future(future, callback) return future @@ -1159,11 +1232,27 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): def on_message(self, message): if self._on_message_callback: self._on_message_callback(message) - elif self.read_future is not None: - self.read_future.set_result(message) - self.read_future = None else: - self.read_queue.append(message) + return self.read_queue.put(message) + + def ping(self, data=b''): + """Send ping frame to the remote end. + + The data argument allows a small amount of data (up to 125 + bytes) to be sent as a part of the ping message. Note that not + all websocket implementations expose this data to + applications. + + Consider using the ``ping_interval`` argument to + `websocket_connect` instead of sending pings manually. + + .. versionadded:: 5.1 + + """ + data = utf8(data) + if self.protocol is None: + raise WebSocketClosedError() + self.protocol.write_ping(data) def on_pong(self, data): pass @@ -1175,11 +1264,19 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): return WebSocketProtocol13(self, mask_outgoing=True, compression_options=self.compression_options) + @property + def selected_subprotocol(self): + """The subprotocol selected by the server. -def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None, + .. versionadded:: 5.1 + """ + return self.protocol.selected_subprotocol + + +def websocket_connect(url, callback=None, connect_timeout=None, on_message_callback=None, compression_options=None, ping_interval=None, ping_timeout=None, - max_message_size=None): + max_message_size=_default_max_message_size, subprotocols=None): """Client-side websocket support. Takes a url and returns a Future whose result is a @@ -1202,19 +1299,27 @@ def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None, ``websocket_connect``. In both styles, a message of ``None`` indicates that the connection has been closed. + ``subprotocols`` may be a list of strings specifying proposed + subprotocols. The selected protocol may be found on the + ``selected_subprotocol`` attribute of the connection object + when the connection is complete. + .. versionchanged:: 3.2 Also accepts ``HTTPRequest`` objects in place of urls. .. versionchanged:: 4.1 Added ``compression_options`` and ``on_message_callback``. - The ``io_loop`` argument is deprecated. .. versionchanged:: 4.5 Added the ``ping_interval``, ``ping_timeout``, and ``max_message_size`` arguments, which have the same meaning as in `WebSocketHandler`. + + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + + .. versionchanged:: 5.1 + Added the ``subprotocols`` argument. """ - if io_loop is None: - io_loop = IOLoop.current() if isinstance(url, httpclient.HTTPRequest): assert connect_timeout is None request = url @@ -1225,12 +1330,13 @@ def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None, request = httpclient.HTTPRequest(url, connect_timeout=connect_timeout) request = httpclient._RequestProxy( request, httpclient.HTTPRequest._DEFAULTS) - conn = WebSocketClientConnection(io_loop, request, + conn = WebSocketClientConnection(request, on_message_callback=on_message_callback, compression_options=compression_options, ping_interval=ping_interval, ping_timeout=ping_timeout, - max_message_size=max_message_size) + max_message_size=max_message_size, + subprotocols=subprotocols) if callback is not None: - io_loop.add_future(conn.connect_future, callback) + IOLoop.current().add_future(conn.connect_future, callback) return conn.connect_future diff --git a/server/www/packages/packages-common/tornado/wsgi.py b/server/www/packages/packages-common/tornado/wsgi.py index 68a7615..e1230da 100644 --- a/server/www/packages/packages-common/tornado/wsgi.py +++ b/server/www/packages/packages-common/tornado/wsgi.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright 2009 Facebook # @@ -34,6 +33,7 @@ from __future__ import absolute_import, division, print_function import sys from io import BytesIO import tornado +import warnings from tornado.concurrent import Future from tornado import escape @@ -77,6 +77,7 @@ class WSGIApplication(web.Application): .. deprecated:: 4.0 Use a regular `.Application` and wrap it in `WSGIAdapter` instead. + This class will be removed in Tornado 6.0. """ def __call__(self, environ, start_response): return WSGIAdapter(self)(environ, start_response) @@ -84,8 +85,10 @@ class WSGIApplication(web.Application): # WSGI has no facilities for flow control, so just return an already-done # Future when the interface requires it. -_dummy_future = Future() -_dummy_future.set_result(None) +def _dummy_future(): + f = Future() + f.set_result(None) + return f class _WSGIConnection(httputil.HTTPConnection): @@ -117,7 +120,7 @@ class _WSGIConnection(httputil.HTTPConnection): self.write(chunk, callback) elif callback is not None: callback() - return _dummy_future + return _dummy_future() def write(self, chunk, callback=None): if self._expected_content_remaining is not None: @@ -129,7 +132,7 @@ class _WSGIConnection(httputil.HTTPConnection): self._write_buffer.append(chunk) if callback is not None: callback() - return _dummy_future + return _dummy_future() def finish(self): if (self._expected_content_remaining is not None and @@ -180,9 +183,25 @@ class WSGIAdapter(object): that it is not possible to use `.AsyncHTTPClient`, or the `tornado.auth` or `tornado.websocket` modules. + In multithreaded WSGI servers on Python 3, it may be necessary to + permit `asyncio` to create event loops on any thread. Run the + following at startup (typically import time for WSGI + applications):: + + import asyncio + from tornado.platform.asyncio import AnyThreadEventLoopPolicy + asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy()) + .. versionadded:: 4.0 + + .. deprecated:: 5.1 + + This class is deprecated and will be removed in Tornado 6.0. + Use Tornado's `.HTTPServer` instead of a WSGI container. """ def __init__(self, application): + warnings.warn("WSGIAdapter is deprecated, use Tornado's HTTPServer instead", + DeprecationWarning) if isinstance(application, WSGIApplication): self.application = lambda request: web.Application.__call__( application, request) diff --git a/server/www/teleport/webroot/app/base/webapp.py b/server/www/teleport/webroot/app/base/webapp.py index 05f8186..654715d 100644 --- a/server/www/teleport/webroot/app/base/webapp.py +++ b/server/www/teleport/webroot/app/base/webapp.py @@ -5,12 +5,14 @@ import os import time import urllib.parse import urllib.request +import asyncio import tornado.httpserver import tornado.ioloop import tornado.netutil import tornado.process import tornado.web +import tornado.platform.asyncio from app.const import * from app.base.configs import tp_cfg from app.base.db import get_db @@ -30,6 +32,8 @@ class WebApp: def init(self, path_app_root, path_data): log.initialize() + asyncio.set_event_loop_policy(tornado.platform.asyncio.AnyThreadEventLoopPolicy()) + cfg = tp_cfg() cfg.app_path = path_app_root cfg.static_path = os.path.join(path_app_root, 'static')