Giter Site home page Giter Site logo

rust-xmlsec's Introduction

Rust wrapper for xmlsec1

This library aims at wrapping xmlsec1 and being interoperable with rust-libxml, while attemting to be as correct and comfortable to use as possible.

Things needing improvement

  • Better input sanitization of string arguments. Currently they get blindly turned into a FFI version and passed through to xmlsec.
  • Proper management for xmlsec error handling. Currently things fail very opaquely without actually telling you why the signing process failed, just that it failed for the particular job.
  • More expressive error handling chain.

Things not yet supported

  • XML encryption.
  • Key management (as in xmlsec key manager). Though the value of wrapping that should be debated first. It may be more sensible to lift that to pure Rust instead.
  • Dynamic selection of crypto backend.

Contibuting

Help in any way improving or completing the wrapping of xmlsec features always very welcome! Please keep some things in mind before PR'ing your changes;

  • Please check tests for breakage and write new ones to cover your changes.
  • Please run valgrind over your tests and make sure you are not leaking resources.

Tested platforms

  • Debian Buster (10.x)

rust-xmlsec's People

Contributors

dasj avatar joshuanitschke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

rust-xmlsec's Issues

Failure to compile on Ubuntu 18.04

I was attempting your crate on Ubuntu which you aptly pointed out hasn't been tested yet.

That said I thought I would open an issue to document what I have seen thus far.
First I installed a few libraries:
libclang-dev
libxmlsec1-dev
libxml2-dev

After those were installed there was an error about llvm-config not being installed so I also installed the llvm package.

I could see this being a problem with the versions of the above packages.

With all that installed I get the following output.

   Compiling xmlsec v0.1.3
error: failed to run custom build command for `xmlsec v0.1.3`

Caused by:
  process didn't exit successfully: `/home/glade/code/xmlsec_test/target/debug/build/xmlsec-5b21d998c66cfeb1/build-script-bindings` (exit code: 101)
--- stdout
cargo:rustc-link-lib=xmlsec1-openssl
cargo:rustc-link-lib=xmlsec1
cargo:rustc-link-lib=xml2
cargo:rustc-link-lib=ssl
cargo:rustc-link-lib=crypto
cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu
cargo:rustc-link-lib=xmlsec1-openssl
cargo:rustc-link-lib=xmlsec1
cargo:rustc-link-lib=ssl
cargo:rustc-link-lib=crypto
cargo:rustc-link-lib=xslt
cargo:rustc-link-lib=xml2

--- stderr
warning: -lxmlsec1-openssl: 'linker' input unused [-Wunused-command-line-argument]
warning: -lxmlsec1: 'linker' input unused [-Wunused-command-line-argument]
warning: -lxslt: 'linker' input unused [-Wunused-command-line-argument]
warning: -lxml2: 'linker' input unused [-Wunused-command-line-argument]
warning: -lssl: 'linker' input unused [-Wunused-command-line-argument]
warning: -lcrypto: 'linker' input unused [-Wunused-command-line-argument]
warning: argument unused during compilation: '-L/usr/lib/x86_64-linux-gnu' [-Wunused-command-line-argument]
/usr/include/stdio.h:33:10: fatal error: 'stddef.h' file not found
warning: -lxmlsec1-openssl: 'linker' input unused [-Wunused-command-line-argument], err: false
warning: -lxmlsec1: 'linker' input unused [-Wunused-command-line-argument], err: false
warning: -lxslt: 'linker' input unused [-Wunused-command-line-argument], err: false
warning: -lxml2: 'linker' input unused [-Wunused-command-line-argument], err: false
warning: -lssl: 'linker' input unused [-Wunused-command-line-argument], err: false
warning: -lcrypto: 'linker' input unused [-Wunused-command-line-argument], err: false
warning: argument unused during compilation: '-L/usr/lib/x86_64-linux-gnu' [-Wunused-command-line-argument], err: false
/usr/include/stdio.h:33:10: fatal error: 'stddef.h' file not found, err: true
thread 'main' panicked at 'Unable to generate bindings: ()', /home/glade/.cargo/registry/src/github.com-1ecc6299db9ec823/xmlsec-0.1.3/bindings.rs:41:24
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Crate fails to build in github actions on version macOS 12.6.5

As an FYI this crate no longer builds on github actions runs-on: macos-latest

