예제 #1
0
    def _get_finished_message(self, function):
        """
        Helper to implement :py:meth:`get_finished` and
        :py:meth:`get_peer_finished`.

        :param function: Either :py:data:`SSL_get_finished`: or
            :py:data:`SSL_get_peer_finished`.

        :return: :py:data:`None` if the desired message has not yet been
            received, otherwise the contents of the message.
        :rtype: :py:class:`bytes` or :py:class:`NoneType`
        """
        # The OpenSSL documentation says nothing about what might happen if the
        # count argument given is zero.  Specifically, it doesn't say whether
        # the output buffer may be NULL in that case or not.  Inspection of the
        # implementation reveals that it calls memcpy() unconditionally.
        # Section 7.1.4, paragraph 1 of the C standard suggests that
        # memcpy(NULL, source, 0) is not guaranteed to produce defined (let
        # alone desirable) behavior (though it probably does on just about
        # every implementation...)
        #
        # Allocate a tiny buffer to pass in (instead of just passing NULL as
        # one might expect) for the initial call so as to be safe against this
        # potentially undefined behavior.
        empty = _ffi.new("char[]", 0)
        size = function(self._ssl, empty, 0)
        if size == 0:
            # No Finished message so far.
            return None

        buf = _ffi.new("char[]", size)
        function(self._ssl, buf, size)
        return _ffi.buffer(buf, size)[:]
예제 #2
0
파일: SSL.py 프로젝트: samucc/pyopenssl
    def _get_finished_message(self, function):
        """
        Helper to implement :py:meth:`get_finished` and
        :py:meth:`get_peer_finished`.

        :param function: Either :py:data:`SSL_get_finished`: or
            :py:data:`SSL_get_peer_finished`.

        :return: :py:data:`None` if the desired message has not yet been
            received, otherwise the contents of the message.
        :rtype: :py:class:`bytes` or :py:class:`NoneType`
        """
        # The OpenSSL documentation says nothing about what might happen if the
        # count argument given is zero.  Specifically, it doesn't say whether
        # the output buffer may be NULL in that case or not.  Inspection of the
        # implementation reveals that it calls memcpy() unconditionally.
        # Section 7.1.4, paragraph 1 of the C standard suggests that
        # memcpy(NULL, source, 0) is not guaranteed to produce defined (let
        # alone desirable) behavior (though it probably does on just about
        # every implementation...)
        #
        # Allocate a tiny buffer to pass in (instead of just passing NULL as
        # one might expect) for the initial call so as to be safe against this
        # potentially undefined behavior.
        empty = _ffi.new("char[]", 0)
        size = function(self._ssl, empty, 0)
        if size == 0:
            # No Finished message so far.
            return None

        buf = _ffi.new("char[]", size)
        function(self._ssl, buf, size)
        return _ffi.buffer(buf, size)[:]
예제 #3
0
파일: SSL.py 프로젝트: Lukasa/pyopenssl
 def wrapper(ssl, out, outlen, arg):
     outstr = callback(Connection._reverse_mapping[ssl])
     self._npn_advertise_callback_args = [
         _ffi.new("unsigned int *", len(outstr)),
         _ffi.new("unsigned char[]", outstr),
     ]
     outlen[0] = self._npn_advertise_callback_args[0][0]
     out[0] = self._npn_advertise_callback_args[1]
     return 0
예제 #4
0
파일: SSL.py 프로젝트: Lukasa/pyopenssl
 def wrapper(ssl, out, outlen, in_, inlen, arg):
     outstr = callback(
         Connection._reverse_mapping[ssl], _ffi.string(in_))
     self._npn_select_callback_args = [
         _ffi.new("unsigned char *", len(outstr)),
         _ffi.new("unsigned char[]", outstr),
     ]
     outlen[0] = self._npn_select_callback_args[0][0]
     out[0] = self._npn_select_callback_args[1]
     return 0
예제 #5
0
파일: SSL.py 프로젝트: Lukasa/pyopenssl
    def get_next_proto_negotiated(self):
        """
        Get the protocol that was negotiated by NPN.
        """
        data = _ffi.new("unsigned char **")
        data_len = _ffi.new("unsigned int *")

        _lib.SSL_get0_next_proto_negotiated(self._ssl, data, data_len)

        if not data_len[0]:
            return ""
        else:
            return _ffi.string(data[0])
