|
PACS System 0.1.0
PACS DICOM system library
|
Classes | |
| struct | built_envelope |
| Result of envelope construction. More... | |
| struct | http_response |
| HTTP response captured from a POST call. More... | |
| struct | mtom_part |
| One attachment part, mapped 1:1 to an xop:Include in the envelope. More... | |
| struct | packaged_mtom |
| Fully assembled MTOM request body. More... | |
| struct | parsed_mtom |
| Result of parsing an inbound multipart/related MTOM response. More... | |
| struct | transport_request |
| Optional test hook: replaces the real libcurl transport. More... | |
Typedefs | |
| using | transport_override |
Enumerations | |
| enum class | stored_query_kind { find_documents , get_documents } |
| Discriminator for the two stored queries this actor supports. More... | |
Functions | |
| void | set_http_transport_override (transport_override fn) |
| void | clear_http_transport_override () |
| kcenon::common::Result< http_response > | http_post (const http_options &opts, const std::string &content_type, const std::string &body) |
POST body to opts.endpoint with the given Content-Type. | |
| kcenon::common::Result< packaged_mtom > | package_mtom (const std::string &envelope_xml, const std::vector< mtom_part > &parts) |
| Assemble a multipart/related MTOM body. | |
| kcenon::common::Result< parsed_mtom > | parse_mtom_response (const std::string &content_type_header, const std::string &body) |
| Parse a multipart/related MTOM response body. | |
| kcenon::common::Result< built_envelope > | build_iti41_envelope (const submission_set &s, const std::vector< std::string > &cid_refs) |
| Build a SOAP envelope for ITI-41 from submission metadata and a list of content-id references for MTOM-attached document bytes. | |
| kcenon::common::Result< bool > | sign_envelope (built_envelope &env, std::string_view cert_pem, std::string_view key_pem, std::string_view key_password) |
Sign the body + timestamp of env in place. | |
| kcenon::common::Result< bool > | verify_envelope_integrity (std::string_view signed_xml) |
| Verify the structural integrity of a previously signed envelope against the certificate embedded in its own BinarySecurityToken. | |
| std::vector< std::uint8_t > | base64_decode_bytes (std::string_view b64) |
Base64-decode b64 using the same BIO-backed decoder the signer and verifier use internally. | |
| kcenon::common::Result< built_envelope > | build_iti43_envelope (const retrieve_request &req) |
| Build a SOAP envelope for ITI-43 from a retrieve_request. | |
| kcenon::common::Result< document_response > | parse_retrieve_response (const std::string &root_xml, const std::vector< mtom_part > &parts, const retrieve_request &req) |
Parse a RetrieveDocumentSetResponse envelope and resolve the attachment that matches req. | |
| kcenon::common::Result< built_envelope > | build_iti18_envelope (const registry_query_request &req, stored_query_kind kind) |
| Build a SOAP envelope for ITI-18 from a registry_query_request. | |
| kcenon::common::Result< registry_query_result > | parse_query_response (const std::string &root_xml) |
| Parse an AdhocQueryResponse envelope into a registry_query_result. | |
Definition at line 57 of file http_client.h.
|
strong |
Discriminator for the two stored queries this actor supports.
| Enumerator | |
|---|---|
| find_documents | |
| get_documents | |
Definition at line 33 of file query_envelope.h.
| std::vector< std::uint8_t > kcenon::pacs::ihe::xds::detail::base64_decode_bytes | ( | std::string_view | b64 | ) |
Base64-decode b64 using the same BIO-backed decoder the signer and verifier use internally.
Exported so callers outside wss_signer.cpp (in particular the retrieve response parser, which needs to decode inline Document payloads on non-MTOM responses) do not have to re-implement the OpenSSL BIO dance. Returns an empty vector on decode failure; callers must check.
Definition at line 608 of file wss_signer.cpp.
References out.
Referenced by parse_retrieve_response().

