summaryrefslogtreecommitdiff
path: root/src/leap/crypto/certs.py
blob: cbb5725a84668d4a6e87d0abe95e3ced6c801087 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
import logging
import os
from StringIO import StringIO
import ssl
import time

from dateutil.parser import parse
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, unicode)):
        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


def get_time_boundaries(certfile):
    cert = get_cert_from_file(certfile)
    null_check(cert, 'certificate')

    fromts, tots = (cert.get_notBefore(), cert.get_notAfter())
    from_, to_ = map(
        lambda ts: time.gmtime(time.mktime(parse(ts).timetuple())),
        (fromts, tots))
    return from_, to_