I'm sort of waiting for the next image update to see if it is still broken, but thought I'd report this in case anyone else has the issue later.

openssl = { version = "0.10", features = ["vendored"] }
[xmlsec = "0.2.2"]

Failure is on

Operating System
  macOS
  12.6.5
Runner Image
  Image: macos-12
  Included Software: https://github.com/actions/runner-images/blob/macOS-12/20230505.1/images/macos/macos-12-Readme.md
  Image Release: https://github.com/actions/runner-images/releases/tag/macOS-12%2F20230505.1

Last time it successfully built was on:

Operating System
  macOS
  12.6.4
  21G526
Runner Image
  Image: macos-12
  Included Software: https://github.com/actions/runner-images/blob/macOS-12/20230328.1/images/macos/macos-12-Readme.md
  Image Release: https://github.com/actions/runner-images/releases/tag/macOS-12%2F20230328.1

Current errors:

error[E0425]: cannot find function `xmlSecOpenSSLTransformHmacMd5GetKlass` in module `bindings`
     --> /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/xmlsec-0.2.2/src/crypto/openssl.rs:80:55
      |
80    |             Self::HmacMd5       => unsafe { bindings::xmlSecOpenSSLTransformHmacMd5GetKlass() },
      |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `xmlSecOpenSSLTransformHmacSha1GetKlass`
      |
     ::: /Users/runner/work/my-project/my-project/target/release/build/xmlsec-ce71c6600a0b42d1/out/bindings.rs:61325:5
      |
61325 |     pub fn xmlSecOpenSSLTransformHmacSha1GetKlass() -> xmlSecTransformId;
      |     --------------------------------------------------------------------- similarly named function `xmlSecOpenSSLTransformHmacSha1GetKlass` defined here

error[E0425]: cannot find function `xmlSecOpenSSLTransformMd5GetKlass` in module `bindings`
     --> /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/xmlsec-0.2.2/src/crypto/openssl.rs:87:55
      |
87    |             Self::Md5           => unsafe { bindings::xmlSecOpenSSLTransformMd5GetKlass() },
      |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `xmlSecOpenSSLTransformEcdhGetKlass`
      |
     ::: /Users/runner/work/my-project/my-project/target/release/build/xmlsec-ce71c6600a0b42d1/out/bindings.rs:61309:5
      |
61309 |     pub fn xmlSecOpenSSLTransformEcdhGetKlass() -> xmlSecTransformId;
      |     ----------------------------------------------------------------- similarly named function `xmlSecOpenSSLTransformEcdhGetKlass` defined here

error[E0425]: cannot find function `xmlSecOpenSSLTransformRsaMd5GetKlass` in module `bindings`
     --> /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/xmlsec-0.2.2/src/crypto/openssl.rs:89:55
      |
89    |             Self::RsaMd5        => unsafe { bindings::xmlSecOpenSSLTransformRsaMd5GetKlass() },
      |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `xmlSecOpenSSLTransformRsaOaepGetKlass`
      |
     ::: /Users/runner/work/my-project/my-project/target/release/build/xmlsec-ce71c6600a0b42d1/out/bindings.rs:61389:5
      |
61389 |     pub fn xmlSecOpenSSLTransformRsaOaepGetKlass() -> xmlSecTransformId;
      |     -------------------------------------------------------------------- similarly named function `xmlSecOpenSSLTransformRsaOaepGetKlass` defined here

error[E0308]: mismatched types
     --> /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/xmlsec-0.2.2/src/keys.rs:90:13
      |
