1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2013 LEAP
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 Implements cert checks and helpers
26 from OpenSSL import crypto
27 from dateutil.parser import parse as dateparse
29 from leap.common.check import leap_assert
31 logger = logging.getLogger(__name__)
34 def get_cert_from_string(string):
36 Returns the x509 from the contents of this string
38 :param string: certificate contents as downloaded
43 leap_assert(string, "We need something to load")
47 x509 = crypto.load_certificate(crypto.FILETYPE_PEM, string)
48 except Exception as e:
49 logger.error("Something went wrong while loading the certificate: %r"
54 def get_privatekey_from_string(string):
56 Returns the private key from the contents of this string
58 :param string: private key contents as downloaded
61 :return: private key or None
63 leap_assert(string, "We need something to load")
67 pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, string)
68 except Exception as e:
69 logger.error("Something went wrong while loading the certificate: %r"
74 def get_digest(cert_data, method):
76 Returns the digest for the cert_data using the method specified
78 :param cert_data: certificate data in string form
80 :param method: method to be used for digest
85 x509 = get_cert_from_string(cert_data)
86 digest = x509.digest(method).replace(":", "").lower()
91 def can_load_cert_and_pkey(string):
93 Loads certificate and private key from a buffer, returns True if
94 everything went well, False otherwise
96 :param string: buffer containing the cert and private key
97 :type string: str or any kind of buffer
104 cert = get_cert_from_string(string)
105 key = get_privatekey_from_string(string)
107 leap_assert(cert, 'The certificate could not be loaded')
108 leap_assert(key, 'The private key could not be loaded')
109 except Exception as e:
111 logger.error("Something went wrong while trying to load "
112 "the certificate: %r" % (e,))
117 def is_valid_pemfile(cert):
119 Checks that the passed string is a valid pem certificate
121 :param cert: String containing pem content
126 leap_assert(cert, "We need a cert to load")
128 return can_load_cert_and_pkey(cert)
131 def get_cert_time_boundaries(certfile):
133 Returns the time boundaries for the certificate saved in certfile
135 :param certfile: path to certificate
138 :rtype: tuple (from, to)
140 cert = get_cert_from_string(certfile)
141 leap_assert(cert, 'There was a problem loading the certificate')
143 fromts, tots = (cert.get_notBefore(), cert.get_notAfter())
145 lambda ts: time.gmtime(time.mktime(dateparse(ts).timetuple())),
150 def should_redownload(certfile, now=time.gmtime):
152 Returns True if any of the checks don't pass, False otherwise
154 :param certfile: path to certificate
156 :param now: current date function, ONLY USED FOR TESTING
160 exists = os.path.isfile(certfile)
167 with open(certfile, "r") as f:
169 if not is_valid_pemfile(certdata):
174 valid_from, valid_to = get_cert_time_boundaries(certdata)
176 if not (valid_from < now() < valid_to):