-
Notifications
You must be signed in to change notification settings - Fork 1
/
xml.clj
69 lines (60 loc) · 2.43 KB
/
xml.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
(ns saml20-clj.xml
(:require [hiccup.core]
[hiccup.page]
[saml20-clj.shared :as saml-shared])
(:import [javax.xml.crypto KeySelector]
[javax.xml.crypto.dsig XMLSignature XMLSignatureFactory]
[javax.xml.crypto.dsig.dom DOMValidateContext]
[java.io ByteArrayInputStream]
[javax.xml.parsers DocumentBuilderFactory]
[org.w3c.dom Document]
[org.w3c.dom NodeList]
[org.apache.xml.security.c14n Canonicalizer]))
(defn make-xml-string
"Creates an XML string using hiccup."
[structure]
(str
(hiccup.page/xml-declaration "UTF-8")
(hiccup.core/html structure)))
(defn singleton-key-selector
"Always uses a provided key as a selector."
[jkey]
(KeySelector/singletonKeySelector jkey))
(defn new-doc-builder
[]
(let [doc (DocumentBuilderFactory/newInstance)]
(.setNamespaceAware doc true)
(.newDocumentBuilder doc)))
(defn new-xml-sig-factory
[]
(XMLSignatureFactory/getInstance "DOM"))
(defn str->xmldoc
[parsable-str]
(let [document (new-doc-builder)]
(.parse document (saml-shared/str->inputstream parsable-str))))
(defn xmlsig-from-xmldoc
[xmldoc]
(let [nodes (.getElementsByTagNameNS xmldoc XMLSignature/XMLNS "Signature")]
;;; Zero nodes means that we can't find a XML signature.
(if (= (.getLength nodes) 0)
;;(throw (Throwable. "This XML document has no signature to verify."))
nil
(.item nodes 0)))) ;;; Take the first node.
(defn get-dom-context
[kv-selector signature-node]
(DOMValidateContext. kv-selector signature-node))
(defn validate-xml-signature
"Checks if this XML document's signature is valid using the supplied certificate"
[xml-string cert-string]
(let [sig-factory (new-xml-sig-factory)
public-key (saml-shared/jcert->public-key (saml-shared/certificate-x509 cert-string))
xmldoc (str->xmldoc xml-string)
xml-sig-node (xmlsig-from-xmldoc xmldoc)
validate-signature #(let [context (get-dom-context (singleton-key-selector public-key) xml-sig-node)
signature (.unmarshalXMLSignature sig-factory context)]
(.validate signature context))]
(if xml-sig-node (validate-signature)
true)))
(defn dom-node->str [dom-node]
(let [canonicalizer (Canonicalizer/getInstance Canonicalizer/ALGO_ID_C14N_EXCL_OMIT_COMMENTS)]
(String. (.canonicalizeSubtree canonicalizer dom-node))))