88    |         let key = unsafe { bindings::xmlSecOpenSSLAppKeyLoadMemory(
      |                            --------------------------------------- arguments to this function are incorrect
89    |             buffer.as_ptr(),
90    |             buffer.len() as u32,
      |             ^^^^^^^^^^^^^^^^^^^ expected `u64`, found `u32`
      |
note: function defined here
     --> /Users/runner/work/my-project/my-project/target/release/build/xmlsec-ce71c6600a0b42d1/out/bindings.rs:60638:12
      |
60638 |     pub fn xmlSecOpenSSLAppKeyLoadMemory(
      |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: you can convert a `u32` to a `u64`
      |
90    |             (buffer.len() as u32).into(),
      |             +                   ++++++++

error[E0308]: mismatched types
     --> /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/xmlsec-0.2.2/src/keys.rs:125:17
      |
122   |             bindings::xmlSecOpenSSLAppKeyCertLoadMemory(
      |             ------------------------------------------- arguments to this function are incorrect
...
125   |                 buff.len() as u32,
      |                 ^^^^^^^^^^^^^^^^^ expected `u64`, found `u32`
      |
note: function defined here
     --> /Users/runner/work/my-project/my-project/target/release/build/xmlsec-ce71c6600a0b42d1/out/bindings.rs:60689:12
      |
60689 |     pub fn xmlSecOpenSSLAppKeyCertLoadMemory(
      |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: you can convert a `u32` to a `u64`
      |
125   |                 (buff.len() as u32).into(),
      |                 +                 ++++++++

Some errors have detailed explanations: E0308, E0425.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `xmlsec` due to 5 previous errors
warning: build failed, waiting for other jobs to finish...
Error: Process completed with exit code 101.

SHA256 with RSA with MGF1 padding

Hello!

for a special german SAML IdP i need to use these algorithms

  • signing method: http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1
  • digest method: http://www.w3.org/2001/04/xmlenc#sha256

The IdP does sadly not accept any other algorithm. I don't know if it is correct, but sha256-rsa-MGF1 seems to be PKCS1 PSS?

If i try to use it with a request that looks like this (with a real certificate, destination, AcsUrl and issuer)

Example AuthnRequest
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" 
                     ID="id-2309765366"
                     Version="2.0"
                     IssueInstant="2022-11-15T10:10:39.687Z"
                     Destination="https://sso.example.org/idp"
                     ForceAuthn="false"
                     ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                     AssertionConsumerServiceURL="http://sp.example.com/demo1/login">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
        http://sp.example.com/demo1
    </saml2:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"/>
            <ds:Reference URI="#id-2309765366">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                <ds:DigestValue></ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
        </ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>
KLLUp...                                                                                                                                                                                                                                                                                                                                                                                                  
                </ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    <saml2p:NameIDPolicy AllowCreate="true"/>
    <saml2p:RequestedAuthnContext xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Comparison="minimum">
        <saml2:AuthnContextClassRef>SOME_TEXT</saml2:AuthnContextClassRef>
    </saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest>                                                                    

then i get this error

func=xmlSecTransformNodeRead:file=transforms.c:line=1314:obj=unknown:subj=xmlSecTransformIdListFindByHref:error=1:xmlsec library function failed:href=http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1                                                                 │
func=xmlSecTransformCtxNodeRead:file=transforms.c:line=595:obj=SignatureMethod:subj=xmlSecTransformNodeRead:error=1:xmlsec library function failed:                                                                                                                          │
func=xmlSecDSigCtxProcessSignedInfoNode:file=xmldsig.c:line=661:obj=SignatureMethod:subj=xmlSecTransformCtxNodeRead:error=1:xmlsec library function failed:                                                                                                                  │
func=xmlSecDSigCtxProcessSignatureNode:file=xmldsig.c:line=497:obj=unknown:subj=xmlSecDSigCtxProcessSignedInfoNode:error=1:xmlsec library function failed:                                                                                                                   │
func=xmlSecDSigCtxSign:file=xmldsig.c:line=291:obj=unknown:subj=xmlSecDSigCtxProcessSignatureNode:error=1:xmlsec library function failed:

I use it like this

pub fn sign_xml<Bytes: AsRef<[u8]>>(xml: Bytes, private_key_der: &[u8]) -> Result<String, Error> {
    let parser = XmlParser::default();
    let document = parser.parse_string(xml)?;
    document
        .template()
        .signature(XmlSecSignatureMethod::RsaPkcs1)
        .done()?;

    let key = XmlSecKey::from_memory(private_key_der, XmlSecKeyFormat::Der, None)?;
    let mut context = XmlSecSignatureContext::new()?;
    context.insert_key(key);

    context.sign_document(&document, Some("ID"))?;

    Ok(document.to_string())
}

Am i doing anything wrong, or is it currently not possibly to use this algorithm? Sorry if this should be kinda obvious, i am a cryptography noob 😅

Extend builder to allow for x509 issuer serial parameter specifiying

@lweberk I'm happy to extend the builder for what I need as opposed to just exposing the raw functionality.

The only feature that is lacking for me (right now) is that I can't add the X509IssuerSerial block into the x509data.

 <dsig:X509IssuerSerial>
     <dsig:X509IssuerName>redacted</dsig:X509IssuerName>
     <dsig:X509SerialNumber>redacted</dsig:X509SerialNumber>
 </dsig:X509IssuerSerial>

Maybe we just add another option? x509issuer_serial(bool) (that defaults to false)?

doc.template()
        .canonicalization(XmlSecCanonicalizationMethod::ExclusiveC14N)
        .signature(XmlSecSignatureMethod::RsaSha1)
        .keyname(true)
        .keyvalue(true)
        .x509data(true)
        .x509issuer_serial(true)
        .uri("ReferencedID")
        .done();

All that issuer data is in the cert (obviously), which has already been given to the context. I'm not sure if xmlsec can get at it on its own as I am not very familiar with the library, I use https://docs.rs/openssl/latest/openssl/ for my use case.

Originally posted by @JoshuaNitschke in #5 (comment)

Not finding ID attribute

Thank you for putting this project together. I'm trying to verify signature of a saml response and receiving the following error below. I believe it's not finding the appropriate ID attribute. Other libraries allow you to set the ID attribute. How would I go about doing that in this project?

func=xmlSecXPathDataExecute:file=xpath.c:line=247:obj=unknown:subj=xmlXPtrEval:error=5:libxml2 library function failed:expr=xpointer(id('_30b74cd0e1cadd39f7a6a71d88baec3a7d6f2ab175')); xml error: 0: NULL
func=xmlSecXPathDataListExecute:file=xpath.c:line=330:obj=unknown:subj=xmlSecXPathDataExecute:error=1:xmlsec library function failed:
func=xmlSecTransformXPathExecute:file=xpath.c:line=431:obj=xpointer:subj=xmlSecXPathDataListExecute:error=1:xmlsec library function failed:
func=xmlSecTransformDefaultPushXml:file=transforms.c:line=2109:obj=xpointer:subj=xmlSecTransformExecute:error=1:xmlsec library function failed:
func=xmlSecTransformCtxXmlExecute:file=transforms.c:line=1045:obj=xpointer:subj=xmlSecTransformPushXml:error=1:xmlsec library function failed:
func=xmlSecTransformCtxExecute:file=transforms.c:line=1092:obj=unknown:subj=xmlSecTransformCtxXmlExecute:error=1:xmlsec library function failed:
func=xmlSecDSigReferenceCtxProcessNode:file=xmldsig.c:line=1408:obj=unknown:subj=xmlSecTransformCtxExecute:error=1:xmlsec library function failed:
func=xmlSecDSigCtxProcessReferences:file=xmldsig.c:line=753:obj=Reference:subj=xmlSecDSigReferenceCtxProcessNode:error=1:xmlsec library function failed:
func=xmlSecDSigCtxProcessSignatureNode:file=xmldsig.c:line=517:obj=unknown:subj=xmlSecDSigCtxProcessReferences:error=1:xmlsec library function failed:
func=xmlSecDSigCtxVerify:file=xmldsig.c:line=346:obj=unknown:subj=xmlSecDSigCtxProcessSignatureNode:error=1:xmlsec library function failed:

Make bindings crypto backend agnostic

Currently it requires the openssl backend to be present, relying on its implementation directly instead of its crypto.h abstractions. This would make the whole more platform/distro agnostic.

Expose wrapped internals for ease of adhoc extension

Make it easier to extend functionality of this wrapper by having API make the wrapped internals available under "unsafe" conditions. This can be beneficial for quick and dirty extension for not yet wrapped functionality without having to fork or otherwise handle upstream.

The downside for something like this, which in my perspective is not a stopper in itself, is that it disincentives the contributing back such an extension to upstream.

Design-wise the idea is to settle for the overarching use of unsafe fn as_ptr() -> *rawPtr and also the availability of the bindgen generated low level bindings which currently are private to the bindings module. The combination of both should enable most of what might be needed.

  • as_ptr(&self) -> *wrappedXmlStructure to borrow the wrapped structure pointer
  • into_ptr(self) -> *wrappedXmlStructure to move out the wrapped structure pointer, all the while suppressing the cleanup in the drop call.

Stakeholders;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.