| kcenon::common::Result< built_envelope > kcenon::pacs::ihe::xds::detail::build_iti18_envelope | ( | const registry_query_request & | req, |
| stored_query_kind | kind ) |
Build a SOAP envelope for ITI-18 from a registry_query_request.
Emits an AdhocQueryRequest containing one AdhocQuery with the stored query id corresponding to kind. The envelope carries a wsa:Action of "urn:ihe:iti:2007:RegistryStoredQuery" and an empty wsse:Security header containing a Timestamp and BinarySecurityToken that sign_envelope fills in and signs afterwards.
For find_documents: emits $XDSDocumentEntryPatientId and $XDSDocumentEntryStatus slots, plus optional $XDSDocumentEntryCreationTimeFrom / $XDSDocumentEntryCreationTimeTo slots when req.options populates them.
For get_documents: emits $XDSDocumentEntryEntryUUID with the list literal form that ebRIM StoredQuery slots require.
Returns registry_query_missing_patient_id / registry_query_empty_uuid_list on empty required fields; envelope_serialization_failed if pugixml cannot serialize the document.
Definition at line 149 of file query_envelope.cpp.
References kcenon::pacs::ihe::xds::registry_query_options::creation_time_from, kcenon::pacs::ihe::xds::registry_query_options::creation_time_to, kcenon::pacs::ihe::xds::registry_query_request::document_uuids, kcenon::pacs::ihe::xds::envelope_serialization_failed, kcenon::pacs::ihe::xds::error_source, find_documents, get_documents, kcenon::pacs::ihe::xds::registry_query_request::options, out, kcenon::pacs::ihe::xds::registry_query_request::patient_id, kcenon::pacs::ihe::xds::registry_query_empty_uuid_list, kcenon::pacs::ihe::xds::registry_query_invalid_patient_id, kcenon::pacs::ihe::xds::registry_query_missing_document_uuid, kcenon::pacs::ihe::xds::registry_query_missing_patient_id, and kcenon::pacs::ihe::xds::registry_query_options::status_values.
Referenced by kcenon::pacs::ihe::xds::registry_query::impl::execute().

| kcenon::common::Result< built_envelope > kcenon::pacs::ihe::xds::detail::build_iti41_envelope | ( | const submission_set & | s, |
| const std::vector< std::string > & | cid_refs ) |
Build a SOAP envelope for ITI-41 from submission metadata and a list of content-id references for MTOM-attached document bytes.
The cid_refs vector must be the same length as s.documents. Each cid is placed inside the matching ExtrinsicObject as an xop:Include.
Returns envelope_build_failed on any input inconsistency; envelope_serialization_failed if pugixml cannot serialize the document.
Definition at line 201 of file soap_envelope.cpp.
References kcenon::pacs::ihe::xds::submission_set::documents, kcenon::pacs::ihe::xds::envelope_build_failed, kcenon::pacs::ihe::xds::envelope_serialization_failed, kcenon::pacs::ihe::xds::error_source, kcenon::pacs::ihe::xds::metadata_document_empty, kcenon::pacs::ihe::xds::metadata_document_missing_mime_type, kcenon::pacs::ihe::xds::metadata_document_missing_unique_id, kcenon::pacs::ihe::xds::metadata_missing_patient_id, kcenon::pacs::ihe::xds::metadata_missing_source_id, kcenon::pacs::ihe::xds::metadata_missing_submission_set_uid, kcenon::pacs::ihe::xds::metadata_no_documents, out, kcenon::pacs::ihe::xds::submission_set::patient_id, kcenon::pacs::ihe::xds::submission_set::source_id, and kcenon::pacs::ihe::xds::submission_set::submission_set_unique_id.
Referenced by kcenon::pacs::ihe::xds::document_source::impl::submit().