예제 #6
0
def get_csr(client, key_id, key_version_id, subject_name, domain,
            kms_algorithm, signature_algorithm):
    clear_text_public_key_pem = get_public_key(client, key_id, key_version_id)

    # kms get_public_key
    pkey = load_publickey(FILETYPE_PEM, clear_text_public_key_pem)

    req = X509Req()
    req.set_pubkey(pkey)

    req.get_subject().CN = subject_name.get('CN')
    req.get_subject().C = subject_name.get('C')
    req.get_subject().O = subject_name.get('O')
    req.set_version(0)
    # addExtensions
    req.add_extensions([
        X509Extension(b'subjectAltName', False,
                      ','.join(domain).encode('ascii'))
    ])

    result_buffer = _ffi.new('unsigned char**')
    encode_result = _lib.i2d_re_X509_REQ_tbs(req._req, result_buffer)

    md_length = _ffi.new("unsigned int *")
    md = _ffi.new("unsigned char[]", 32)
    evp_md = _lib.EVP_get_digestbyname(b"sha256")

    md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
    md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
    _lib.EVP_DigestInit_ex(md_ctx, evp_md, _ffi.NULL)
    _lib.EVP_DigestUpdate(md_ctx, result_buffer[0], encode_result)
    _lib.EVP_DigestFinal_ex(md_ctx, md, md_length)

    psig = _ffi.new("ASN1_BIT_STRING **")
    palg = _ffi.new("X509_ALGOR **")
    _lib.X509_REQ_get0_signature(req._req, psig, palg)

    # kms_sign
    sign_data = kms_sign(client, key_id, key_version_id, kms_algorithm,
                         bytes(md))

    _lib.ASN1_STRING_set(psig[0], sign_data, len(sign_data))
    psig[0].flags &= ~(0x08 | 0x07)
    psig[0].flags |= 0x08

    _lib.OPENSSL_free(result_buffer[0])

    palg[0].algorithm = _lib.OBJ_nid2obj(_lib.OBJ_sn2nid(signature_algorithm))

    csr_pem_str = dump_certificate_request(FILETYPE_PEM, req)
    return csr_pem_str
예제 #7
0
    def sendall(self, buf, flags=0):
        """
        Send "all" data on the connection. This calls send() repeatedly until
        all data is sent. If an error occurs, it's impossible to tell how much
        data has been sent.

        :param buf: The string, buffer or memoryview to send
        :param flags: (optional) Included for compatibility with the socket
                      API, the value is ignored
        :return: The number of bytes written
        """
        if isinstance(buf, _memoryview):
            buf = buf.tobytes()
        if isinstance(buf, unicode):
	    try:
	        buf = str(buf)
	    except:
                raise TypeError("couldn't convert unicode buf to byte string")
        if isinstance(buf, _buffer):
            buf = str(buf)
        if not isinstance(buf, bytes):
            raise TypeError("buf must be a memoryview, buffer or byte string")

        left_to_send = len(buf)
        total_sent = 0
        data = _ffi.new("char[]", buf)

        while left_to_send:
            result = _lib.SSL_write(self._ssl, data + total_sent, left_to_send)
            self._raise_ssl_error(self._ssl, result)
            total_sent += result
            left_to_send -= result
예제 #8
0
    def sendall(self, buf, flags=0):
        """
        Send "all" data on the connection. This calls send() repeatedly until
        all data is sent. If an error occurs, it's impossible to tell how much
        data has been sent.

        :param buf: The string to send
        :param flags: (optional) Included for compatibility with the socket
                      API, the value is ignored
        :return: The number of bytes written
        """
        if isinstance(buf, _memoryview):
            buf = buf.tobytes()
        if not isinstance(buf, bytes):
            raise TypeError("buf must be a byte string")

        left_to_send = len(buf)
        total_sent = 0
        data = _ffi.new("char[]", buf)

        while left_to_send:
            result = _lib.SSL_write(self._ssl, data + total_sent, left_to_send)
            self._raise_ssl_error(self._ssl, result)
            total_sent += result
            left_to_send -= result
예제 #9
0
파일: ca.py 프로젝트: delroth/sslenroll
 def wrapper(b64, lib=lib):
     if isinstance(b64, str):
         b64 = b64.encode('ascii')
     b64_ptr = _sslffi.new('char[]', b64)
     spki_obj = lib.NETSCAPE_SPKI_b64_decode(b64_ptr, len(b64))
     if spki_obj == cffi.NULL:
         raise ValueError("Invalid SPKI base64")
     def free(spki_obj, ref=b64_ptr):
         _ssllib.NETSCAPE_SPKI_free(spki_obj)
     return _sslffi.gc(spki_obj, free)
예제 #10
0
    def b64_decode(cls, spkac_str):
        """
        Construct a NetscapeSPKI from spkac base64 string

        :param spkac_str: base64 encoded string
        """

        new = cls()
        arg = _ffi.new('char[]', spkac_str)
        spki = _lib.NETSCAPE_SPKI_b64_decode(arg, -1)
        if spki == _ffi.NULL:
            raise ValueError('Invalid SPKAC string')
        new._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
        return new
