def parse_logging_config(log_config_spec) -> Dict[Optional[str], LogConfig]: if not isinstance(log_config_spec, dict): raise ConfigurationError('logging config should be a dictionary') root_logger_level = _retrieve_log_level( log_config_spec, 'root-level', default=DEFAULT_ROOT_LOGGER_LEVEL ) root_logger_output = get_and_apply( log_config_spec, 'root-output', LogConfig.parse_output_spec, default=StdLogOutput.STDERR ) log_config = {None: LogConfig(root_logger_level, root_logger_output)} logging_by_module = log_config_spec.get('by-module', {}) if not isinstance(logging_by_module, dict): raise ConfigurationError('logging.by-module should be a dict') for module, module_logging_settings in logging_by_module.items(): if not isinstance(module, str): raise ConfigurationError( "Keys in logging.by-module should be strings" ) level_spec = _retrieve_log_level(module_logging_settings, 'level') output_spec = get_and_apply( module_logging_settings, 'output', LogConfig.parse_output_spec, default=StdLogOutput.STDERR ) log_config[module] = LogConfig(level=level_spec, output=output_spec) return log_config
def read_dss(cls, handler: PdfHandler) -> 'DocumentSecurityStore': """ Read a DSS record from a file and add the data to a validation context. :param handler: PDF handler from which to read the DSS. :return: A DocumentSecurityStore object describing the current state of the DSS. """ try: dss_dict = handler.root['/DSS'] except KeyError as e: raise NoDSSFoundError() from e cert_refs = {} cert_ref_list = get_and_apply(dss_dict, '/Certs', list, default=()) for cert_ref in cert_ref_list: cert_stream: generic.StreamObject = cert_ref.get_object() cert: Certificate = Certificate.load(cert_stream.data) cert_refs[cert.issuer_serial] = cert_ref ocsp_refs = get_and_apply(dss_dict, '/OCSPs', list, default=()) ocsps = [] for ocsp_ref in ocsp_refs: ocsp_stream: generic.StreamObject = ocsp_ref.get_object() resp = asn1_ocsp.OCSPResponse.load(ocsp_stream.data) ocsps.append(resp) crl_refs = get_and_apply(dss_dict, '/CRLs', list, default=()) crls = [] for crl_ref in crl_refs: crl_stream: generic.StreamObject = crl_ref.get_object() crl = asn1_crl.CertificateList.load(crl_stream.data) crls.append(crl) # shallow-copy the VRI dictionary try: vri_entries = dict(dss_dict['/VRI']) except KeyError: vri_entries = None # if the handler is a writer, the DSS will support updates if isinstance(handler, BasePdfFileWriter): writer = handler else: writer = None # the DSS returned will be backed by the original DSS object, so CRLs # are automagically preserved if they happened to be included in # the original file dss = cls( writer=writer, certs=cert_refs, ocsps=ocsp_refs, vri_entries=vri_entries, crls=crl_refs, backing_pdf_object=dss_dict ) return dss
def from_pdf_object(cls, pdf_dict): """ Read a PDF dictionary into a :class:`.SigCertConstraints` object. :param pdf_dict: A :class:`~.generic.DictionaryObject`. :return: A :class:`.SigCertConstraints` object. """ if isinstance(pdf_dict, generic.IndirectObject): pdf_dict = pdf_dict.get_object() try: if pdf_dict['/Type'] != '/SVCert': # pragma: nocover raise ValueError('Object /Type entry is not /SVCert') except KeyError: # pragma: nocover pass flags = SigCertConstraintFlags(pdf_dict.get('/Ff', 0)) subjects = [ oskeys.parse_certificate(cert.original_bytes) for cert in pdf_dict.get('/Subject', ()) ] issuers = [ oskeys.parse_certificate(cert.original_bytes) for cert in pdf_dict.get('/Issuer', ()) ] def format_attr(attr): # strip initial / attr = attr[1:] # attempt to convert abbreviated attrs to OIDs, since build() # takes OIDs return name_type_abbrevs_rev.get(attr.upper(), attr) subject_dns = x509.Name.build({ format_attr(attr): value for dn_dir in pdf_dict.get('/SubjectDN', ()) for attr, value in dn_dir.items() }) def parse_key_usage(val): return [SigCertKeyUsage.read_from_sv_string(ku) for ku in val] key_usage = get_and_apply(pdf_dict, '/KeyUsage', parse_key_usage) url = pdf_dict.get('/URL') url_type = pdf_dict.get('/URLType') kwargs = { 'flags': flags, 'subjects': subjects or None, 'subject_dn': subject_dns or None, 'issuers': issuers or None, 'info_url': url, 'key_usage': key_usage } if url is not None and url_type is not None: kwargs['url_type'] = url_type return cls(**kwargs)
def from_pdf_object(cls, pdf_dict): """ Read from a seed value dictionary. :param pdf_dict: A :class:`~.generic.DictionaryObject`. :return: A :class:`.SigSeedValueSpec` object. """ if isinstance(pdf_dict, generic.IndirectObject): pdf_dict = pdf_dict.get_object() try: if pdf_dict['/Type'] != '/SV': # pragma: nocover raise ValueError('Object /Type entry is not /SV') except KeyError: # pragma: nocover pass flags = SigSeedValFlags(pdf_dict.get('/Ff', 0)) try: sig_filter = pdf_dict['/Filter'] if (flags & SigSeedValFlags.FILTER) and \ (sig_filter != '/Adobe.PPKLite'): raise SigningError( "Signature handler '%s' is not available, only the " "default /Adobe.PPKLite is supported." % sig_filter) except KeyError: pass try: min_version = pdf_dict['/V'] supported = SeedValueDictVersion.PDF_2_0.value if flags & SigSeedValFlags.V and min_version > supported: raise SigningError( "Seed value dictionary version %s not supported." % min_version) min_version = SeedValueDictVersion(min_version) except KeyError: min_version = None try: add_rev_info = bool(pdf_dict['/AddRevInfo']) except KeyError: add_rev_info = None subfilter_reqs = pdf_dict.get('/SubFilter', None) subfilters = None if subfilter_reqs is not None: def _subfilters(): for s in subfilter_reqs: try: yield SigSeedSubFilter(s) except ValueError: pass subfilters = list(_subfilters()) try: digest_methods = [s.lower() for s in pdf_dict['/DigestMethod']] except KeyError: digest_methods = None reasons = get_and_apply(pdf_dict, '/Reasons', list) legal_attestations = get_and_apply(pdf_dict, '/LegalAttestation', list) def read_mdp_dict(mdp): try: val = mdp['/P'] return SeedSignatureType(None if val == 0 else MDPPerm(val)) except (KeyError, TypeError, ValueError): raise SigningError( f"/MDP entry {mdp} in seed value dictionary is not " "correctly formatted.") signature_type = get_and_apply(pdf_dict, '/MDP', read_mdp_dict) def read_lock_document(val): try: return SeedLockDocument(val) except ValueError: raise SigningError(f"/LockDocument entry '{val}' is invalid.") lock_document = get_and_apply(pdf_dict, '/LockDocument', read_lock_document) appearance_filter = pdf_dict.get('/AppearanceFilter', None) timestamp_dict = pdf_dict.get('/TimeStamp', {}) timestamp_server_url = timestamp_dict.get('/URL', None) timestamp_required = bool(timestamp_dict.get('/Ff', 0)) cert_constraints = pdf_dict.get('/Cert', None) if cert_constraints is not None: cert_constraints = SigCertConstraints.from_pdf_object( cert_constraints) return cls(flags=flags, reasons=reasons, timestamp_server_url=timestamp_server_url, cert=cert_constraints, subfilters=subfilters, digest_methods=digest_methods, add_rev_info=add_rev_info, timestamp_required=timestamp_required, legal_attestations=legal_attestations, seed_signature_type=signature_type, sv_dict_version=min_version, lock_document=lock_document, appearance=appearance_filter)
def from_pdf_object(cls, pdf_dict): """ Read from a seed value dictionary. :param pdf_dict: A :class:`~.generic.DictionaryObject`. :return: A :class:`.SigSeedValueSpec` object. """ if isinstance(pdf_dict, generic.IndirectObject): pdf_dict = pdf_dict.get_object() try: if pdf_dict['/Type'] != '/SV': # pragma: nocover raise ValueError('Object /Type entry is not /SV') except KeyError: # pragma: nocover pass flags = SigSeedValFlags(pdf_dict.get('/Ff', 0)) try: sig_filter = pdf_dict['/Filter'] if (flags & SigSeedValFlags.FILTER) and \ (sig_filter != '/Adobe.PPKLite'): raise SigningError( "Signature handler '%s' is not available, only the " "default /Adobe.PPKLite is supported." % sig_filter) except KeyError: pass # TODO support all PDF 2.0 values min_version = pdf_dict.get('/V', 1) if flags & SigSeedValFlags.V and min_version > 1: raise SigningError( "Seed value dictionary version %s not supported." % min_version) try: add_rev_info = bool(pdf_dict['/AddRevInfo']) except KeyError: add_rev_info = None subfilter_reqs = pdf_dict.get('/SubFilter', None) subfilters = None if subfilter_reqs is not None: def _subfilters(): for s in subfilter_reqs: try: yield SigSeedSubFilter(s) except ValueError: pass subfilters = list(_subfilters()) try: digest_methods = [s.lower() for s in pdf_dict['/DigestMethod']] except KeyError: digest_methods = None reasons = get_and_apply(pdf_dict, '/Reasons', list) timestamp_dict = pdf_dict.get('/TimeStamp', {}) timestamp_server_url = timestamp_dict.get('/URL', None) timestamp_required = bool(timestamp_dict.get('/Ff', 0)) cert_constraints = pdf_dict.get('/Cert', None) if cert_constraints is not None: cert_constraints = SigCertConstraints.from_pdf_object( cert_constraints) return cls(flags=flags, reasons=reasons, timestamp_server_url=timestamp_server_url, cert=cert_constraints, subfilters=subfilters, digest_methods=digest_methods, add_rev_info=add_rev_info, timestamp_required=timestamp_required)