| kcenon::common::Result< built_envelope > kcenon::pacs::ihe::xds::detail::build_iti43_envelope | ( | const retrieve_request & | req | ) |
Build a SOAP envelope for ITI-43 from a retrieve_request.
Emits one xdsb:DocumentRequest element per call. The envelope carries a wsa:Action of "urn:ihe:iti:2007:RetrieveDocumentSet" and an empty wsse:Security header containing a Timestamp and BinarySecurityToken that sign_envelope fills in and signs afterwards.
Returns consumer_retrieve_missing_document_id / consumer_retrieve_missing_repository_id on empty fields; envelope_serialization_failed if pugixml cannot serialize the document.
Definition at line 68 of file retrieve_envelope.cpp.
References kcenon::pacs::ihe::xds::consumer_retrieve_missing_document_id, kcenon::pacs::ihe::xds::consumer_retrieve_missing_repository_id, kcenon::pacs::ihe::xds::retrieve_request::document_unique_id, kcenon::pacs::ihe::xds::envelope_serialization_failed, kcenon::pacs::ihe::xds::error_source, out, and kcenon::pacs::ihe::xds::retrieve_request::repository_unique_id.
Referenced by kcenon::pacs::ihe::xds::document_consumer::impl::retrieve().

| void kcenon::pacs::ihe::xds::detail::clear_http_transport_override | ( | ) |
Definition at line 111 of file http_client.cpp.
| kcenon::common::Result< http_response > kcenon::pacs::ihe::xds::detail::http_post | ( | const http_options & | opts, |
| const std::string & | content_type, | ||
| const std::string & | body ) |
POST body to opts.endpoint with the given Content-Type.
Adds a SOAPAction header, a User-Agent, and forwards the TLS settings from opts. Returns transport_curl_failed / transport_tls_error / transport_http_error with context in the message.
Definition at line 116 of file http_client.cpp.
References kcenon::pacs::ihe::xds::detail::transport_request::body, kcenon::pacs::ihe::xds::http_options::ca_bundle_path, kcenon::pacs::ihe::xds::http_options::client_certificate_path, kcenon::pacs::ihe::xds::http_options::client_private_key_path, code, kcenon::pacs::ihe::xds::http_options::connect_timeout, content_type, kcenon::pacs::ihe::xds::detail::transport_request::content_type, kcenon::pacs::ihe::xds::http_options::endpoint, kcenon::pacs::ihe::xds::error_source, out, kcenon::pacs::ihe::xds::http_options::request_timeout, kcenon::pacs::ihe::xds::detail::transport_request::soap_action, kcenon::pacs::ihe::xds::http_options::soap_action, kcenon::pacs::ihe::xds::transport_curl_failed, kcenon::pacs::ihe::xds::transport_http_error, kcenon::pacs::ihe::xds::transport_init_failed, kcenon::pacs::ihe::xds::transport_not_configured, kcenon::pacs::ihe::xds::transport_response_too_large, kcenon::pacs::ihe::xds::transport_timeout, kcenon::pacs::ihe::xds::transport_tls_error, kcenon::pacs::ihe::xds::detail::transport_request::url, kcenon::pacs::ihe::xds::http_options::user_agent, kcenon::pacs::ihe::xds::http_options::verify_host, kcenon::pacs::ihe::xds::detail::transport_request::verify_peer, and kcenon::pacs::ihe::xds::http_options::verify_peer.
Referenced by kcenon::pacs::ihe::xds::registry_query::impl::execute(), kcenon::pacs::ihe::xds::document_consumer::impl::retrieve(), and kcenon::pacs::ihe::xds::document_source::impl::submit().

| kcenon::common::Result< packaged_mtom > kcenon::pacs::ihe::xds::detail::package_mtom | ( | const std::string & | envelope_xml, |
| const std::vector< mtom_part > & | parts ) |
Assemble a multipart/related MTOM body.
envelope_xml is the signed SOAP 1.2 envelope; parts are the document binaries referenced from the envelope by xop:Include.
The boundary is generated from a thread-local PRNG and guaranteed not to appear in any of the inputs via a fallback re-seed if a collision is detected.
Definition at line 59 of file mtom_packager.cpp.
References kcenon::pacs::ihe::xds::error_source, kcenon::pacs::ihe::xds::mtom_boundary_generation_failed, kcenon::pacs::ihe::xds::mtom_empty_payload, and out.
Referenced by kcenon::pacs::ihe::xds::document_source::impl::submit().

