summaryrefslogtreecommitdiff
path: root/src/leap/crypto/certs.py
blob: c2835878ff7011e2306cce0db5d0fd4ebdc07175 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import logging
import os
from StringIO import StringIO
import ssl

from OpenSSL import crypto

from leap.util.misc import null_check

logger = logging.getLogger(__name__)


class BadCertError(Exception):
    """
    raised for malformed certs
    """


class NoCertError(Exception):
    """
    raised for cert not found in given path
    """


def get_https_cert_from_domain(domain, port=443):
    """
    @param domain: a domain name to get a certificate from.
    """
    cert = ssl.get_server_certificate((domain, port))
    x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
    return x509


def get_cert_from_file(_file):
    null_check(_file, "pem file")
    if isinstance(_file, str):
        if not os.path.isfile(_file):
            raise NoCertError
        with open(_file) as f:
            cert = f.read()
    else:
        cert = _file.read()
    x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
    return x509


def get_pkey_from_file(_file):
    getkey = lambda f: crypto.load_privatekey(
        crypto.FILETYPE_PEM, f.read())

    if isinstance(_file, str):
        with open(_file) as f:
            key = getkey(f)
    else:
        key = getkey(_file)
    return key


def can_load_cert_and_pkey(string):
    """
    loads certificate and private key from
    a buffer
    """
    try:
        f = StringIO(string)
        cert = get_cert_from_file(f)

        f = StringIO(string)
        key = get_pkey_from_file(f)

        null_check(cert, 'certificate')
        null_check(key, 'private key')
    except Exception as exc:
        logger.error(type(exc), exc.message)
        raise BadCertError
    else:
        return True


def get_cert_fingerprint(domain=None, port=443, filepath=None,
                         hash_type="SHA256", sep=":"):
    """
    @param domain: a domain name to get a fingerprint from
    @type domain: str
    @param filepath: path to a file containing a PEM file
    @type filepath: str
    @param hash_type: the hash function to be used in the fingerprint.
        must be one of SHA1, SHA224, SHA256, SHA384, SHA512
    @type hash_type: str
    @rparam: hex_fpr, a hexadecimal representation of a bytestring
             containing the fingerprint.
    @rtype: string
    """
    if domain:
        cert = get_https_cert_from_domain(domain, port=port)
    if filepath:
        cert = get_cert_from_file(filepath)
    hex_fpr = cert.digest(hash_type)
    return hex_fpr