예제 #11
0
    def recv(self, bufsiz, flags=None):
        """
        Receive data on the connection. NOTE: If you get one of the WantRead,
        WantWrite or WantX509Lookup exceptions on this, you have to call the
        method again with the SAME buffer.

        :param bufsiz: The maximum number of bytes to read
        :param flags: (optional) Included for compatibility with the socket
                      API, the value is ignored
        :return: The string read from the Connection
        """
        buf = _ffi.new("char[]", bufsiz)
        result = _lib.SSL_read(self._ssl, buf, bufsiz)
        self._raise_ssl_error(self._ssl, result)
        return _ffi.buffer(buf, result)[:]
예제 #12
0
    def recv(self, bufsiz, flags=None):
        """
        Receive data on the connection. NOTE: If you get one of the WantRead,
        WantWrite or WantX509Lookup exceptions on this, you have to call the
        method again with the SAME buffer.

        :param bufsiz: The maximum number of bytes to read
        :param flags: (optional) Included for compatibility with the socket
                      API, the value is ignored
        :return: The string read from the Connection
        """
        buf = _ffi.new("char[]", bufsiz)
        result = _lib.SSL_read(self._ssl, buf, bufsiz)
        self._raise_ssl_error(self._ssl, result)
        return _ffi.buffer(buf, result)[:]
예제 #13
0
    def bio_read(self, bufsiz):
        """
        When using non-socket connections this function reads the "dirty" data
        that would have traveled away on the network.

        :param bufsiz: The maximum number of bytes to read
        :return: The string read.
        """
        if self._from_ssl is None:
            raise TypeError("Connection sock was not None")

        if not isinstance(bufsiz, integer_types):
            raise TypeError("bufsiz must be an integer")

        buf = _ffi.new("char[]", bufsiz)
        result = _lib.BIO_read(self._from_ssl, buf, bufsiz)
        if result <= 0:
            self._handle_bio_errors(self._from_ssl, result)

        return _ffi.buffer(buf, result)[:]
예제 #14
0
    def bio_read(self, bufsiz):
        """
        When using non-socket connections this function reads the "dirty" data
        that would have traveled away on the network.

        :param bufsiz: The maximum number of bytes to read
        :return: The string read.
        """
        if self._from_ssl is None:
            raise TypeError("Connection sock was not None")

        if not isinstance(bufsiz, integer_types):
            raise TypeError("bufsiz must be an integer")

        buf = _ffi.new("char[]", bufsiz)
        result = _lib.BIO_read(self._from_ssl, buf, bufsiz)
        if result <= 0:
            self._handle_bio_errors(self._from_ssl, result)

        return _ffi.buffer(buf, result)[:]
예제 #15
0
파일: rand.py 프로젝트: haldean/pyopenssl
def bytes(num_bytes):
    """
    Get some random bytes as a string.

    :param num_bytes: The number of bytes to fetch
    :return: A string of random bytes
    """
    if not isinstance(num_bytes, _integer_types):
        raise TypeError("num_bytes must be an integer")

    if num_bytes < 0:
        raise ValueError("num_bytes must not be negative")

    result_buffer = _ffi.new("char[]", num_bytes)
    result_code = _lib.RAND_bytes(result_buffer, num_bytes)
    if result_code == -1:
        # TODO: No tests for this code path.  Triggering a RAND_bytes failure
        # might involve supplying a custom ENGINE?  That's hard.
        _raise_current_error()

    return _ffi.buffer(result_buffer)[:]
예제 #16
0
def bytes(num_bytes):
    """
    Get some random bytes as a string.

    :param num_bytes: The number of bytes to fetch
    :return: A string of random bytes
    """
    if not isinstance(num_bytes, _integer_types):
        raise TypeError("num_bytes must be an integer")

    if num_bytes < 0:
        raise ValueError("num_bytes must not be negative")

    result_buffer = _ffi.new("char[]", num_bytes)
    result_code = _lib.RAND_bytes(result_buffer, num_bytes)
    if result_code == -1:
        # TODO: No tests for this code path.  Triggering a RAND_bytes failure
        # might involve supplying a custom ENGINE?  That's hard.
        _raise_current_error()

    return _ffi.buffer(result_buffer)[:]
예제 #17
0
def _new_mem_buf(buffer=None):
    """
    Allocate a new OpenSSL memory BIO.
    Arrange for the garbage collector to clean it up automatically.
    :param buffer: None or some bytes to use to put into the BIO so that they
        can be read out.
    """
    if buffer is None:
        bio = _lib.BIO_new(_lib.BIO_s_mem())
        free = _lib.BIO_free
    else:
        data = _ffi.new("char[]", buffer)
        bio = _lib.BIO_new_mem_buf(data, len(buffer))

        # Keep the memory alive as long as the bio is alive!
        def free(bio, ref=data):
            return _lib.BIO_free(bio)

    if bio == _ffi.NULL:
        # TODO: This is untested.
        _raise_current_error()

    bio = _ffi.gc(bio, free)
    return bio