| kcenon::common::Result< parsed_mtom > kcenon::pacs::ihe::xds::detail::parse_mtom_response | ( | const std::string & | content_type_header, |
| const std::string & | body ) |
Parse a multipart/related MTOM response body.
Prefers the boundary parameter from content_type_header when it is non-empty and carries a boundary="..." (or bare boundary=...) attribute. Falls back to sniffing the first --<boundary> marker in body when the header is absent or malformed. The 8 MiB response cap in http_client.cpp bounds the walk in either path.
The body is split into parts, each part is stripped of its headers, and the first encountered part is treated as the root envelope.
Non-MTOM responses (the repository returned plain SOAP with no multipart framing) are detected and returned with root_xml set to the whole body and parts empty, so the caller can still invoke the signer and response parser uniformly. This matches the fallback behavior of Apache CXF repositories that omit MTOM when no attachments are present.
Definition at line 257 of file mtom_packager.cpp.
References kcenon::pacs::ihe::xds::consumer_response_missing_mtom_root, kcenon::pacs::ihe::xds::consumer_response_mtom_malformed, kcenon::pacs::ihe::xds::detail::mtom_part::content, kcenon::pacs::ihe::xds::detail::mtom_part::content_id, kcenon::pacs::ihe::xds::error_source, kcenon::pacs::ihe::xds::detail::mtom_part::mime_type, and out.
Referenced by kcenon::pacs::ihe::xds::document_consumer::impl::retrieve().

| kcenon::common::Result< registry_query_result > kcenon::pacs::ihe::xds::detail::parse_query_response | ( | const std::string & | root_xml | ) |
Parse an AdhocQueryResponse envelope into a registry_query_result.
root_xml is the response envelope (already signature-verified).
Returns registry_failure_response when the registry reports a Failure status. Returns registry_partial_success on PartialSuccess - callers wanting to tolerate that state must inspect the status string of the returned error context.
An empty RegistryObjectList on Success is a successful empty result, not an error: the function returns a registry_query_result with an empty entries vector.
Definition at line 146 of file query_response_parser.cpp.
References kcenon::pacs::ihe::xds::error_source, out, kcenon::pacs::ihe::xds::registry_failure_response, kcenon::pacs::ihe::xds::registry_query_response_malformed, kcenon::pacs::ihe::xds::transport_invalid_response, and kcenon::pacs::ihe::xds::transport_response_too_large.
Referenced by kcenon::pacs::ihe::xds::registry_query::impl::execute().

| kcenon::common::Result< document_response > kcenon::pacs::ihe::xds::detail::parse_retrieve_response | ( | const std::string & | root_xml, |
| const std::vector< mtom_part > & | parts, | ||
| const retrieve_request & | req ) |
Parse a RetrieveDocumentSetResponse envelope and resolve the attachment that matches req.
root_xml is the root part of the MTOM response (already verified). parts are the remaining attachment parts, keyed on the bare content-id that the xop:Include elements reference via "cid:".
Returns consumer_response_document_not_found when the registry reports a Failure status, when no DocumentResponse matches the requested document_unique_id, or when the matching xop:Include points to a cid that is not present in parts.
Definition at line 52 of file retrieve_response_parser.cpp.
References base64_decode_bytes(), kcenon::pacs::ihe::xds::consumer_response_document_not_found, kcenon::pacs::ihe::xds::detail::mtom_part::content, kcenon::pacs::ihe::xds::retrieve_request::document_unique_id, kcenon::pacs::ihe::xds::error_source, match, kcenon::pacs::ihe::xds::detail::mtom_part::mime_type, out, kcenon::pacs::ihe::xds::registry_partial_success, kcenon::pacs::ihe::xds::retrieve_request::repository_unique_id, kcenon::pacs::ihe::xds::transport_invalid_response, kcenon::pacs::ihe::xds::transport_response_too_large, and uid.
Referenced by kcenon::pacs::ihe::xds::document_consumer::impl::retrieve().


