def download(port, cert_var, cert_length_var, output, use_store, keep_dupes, domain): """Download the SSL certificates for specified domain(s) and save them as a C header file that can be imported into a sketch. Provide at least one argument that is the domain to query for its SSL certificate, for example google.com for Google's SSL certificate. You can provide any number of domains as additional arguments. All of the certificates will be combined into a single output header. By default the file 'certificates.h' will be created, however you can change the name of the file with the --output option. If a chain of certificates is retrieved then only the root certificate (i.e. the last in the chain) will be saved. However you can override this and force the full chain to be saved with the --full-chain option. Example of downloading google.com's SSL certificate and storing it in certificates.h: pycert download google.com Example of downloading google.com and adafruit.com's SSL certificates and storing them in data.h: pycert download --output data.h google.com adafruit.com Note that the certificates will be validated before they are downloaded! """ # if array is emptey, exit if len(domain) == 0: return # prepare the root certificate store cert_obj_store = cert_util.parse_root_certificate_store(use_store) cert_dict = dict([(cert.get_subject().hash(), cert) for cert in cert_obj_store]) # Download the cert object for each provided domain. down_certs = [] for d in domain: # Download the certificate (unfortunately python will _always_ try to # validate it so we have no control over turning that off). cert = cert_util.get_server_root_cert(d, port, cert_dict) if cert is None: raise click.ClickException( 'Could not download and/or validate the certificate for {0} port {1}!' .format(d, port)) click.echo('Retrieved certificate for {0}'.format(d)) # append cert to array down_certs.append(cert) # Combine PEMs and write output header. try: cert_util.x509_to_header(down_certs, cert_var, cert_length_var, output, keep_dupes, domains=domain) except Exception as E: click.echo( f'Recieved error when converting certificate to header: {E}') exit(1)
def convert(cert_var, cert_length_var, output, use_store, keep_dupes, no_search, cert): """Convert PEM certificates into a C header that can be imported into a sketch. Specify each certificate to encode as a separate argument (each must be in PEM format) and they will be merged into a single file. By default the file 'certificates.h' will be created, however you can change the name of the file with the --output option. If a chain of certificates is found then only the root certificate (i.e. the last in the chain) will be saved. Example of converting a foo.pem certificate into a certificates.h header: pycert convert foo.pem Example of converting foo.pem and bar.pem certificates into data.h: pycert convert foo.pem bar.pem """ # if array is emptey, exit if len(cert) == 0: return # prepare root certificate store cert_obj_store = cert_util.parse_root_certificate_store(use_store) cert_dict = dict([(cert.get_subject().hash(), cert) for cert in cert_obj_store]) # Load all the provided PEM files. cert_objs = [] for c in cert: cert_pem = c.read() cert_parsed = crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem) if cert_parsed is None: click.echo('Failed to load certificate {0}'.format(c.name)) else: click.echo('Loaded certificate {0}'.format(c.name)) cert_objs.append(cert_parsed) # find a root certificate for each root_certs = [] if no_search: root_certs = cert_objs else: for i, c in enumerate(cert_objs): cn_hash = c.get_issuer().hash() if cn_hash not in cert_dict: click.echo('Could not find a root certificate for {0}'.format( cert[i].name)) else: root_certs.append(cert_dict[cn_hash]) # Combine PEMs and write output header. try: cert_util.x509_to_header(root_certs, cert_var, cert_length_var, output, keep_dupes) except Exception as E: click.echo( f'Recieved error when converting certificate to header: {E}') exit(1)
def get_header(event, context): # check that the input object is formatted correctly if event is None or Q_STR_KEY not in event or event[Q_STR_KEY] is None or "domain" not in event[Q_STR_KEY]: return ERROR # extract domains from the event object, and deduplicate domains = list(set(event[Q_STR_KEY]["domain"])) # iterate through the domains, fetching the certificates for each one out_invalid, out_valid_tuple = validate_and_get_certs(domains, True) if out_invalid is None or out_valid_tuple is None: return ERROR # split the packed tuple for the function out_dom = [ d for d, cert in out_valid_tuple ] out_cert = [ cert for d, cert in out_valid_tuple ] # create the header from the certs and some url parameters, escaping all the weird stuff header = "\"\"" if len(out_cert) > 0: header = json.dumps(cert_util.x509_to_header( out_cert, get_param(event, "array_name", CERT_ARRAY_NAME), get_param(event, "length_name", CERT_LENGTH_NAME), False, get_param(event, "guard_name", GUARD_NAME), domains=domains)) inval_str = "" if len(out_invalid) > 0: inval_str = "\"" + "\", \"".join(out_invalid) + "\"" valid_str = "" if len(out_dom) > 0: valid_str = "\"" + "\", \"".join(out_dom) + "\"" # return some JSON! return { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*", }, "body": HEAD_OUT_FMT.format( head=header, dom_inval=inval_str, dom_val=valid_str ) }