| void kcenon::pacs::ihe::xds::detail::set_http_transport_override | ( | transport_override | fn | ) |
Definition at line 106 of file http_client.cpp.
| kcenon::common::Result< bool > kcenon::pacs::ihe::xds::detail::sign_envelope | ( | built_envelope & | env, |
| std::string_view | cert_pem, | ||
| std::string_view | key_pem, | ||
| std::string_view | key_password ) |
Sign the body + timestamp of env in place.
cert_pem is the PEM-encoded X.509 signer certificate. key_pem is the matching PEM RSA or EC private key; key_password decrypts it when the key is encrypted and is ignored otherwise.
The envelope's BinarySecurityToken is populated with the DER-encoded certificate (Base64). A ds:Signature element is appended to the wsse:Security header covering the body and timestamp by wsu:Id reference.
On success, env.xml is replaced by the signed envelope and the Result<bool> value is true (the bool is a sentinel; the signature itself is inside env.xml).
Definition at line 206 of file wss_signer.cpp.
References base64_encode(), kcenon::pacs::ihe::xds::detail::built_envelope::binary_security_token_id, kcenon::pacs::ihe::xds::detail::built_envelope::body_id, kcenon::pacs::ihe::xds::envelope_build_failed, kcenon::pacs::ihe::xds::error_source, kcenon::pacs::ihe::xds::signer_digest_failed, kcenon::pacs::ihe::xds::signer_invalid_certificate, kcenon::pacs::ihe::xds::signer_invalid_private_key, kcenon::pacs::ihe::xds::signer_sign_failed, kcenon::pacs::ihe::xds::detail::built_envelope::timestamp_id, and kcenon::pacs::ihe::xds::detail::built_envelope::xml.
Referenced by kcenon::pacs::ihe::xds::registry_query::impl::execute(), kcenon::pacs::ihe::xds::document_consumer::impl::retrieve(), and kcenon::pacs::ihe::xds::document_source::impl::submit().


| kcenon::common::Result< bool > kcenon::pacs::ihe::xds::detail::verify_envelope_integrity | ( | std::string_view | signed_xml | ) |
Verify the structural integrity of a previously signed envelope against the certificate embedded in its own BinarySecurityToken.
Reparses signed_xml, locates the ds:Signature in wsse:Security, decodes the BinarySecurityToken into an X.509 public key, re-digests Body and Timestamp with the same pugixml format_raw serializer used for signing, and calls EVP_DigestVerify against the SignedInfo bytes.
SECURITY NOTE - SELF-AUTHENTICATING CHECK, NOT TRUST VALIDATION: this function verifies that the ds:Signature binds the payload to the certificate embedded in the response's BST. It does NOT validate that certificate against a trust anchor, CRL, OCSP responder, or peer TLS identity. A man-in-the-middle who can serve any valid X.509 certificate can produce a response that passes this check - the embedded key, the embedded signature, and the embedded payload are all self-consistent by construction. Full trust-chain validation will land with the Gazelle conformance integration tracked in #1131. Until that lands, callers relying solely on this function for authenticity guarantees are trusting whatever party the TLS peer is.
The rename from verify_envelope to verify_envelope_integrity in the #1129 review cycle is deliberate: the new name closes the "what does this actually guarantee" gap at the call site.
Honest-URI policy: the CanonicalizationMethod and every Transform Algorithm URI inside SignedInfo MUST equal "urn:kcenon:xds:c14n:pugixml-format-raw-v1". If any Algorithm advertises exc-c14n or any other URI, verification is refused with consumer_signature_verification_failed rather than silently digesting a mismatched byte stream. This mirrors the signer's behavior.
Canonicalization caveat: verification is only reproducible for envelopes produced by this project's sign_envelope. Real exc-c14n interop is a follow-up issue that must land before production use against a third-party IHE XDS.b repository.
Returns consumer_signature_missing if the envelope carries no ds:Signature element; consumer_signature_verification_failed on any other mismatch (digest, signature, algorithm, KeyInfo shape).
Definition at line 413 of file wss_signer.cpp.
References kcenon::pacs::ihe::xds::consumer_signature_missing, kcenon::pacs::ihe::xds::consumer_signature_verification_failed, and kcenon::pacs::ihe::xds::error_source.
Referenced by kcenon::pacs::ihe::xds::registry_query::impl::execute(), and kcenon::pacs::ihe::xds::document_consumer::impl::retrieve().
