diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/KEYS b/CASA-auth-token/server-java/Svc/external/xmlsec/KEYS new file mode 100644 index 00000000..8e05d3b2 --- /dev/null +++ b/CASA-auth-token/server-java/Svc/external/xmlsec/KEYS @@ -0,0 +1,142 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBDxEPCgRBADeMrVI5GwYKss+WbhLYEHaDoyVHsK85zwGk5uv4cMKk4qsmrxu +T15j/9SYHmlp9jNR7ZdzKSonVV8ME+qpWnCrwv/vKg4WuHELS8lk9FE5jXtn9MDH +cDZllccnrRMFLJdDXJuYuYXRtBvt3ZEULUVsRwJAmFdZjrAxsEtFTdSvJQCg/x2X +HwKkTutgVbQDrV7MUAMxP20D/Rj518EIR7zJ8+ev2lWV99RoZO/l44guwklwC3H+ +wqUhAJ898E7CQsHMOa1PsciYizl+YAQC0AQ3K9j64sj7hHD4ZNngWVOEOO7s36hl +PTuzL2WOx76O49oCVtfxiM0DtKQolVMqN1OfiHHMFRIj1SFsruVBdEkwYKGvfVWk +/LPiA/9Lb0fJlcQDdpGEtijnuMu2xTJMAb/Xcq6sSuZkl/Ykij64lk9BdsfcFRBr +0Xh7KzqtADLZ8XPTJI6XZj+ytbWXXdi2Hahs4HK/y7vveErKiviYSxFhRlgpY6lV +uiuIPENy/+wfZx3Fpdk2YDXeJIBN70FWAbmlDsvj3ZsnW1EQwLQsQ2hyaXN0aWFu +IEdldWVyLVBvbGxtYW5uIDxnZXVlcnBAYXBhY2hlLm9yZz6JAFgEEBECABgFAjxE +PCkICwMJCAcCAQoCGQEFGwMAAAAACgkQrc03WC8EhM0OzQCg2Pzsq+09gIsK6qTV +quduJCHMNykAn0u+Rq2ftJQPXOwcUGvF4yxcsF54iQEcBBABAgAGBQI8RDxHAAoJ +EE/ylwIE5/aVtAMIALcvI/B8FhjnS7RPJU1q9oCXdb5jgDVvXgFJEuDghSATxOjn +Hrjtrsj1x9QdAY23lBDy4GKgiwwZDAy2hcmr2DL20AqdA6FAy8H1/7Cgl8MUNI2m +Q2BjLnjuIlH9RZXhkJhUv4E7Np0IaRQMtCzW/oqu2LGRHqiq4R1ZiIhsHGfeAfrd +2skJPTs+9SHg4dndfvueOS0mLbeOztwN5k1N2uHafFkcFCDx4vKjcn7+qnw/YaYG +g2tsIGkwKr8dh+Yxf2Xhej7vRGgnNf1QMkvLFXiHEtx0o83GloR2bI8AFYp5ba9D +veMXNk5SUUd5O9AOqMe1f74LMAIFtGC/K6aOCIGJAEYEEBECAAYFAjxEPFkACgkQ +9kCJQ/wGyi3orACgiJIRnrQRN8ANs6xiKnwNdPLq6MsAoN3wyfQV5L1MV7zlO6ne +FxdUBDBzuQINBDxEPCkQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoB +p1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnh +V5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr +5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4 +XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zaf +q9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/9LL8Uz61JXVOxZ +C4hYgyP0SV0GgYoUiKmVbU1+/1dkiFvMV7beDJEDOKbVUurdpEKLTwO7s9YUAmp6 +6WvwtqGkCU7aHEsXMRSwSGoEXpQDHXHTwUjTtRvoBpd/LQ4t+ny1+B+p+PLt/cGJ +RqvGHK/n9rlTb5jxzjCxRbhXqezmnJSwGG5fQD2mRtCQ9w3wgaxN/bVvxGnBgJO+ +TYo5PomNLa/24ujT4dPxKf2SFokuLJmgNRzRkaEtSV97t7lCYM05crOdcWbI2rPr +c2FuzTig9gL4qB9QJRnpYI/VfbnsVAI+Qn66O+dPz7T2WNwj6CihodSdSxO3oo7Z +rJsNjeOLiQBMBBgRAgAMBQI8RDwpBRsMAAAAAAoJEK3NN1gvBITNRqwAnRLnb+ng +Bsho6M4hWqkwmdxRNw1xAJ9Jor374EYfbkYkHxejfoQUkJTmeg== +=fPiH +-----END PGP PUBLIC KEY BLOCK----- + + +pub 1024D/B990D401 2003-02-15 Berin Lautenbach + Key fingerprint = 03A7 690B E75C F9BF 15FF A362 7042 2E3D B990 D401 +sig 3 B990D401 2003-02-15 Berin Lautenbach +sig 609CD2C0 2003-02-15 Berin Lautenbach +sub 2048g/04284FDD 2003-02-15 +sig B990D401 2003-02-15 Berin Lautenbach + + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.1 (GNU/Linux) + +mQGiBD5OCBQRBACt0CGpKMnjauQ5FXwshMRRA+t706lf16ANsXBpdADkQTJXby0O +Vj/c9xzyEGi+H3ODBl6BIqMkGZKXwVFfJus8ctBkvBs1vCObzVH6xxCzVzwFo+rc +5mdJbf3EV65roAFLG1jbLgwadEgZumj7tNYuX8fpAZkVqR0FyE4q8Nr8PwCgzc4J +6Za6y+on5Rw61cN6vyovJZsEAKoSupBUfs945BBnK+QwfgpWRKeybF4bO27rtAVH +fFqEjOlBIM0tTbcA4q5T+1rFKOIOqsYVb50mVBybo6n4zRXOvZmoe5fAHlyN6GDA +zn0ozfCd3e+skB1FBkxo/x6miWqv2ks5IF1VOYZRknGfudBhUoUZY0dintohxVuA +eL71A/4tsx5TdPsZtUp7rfmOoj9S7F8As8rJ7ijfticdg6Z50IJKhuCsS3Vgwmnz +Zi4QSlGfbvCql38Kdwhsyx2jjR3AK0GTeq4ik1jv+HmsW//OnA8CDEljVnyVKZz+ +hVx7sakniAXAggOXSRs8WE2aYZcwTKbUqJeRd1rA7DEJ/g2GEbQmQmVyaW4gTGF1 +dGVuYmFjaCA8YmxhdXRlbmJAYXBhY2hlLm9yZz6IVwQTEQIAFwUCPk4IFAULBwoD +BAMVAwIDFgIBAheAAAoJEHBCLj25kNQByp8AnArT68V2aV8ti5epH9wc/FrVKbiS +AKDMztjQXlkVYjsOhh6DIYabN3I8m4hGBBARAgAGBQI+TgkbAAoJEBf9q+hgnNLA +Q5AAn2Lyyyq/Uy3T8zclslGQUby+1VaQAKCPL28vDFp2TrX07TDkXMJqJzI0TLkC +DQQ+Tgg2EAgAm32VA74jozy/kz39ph0rbLnpJzYxnB9ksVmxEMgtj7x8+qth7CIH +DjopxSYCf1j4RF3sHQtlyAZafbulV3mU7xA0vDq4fVsNLRV51NFjULHxSkt/rA6C +KbjRq2qYIeCtaqivWUwxjKo06WmDq6dCavDdqf9J8opVv7QUvXiT/vV6yBzygkr0 +T1C9Gny4jiIryUSi1eWxbKLHLh1zj/zCgOjyDbsyKHF5wefF0PzNrak+IzTwP6gj +FSLl+DFjEZsINDR1lKiAQucm2xfqLLttAEEXhW25D3/BuD92eVXx9bpz6kw4ZB9A +Yk+4tbrr2ly4+9PDLCZjWGDSDAGWhlGYzwADBQf9HbL9wOex+LKDlSCW1ZckRvOK +jGwvvhr8YUDinK7B3pYs3pLOVXxd14kHryhE8iEWnCrzgLMgJxS3/ryzvOOvL5Rr +F9B94doNvxeUzk5Cn4ppMlmhB74Jp6QbXj7rVa5LpnphdrnNxMMRiWCEjrJMC1Og +dokRWI9hAhyAYEqQKGt/Vy8o+FVs1yM4DxK8X0L6z6OnrpVqfNBDRs2R1lTs0G/u +LS30dsBTXn5IZAYllb2VU3ocL40e45emmLTxVSvSRDBkcULYo4ZydNR9hMVy6TfU +Q0cZZ6tpiL+exlYb6MeOQb5lbDzCnWQ5pOW7RCjOevyf6pFV7HUgSWAcJpNl/ohG +BBgRAgAGBQI+Tgg2AAoJEHBCLj25kNQBeA0AoJ25w7yjduC3BedW4izdUCKcDZLe +AJsEGTqwf0MYTdebbMXoZlVStqiRBQ== +=e1F3 +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQGiBEG1ilMRBACUX9pWnOfhIWK+aAZPydwqABQRmhBim0LqrmbqEcW/6Aaiv05H +8+2Y88ENzhSUpoobx/mlkfi+H/sdi86J2zd26kPevykoXmPkQ+Dcj1sif7K21RIX +b2QFoPD9lki6ffk8H38Xx/UaAz9xeyKZEBBMICUd/pFcJDwpwMa9AsGCxwCg5fBD +8WeNuEqmV918e0UNCCfbvisD/R7iN2PrhCp3ERqGjmRM+TjgmfS8CnXinOYLNp5H +lxgjdqy497VLEYoZgFGsG5TYyK9QmWYiQ4HdlwkSBQeZcIuhs+D/16HFXgXRTQhQ +KN3hNOjn5vA6m6kEpkKis72Kvdn1lcWdWJNBTiXdK4O7232k1N+8pglF642M3fNB +WzVSA/9sU5AbnU9cQ3wOitGhIONNPt76KjtNvS3AYuR+3Zo0KIaDd1Rxvfzob2xr +t1unZRW2jd6FYVz2qtCHXG07bbkmRbttBDw0IJIPw9lkvdyF71WTZH+6U633TxLM +3ZT+3TfcOi8fSQiWnJzASZ2Yy/ZfnG9YxmMhtuiDkAGbcR11UrQkUmF1bCBCZW5p +dG8gR2FyY2lhIDxyYXVsQGFwYWNoZS5vcmc+iF4EExECAB4FAkG1ilMCGwMGCwkI +BwMCAxUCAwMWAgECHgECF4AACgkQtImwQHrM6+xGlwCfVlNi4dz6bbPUyFqIZB5F +7sKwe7YAoJ5yZ92LrG71QBp53PZu/d6F4zGwuQINBEG1imwQCACMhxnoh563xmVa +xB4l0Zs1ZwXQ61aNJT67p+8vvGyzMQ0T2HYHt59ZyuWmV8U0kDQe4A8AVm7HnANZ +1LyCiNM/3xLmNoZzek9dOqzBrJqtUjLXJSE81wZJzTscDdW9K6hoSIwnUYxzt0ie +oup+Rm/BWSlSvSx35X9aFpcFM1Iru66nvolNfNgjGN4mpp2r/W3yOsW6DcapWmp0 +t891tGHU4E19DtjFmMC55eO9Vp3gxOpIP2MxICVB8GBkwMt4ecuoI++znJcBXpo+ +bvF75OaHeP9qVLy7UV1walZfO3fLO3GegI9oMiI4uvc9CYiJpBa3mBDNYr9Axl4z +9ajJz9e3AAMFB/95RK3Ioh4u3cEE5jY7yLwSDAuqD6GjGHywqkmT6k5WOQHqy7HI +Sjk5Aye3dyNyl5POTMPmSZn4u6lIlWSj1zbipmVF6UvlX9ei6YKTJo8pDcjSZdb6 +1vdeJd1l9taoKXHPE1u/xvNsZgH6+QjlGb1lxs0m/1qfNyzZqKPZNHXiqvVHMNH6 +vTSCqW+OO1aPnSEOcSq6NX6X9Un6n/p3WLu5eD+2eObYL0oCTMf7Idwlzo/kXDtp +sCktwTR4pSPbXeMSaKztpWfXEz8CLQ2YIer66+b6Sbp1n+H/kPp+8aTZYs8fGZe0 +mRv4mbxIr041YpV4vLqbtPNvwMPNYcm+DHZBiEkEGBECAAkFAkG1imwCGwwACgkQ +tImwQHrM6+wXfACgpdr9BhV7M2j5uype8R839dlGuyMAnREBnNTtKqss7+S87nyU +KlDKaJbI +=zQ4J +-----END PGP PUBLIC KEY BLOCK----- +pub 1024D/6103BF59 9/5/2003 Davanum Srinivas (CODE SIGNING) + Primary key fingerprint: A67E 5FD8 80EB 089F 2317 7967 80D8 3A79 6103 BF59 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.3 (MingW32) - WinPT 0.11.12 + +mQGiBD9Y7IURBAD6qYBnCjMLzjfKqAtfBvmOHBLwfpv1NPZPQXbkpO15tRvU0FRX +W9eoqgpRwFvc3+gMsnRuQ5t4pHM4qrbFYIPmGh+uA3CzhVmd9+b5v0WnbIpF7PGU +ttvK7ICKUCewuHA0lYZ0hNjGynRLl2ehR9HCrPTZeTskq4iGYXsO5w7PEQCg/05A +gW5oQIQr7YwvhorDFWiv/EsD/jILL+hmxKpKht1D+YJG6s+aHzMEHIG9/NAhjq6+ +K4L7ZdDoLjkX04oXXZjNsV3FZopMw9AtMlqELw4l6CIPEWOL6Tkh6/UmmnwpUuvr +bXfYFvqhFckq4VgC52chLYmVoNI6YFhrhLFGoeluYY5e2oV+Rg4Wngn8FqmL4/Tl +xUToA/4mMl4ECPUVPEA+5f7r/9lRI9B6qJPYTQ8gaGo2SxHS8t6AwnjEyGG7ZNWd +rZSj2gsOS6BcyCXuiGwS1CUMr9oHvCprsLGai5i/d8DR/I89krUYVIymVcW3DqGa +zXW6vSi5ryxDiYwWl5bS3JKr5cSMilLrlRuWx461Y3upuaaZ+bQxRGF2YW51bSBT +cmluaXZhcyAoQ09ERSBTSUdOSU5HKSA8ZGltc0BhcGFjaGUub3JnPohOBBARAgAO +BQI/WOyFBAsDAgECGQEACgkQgNg6eWEDv1md5gCgrhuJC5pQmpsVUzhb6s6qrky+ +lzoAoLWG370yw84vCTtm4rqukCxKckFxuQINBD9Y7IUQCAD2Qle3CH8IF3Kiutap +QvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfU +odNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7H +AarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxb +LY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyE +pwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1Xp +Mgs7AAICB/9A7c0FSYaXGQwQmwCNMc2HHuwJiUqgO50SDbjiYGyKDM9QCVonbu/V +zKIJ1+caCnAaqlYZRXB53AYa3pk0teO39hT1YqNequfYcZdd7+R00YBPM409Ja4f +Az/A9YYxC/IDiu0YOA+/kuZsatUv/mvOf6hW7UDr0BgFy79CAhhQZgwJm3rilkeu +py5L3ns+H5EJ2/NI2IGbzcQMTWWFT4WY1LHreS7yPvDLvtlZmBhlEN0JZJQM5oRZ +R1hOcSA5elQMYrn056I1u0FrX3TEZG/RPNkPv7C68sxEUmus0lviq4hqydKE/qgB +qIEZEHhzgPrNhw1D/O59+ZN/WMzB9IigiEYEGBECAAYFAj9Y7IUACgkQgNg6eWED +v1l9ygCghBaiVuzN0Z5XZw7IGyGEn4sqkvMAoMzWc6pmSDSX+6hmhli4WXCIsldH +=yLoD +-----END PGP PUBLIC KEY BLOCK----- + + + diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/commons-logging.jar b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/commons-logging.jar new file mode 100644 index 00000000..b73a80fa Binary files /dev/null and b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/commons-logging.jar differ diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/xalan.jar b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/xalan.jar new file mode 100644 index 00000000..979ee761 Binary files /dev/null and b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/xalan.jar differ diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/xmlsec-1.4.0.jar b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/xmlsec-1.4.0.jar new file mode 100644 index 00000000..f3a45ac5 Binary files /dev/null and b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-1_4_0/libs/xmlsec-1.4.0.jar differ diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-bin-1_4_0.zip b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-bin-1_4_0.zip new file mode 100644 index 00000000..fb54d075 Binary files /dev/null and b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-bin-1_4_0.zip differ diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-bin-1_4_0.zip.asc b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-bin-1_4_0.zip.asc new file mode 100644 index 00000000..e10efc39 --- /dev/null +++ b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-bin-1_4_0.zip.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.5 (Cygwin) + +iD8DBQBFhwWdtImwQHrM6+wRAt6YAKDD2KsP/owrw4SWu7bfdejXr4NbOwCeMhyd +1EPh+zzlfrSAoEatfVB3lYI= +=R9lz +-----END PGP SIGNATURE----- diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-src-1_4_0.zip b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-src-1_4_0.zip new file mode 100644 index 00000000..a872f463 Binary files /dev/null and b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-src-1_4_0.zip differ diff --git a/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-src-1_4_0.zip.asc b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-src-1_4_0.zip.asc new file mode 100644 index 00000000..f8950e5d --- /dev/null +++ b/CASA-auth-token/server-java/Svc/external/xmlsec/xml-security-src-1_4_0.zip.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.5 (Cygwin) + +iD8DBQBFhwWotImwQHrM6+wRAtvUAJ9R6uUWCw+1RYfAi4AO7srYQ7mxUwCdGDPn +L02dDJKgli5he+UE3GQGWss= +=sMrX +-----END PGP SIGNATURE----- diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java index fb4e8634..6f6b451d 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java @@ -26,21 +26,17 @@ package com.novell.casa.authtoksvc; import java.io.ByteArrayInputStream; -import org.apache.axis.Message; -import org.apache.axis.MessageContext; -import org.apache.axis.client.AxisClient; -import org.apache.axis.configuration.NullProvider; -import org.apache.axis.message.SOAPEnvelope; -import org.apache.axis.message.SOAPBody; -import org.apache.axis.message.MessageElement; import org.apache.log4j.Logger; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; +import org.apache.xml.security.utils.Constants; +import org.apache.xerces.parsers.DOMParser; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; -import javax.xml.namespace.QName; import java.io.*; -// Un-comment the following line to print Authentication Token Messages -//import org.apache.axis.utils.XMLUtils; - /** * AuthToken Class. @@ -51,7 +47,10 @@ import java.io.*; * and with a timestamp. The body of the SOAP message is as follows: *

* - * Identity Token typeidentity token data + * + * Identity Token type + * identity token data + * * * */ @@ -65,18 +64,9 @@ public final class AuthToken private String m_identityTokenType = null; private String m_identityToken = null; - static final String authTokenSoapMsg = - "" + - "" + - " " + - " " + - " " + - ""; + static private SecureTokenUtil m_serverSecTokenUtil = null; + static private SecureTokenUtil m_clientSecTokenUtil = null; - static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider())); /** * Constructor. @@ -102,61 +92,90 @@ public final class AuthToken AuthTokenConfig authTokenConfig = enabledSvcsConfig.getAuthTokenConfig(targetHost, targetService); if (authTokenConfig != null) { - OutputStream outStream = null; - try + // For now lets use the services of the only IdentityToken provider + // that we have. + // + // tbd - Add code to allow for the consumption of tokens + // from different providers. + CasaIdentityToken identityToken = new CasaIdentityToken(enabledSvcsConfig.getIdenTokenConfig(targetHost, targetService)); + identityToken.initialize(identityId, + realm, + realmUrl, + targetService, + targetHost, + svcConfig); + + m_identityToken = identityToken.getEncodedToken(); + m_identityTokenType = identityToken.getProviderType(); + + m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime); + m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter); + + // Get secure token util object + SecureTokenUtil secTokenUtil = getSecureTokenUtilObj(true); + if (secTokenUtil != null) { - // For now lets use the services of the only IdentityToken provider - // that we have. - // - // tbd - Add code to allow for the consumption of tokens - // from different providers. - CasaIdentityToken identityToken = new CasaIdentityToken(enabledSvcsConfig.getIdenTokenConfig(targetHost, targetService)); - identityToken.initialize(identityId, - realm, - realmUrl, - targetService, - targetHost, - svcConfig); - - m_identityToken = identityToken.getEncodedToken(); - m_identityTokenType = identityToken.getProviderType(); - - m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime); - m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter); - - // Create AuthTokenMessage - Message authTokenMessage = getMessage(identityToken.getEncodedToken(), - identityToken.getProviderType(), - Integer.valueOf(m_lifetime).intValue(), - svcConfig, - (targetHost.compareTo("localhost") == 0) ? false : true); - - // Un-comment the following line to print Authentication Token Messages - //XMLUtils.PrettyElementToWriter(authTokenMessage.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out)); - - // Now save the message as a string - outStream = new ByteArrayOutputStream(); - authTokenMessage.writeTo(outStream); - m_token = outStream.toString(); - } - catch (Exception e) - { - m_log.error("Constructor()- Exception: " + e.toString()); - throw e; - } - finally - { - if (outStream != null) + // Obtain secure token template document + Document tokenDoc = SecureTokenUtil.getSecureTokenTemplate(); + if (tokenDoc != null) { + // Secure token template obtained, now get its top most element. + Node tokenElement = tokenDoc.getDocumentElement(); + + // Add authentication token payload to the token + Node soapBodyElement = SecureTokenUtil.findChildNodeNS(tokenElement, "http://www.w3.org/2003/05/soap-envelope", "Body"); + Node authTokenElement = tokenDoc.createElement("auth_token"); + soapBodyElement.appendChild(authTokenElement); + Node idenTokenElement = tokenDoc.createElement("ident_token"); + authTokenElement.appendChild(idenTokenElement); + Node idenTokenProviderElement = tokenDoc.createElement("ident_token_provider"); + idenTokenProviderElement.setTextContent(m_identityTokenType); + idenTokenElement.appendChild(idenTokenProviderElement); + Node idenTokenDataElement = tokenDoc.createElement("ident_token_data"); + idenTokenDataElement.setTextContent(m_identityTokenType); + idenTokenElement.appendChild(idenTokenDataElement); + + // Secure the token + secTokenUtil.secure(tokenDoc, Integer.valueOf(m_lifetime).intValue()); + + // Now save the token as a string + OutputStream outStream = null; try { - outStream.close(); + outStream = new ByteArrayOutputStream(); + OutputFormat format = new OutputFormat(tokenDoc); + XMLSerializer serializer = new XMLSerializer(outStream, format); + serializer.serialize(tokenDoc.getDocumentElement()); + m_token = outStream.toString(); } - catch (IOException e) + finally { - // Do nothing + if (outStream != null) + { + try + { + outStream.flush(); + outStream.close(); + } + catch (Exception e) + { + // Do nothing + } + } } } + else + { + // Failed to obtain secure token template + m_log.warn("Constructor()- Failed to obtain secure token template"); + throw new Exception("AuthToken.Constructor()- Failed to obtain secure token template"); + } + } + else + { + // Failed to obtain secure token util object + m_log.warn("Constructor()- Failed to obtain secure token util object"); + throw new Exception("SessionToken.Constructor()- Failed to obtain secure token util object"); } } else @@ -177,24 +196,106 @@ public final class AuthToken public AuthToken(String token, boolean encodedToken) throws Exception { - // Decode the token string if necessary - if (encodedToken) - m_token = Base64Coder.decode(token); - else - m_token = token; - - // Now instantiate a SOAP message with the string InputStream inStream = null; - org.apache.axis.Message message = null; + try { + // Decode the token string if necessary + if (encodedToken) + m_token = Base64Coder.decode(token); + else + m_token = token; + + // Now instantiate token document with the token string inStream = new ByteArrayInputStream(m_token.getBytes()); - message = new Message(inStream); - } - catch (Exception e) - { - m_log.warn("Constructor()- Exception caught creating message, msg: " + e.getMessage()); - throw new Exception("Invalid Authentication Token", e); + Constants.setSignatureSpecNSprefix(""); + + DOMParser parser = new DOMParser(); + parser.setFeature("http://xml.org/sax/features/namespaces", true); + parser.parse(new InputSource(inStream)); + Document tokenDoc = parser.getDocument(); + + // Obtain secure token util object + SecureTokenUtil secTokenUtil = getSecureTokenUtilObj(false); + if (secTokenUtil != null) + { + // Use the secure token util to validate the token + if (secTokenUtil.valid(tokenDoc)) + { + // The authentication token is valid, now obtain the identity token + // information from it. + Node tokenElement = tokenDoc.getDocumentElement(); + if (tokenElement != null) + { + Node soapBodyElement = SecureTokenUtil.findChildNodeNS(tokenElement, + "http://www.w3.org/2003/05/soap-envelope", + "Body"); + if (soapBodyElement != null) + { + Node authTokenElement = SecureTokenUtil.findChildNode(soapBodyElement, "auth_token"); + if (authTokenElement != null) + { + Node identTokenElement = SecureTokenUtil.findChildNode(authTokenElement, "ident_token"); + if (identTokenElement != null) + { + Node identTokenProviderElement = SecureTokenUtil.findChildNode(identTokenElement, + "ident_token_provider"); + Node identTokenDataElement = SecureTokenUtil.findChildNode(identTokenElement, + "ident_token_data"); + if (identTokenProviderElement != null + && identTokenDataElement != null) + { + m_identityTokenType = identTokenProviderElement.getTextContent(); + m_identityToken = identTokenDataElement.getTextContent(); + } + else + { + // Missing identity token element child + m_log.warn("Constructor(String)- Unable to obtain identity token element child"); + throw new Exception("AuthToken.Constructor(String)- Unable to obtain identity token element child"); + } + } + else + { + // Missing ident token element + m_log.warn("Constructor(String)- Unable to obtain ident token element"); + throw new Exception("AuthToken.Constructor(String)- Unable to obtain ident token element"); + } + } + else + { + // Missing auth token element + m_log.warn("Constructor(String)- Unable to obtain auth token element"); + throw new Exception("AuthToken.Constructor(String)- Unable to obtain auth token element"); + } + } + else + { + // Invalid SOAP message + m_log.warn("Constructor(String)- Unable to obtain soap body element"); + throw new Exception("AuthToken.Constructor(String)- Unable to obtain soap body element"); + } + } + else + { + // Invalid XML document + m_log.warn("Constructor(String)- Unable to obtain document element"); + throw new Exception("AuthToken.Constructor(String)- Unable to obtain document element"); + } + } + else + { + // Message verification failed + m_log.warn("Constructor(String)- Invalid Auth Token"); + throw new Exception("AuthToken.Constructor(String)- Invalid Auth Token"); + } + } + else + { + // Failed to obtain secure token util object + m_log.warn("Constructor(String)- Failed to obtain secure token util object"); + throw new Exception("AuthToken.Constructor(String)- Failed to obtain secure token util object"); + } } finally { @@ -210,114 +311,57 @@ public final class AuthToken } } } - - // Get access to the SOAP Envelope - SOAPEnvelope envelope = message.getSOAPEnvelope(); - - // Verify the message - if (WSSecurity.verifyMessage(envelope)) - { - // Message verification succeded, now obtain the identity token - // and its type from the message body. - SOAPBody body = (SOAPBody) envelope.getBody(); - QName authTokenElementName = new QName("auth_token"); - MessageElement authTokenElement = body.getChildElement(authTokenElementName); - QName identTokenElementName = new QName("ident_token"); - MessageElement identTokenElement = authTokenElement.getChildElement(identTokenElementName); - if (identTokenElement != null) - { - QName identTokenTypeElementName = new QName("type"); - MessageElement identTokenTypeElement = identTokenElement.getChildElement(identTokenTypeElementName); - if (identTokenTypeElement != null) - { - m_identityToken = identTokenElement.getChildNodes().item(1).getNodeValue(); - m_identityTokenType = identTokenTypeElement.getValue(); - } - } - - if (m_identityToken == null || m_identityTokenType == null) - { - m_log.warn("Constructor()- Required data missing from authentication token"); - throw new Exception("Error: Required data missing from Authentication Token"); - } - } - else - { - // Message verification failed - m_log.warn("Constructor()- Invalid Authentication Token"); - throw new Exception("Invalid Authentication Token"); - } } /** - * Get AuthToken SOAP Message. + * Gets object to be utilized for creating and verifying secure tokens. * - * @param identityToken String containing the identity token that should be part of the message. - * @param identityTokenType String containing the identity token type. - * @param lifetime Lifetime that should be specified in the message timestamp (seconds). - * @param svcConfig Service configuration object. - * @param includeCert True if the message should include the Public Certificate. - * @return AuthToken message, null if the method fails. + * @param serverMode True if to be used to secure tokens. + * @return SecuteTokenUtil object or null if the method fails. */ - private static Message getMessage(String identityToken, - String identityTokenType, - int lifetime, - SvcConfig svcConfig, - boolean includeCert) + private static synchronized SecureTokenUtil getSecureTokenUtilObj(boolean serverMode) { - Message secureMessage; - InputStream inStream = null; - - try + // Proceed based on the mode spacified + if (serverMode) { - // Build SOAP Message with an identity token in the body - // - // First create a message and obtain its body - inStream = new ByteArrayInputStream(authTokenSoapMsg.getBytes()); - Message message = new Message(inStream); - message.setMessageContext(axisMsgContext); - SOAPBody body = (SOAPBody) message.getSOAPBody(); - - // Get access to the auth_token element - QName authTokenElementName = new QName("auth_token"); - MessageElement authTokenElement = body.getChildElement(authTokenElementName); - - // Get access to the ident_token element and set its value - QName identTokenElementName = new QName("ident_token"); - MessageElement identTokenElement = authTokenElement.getChildElement(identTokenElementName); - identTokenElement.addTextNode(identityToken); - - // Get access to the identity token type element element and set its value - QName identTokenTypeElementName = new QName("type"); - MessageElement identTokenTypeElement = identTokenElement.getChildElement(identTokenTypeElementName); - identTokenTypeElement.setValue(identityTokenType); - - // Now we need to secure the SOAP message that we created, we are doing to - // do so by adding a timestamp and signing the timestamp as well as the body. - // To do this we are going to leverage WS-Security. - secureMessage = WSSecurity.secureSOAPEnvelope(message.getSOAPEnvelope(), - lifetime, - svcConfig, - includeCert); - } - catch (Exception e) - { - m_log.error("getMessage() - Exception caught building message, error: " + e.getMessage()); - secureMessage = null; - } - if (inStream != null) - { - try + // Instantiate the server object if it has not been instantiated already + if (m_serverSecTokenUtil == null) { - inStream.close(); + try + { + // Instantiate secure token object to be utilized in server type operations + m_serverSecTokenUtil = new SecureTokenUtil(true); + } + catch (Exception e) + { + // Exception caught + m_log.warn("getSecureTokenUtilObj()- Exception caught, message = " + e.getMessage()); + } } - catch (IOException e) - { - // Do nothing - } - } - return secureMessage; + // Return the object + return m_serverSecTokenUtil; + } + else + { + // Instantiate the client object if it has not been instantiated already + if (m_clientSecTokenUtil == null) + { + try + { + // Instantiate secure token object to be utilized in server type operations + m_clientSecTokenUtil = new SecureTokenUtil(true); + } + catch (Exception e) + { + // Exception caught + m_log.warn("getSecureTokenUtilObj()- Exception caught, message = " + e.getMessage()); + } + } + + // Return the object + return m_clientSecTokenUtil; + } } /** diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java index 42818483..f09d8f5f 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java @@ -346,8 +346,7 @@ public final class Authenticate implements RpcMethod // An identity was resolved, get a SessionToken for it. SessionToken sessionToken = new SessionToken(identId, authReqMsg.getRealm(), - m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime), - m_svcConfig); + m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)); // Write out the response String respLifetime = Integer.toString(Integer.valueOf(m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)).intValue() diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SecureTokenUtil.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SecureTokenUtil.java new file mode 100644 index 00000000..c6d5cf3a --- /dev/null +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SecureTokenUtil.java @@ -0,0 +1,749 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +//package com.novell.casa.authtoksvc; + +package com.novell.casa.authtoksvc; + +import java.io.*; + +import org.apache.xml.security.c14n.Canonicalizer; +import org.apache.xml.security.utils.Constants; +import org.apache.xml.security.signature.XMLSignature; +import org.apache.xml.security.transforms.Transforms; +import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial; +import org.apache.xml.security.keys.content.X509Data; +import org.apache.xerces.parsers.DOMParser; +import org.apache.log4j.Logger; +import org.w3c.dom.*; +import org.xml.sax.InputSource; + +import java.util.*; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.text.SimpleDateFormat; + + +/** + * SecureTokenUtil Class. + *

+ * This class provides methods for creating secure tokens. Tokens are secured in SOAP messages + * by applying a timestamp and signing the appropriate elements. The class utilizes XMlSec and + * headers defined by WS* specifications. + * + */ +public final class SecureTokenUtil +{ + private static final Logger m_log = Logger.getLogger(SecureTokenUtil.class); + + // Signing key and related certificate + private PrivateKey m_signingKey; + private X509Certificate m_signingCert; + + // Certificate issuer:sn map + // + // The map key has the format: "IssuerDN=certissuername SN=certserialnumber" + private Map m_x509ISNCertMap; + + // SecureToken template + private static final String m_secureTokenTemplate = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + /** + * SecureTokenUtil Constructor. + *

+ * @param serverMode Running as server and will be creating secure tokens. + * @throws Exception + */ + public SecureTokenUtil(boolean serverMode) throws Exception + { + InputStream inStream = null; + try + { + // Load our crypto properties + Properties cryptoProperties = new Properties(); + ClassLoader classLoader = SecureTokenUtil.class.getClassLoader(); + inStream = classLoader.getResourceAsStream("crypto.properties"); + cryptoProperties.load(inStream); + + // Get necessary keystore info from the crypto properties + String keystoreType = cryptoProperties.getProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jks"); + String keystoreFile = cryptoProperties.getProperty("org.apache.ws.security.crypto.merlin.file"); + String keystorePass = cryptoProperties.getProperty("org.apache.ws.security.crypto.merlin.keystore.password"); + if (keystoreType == null + || keystoreFile == null + || keystorePass == null) + { + m_log.error("Constructor()- Missing crypto configuration"); + throw new Exception("SecureTokenUtil()- Missing crypto configuration"); + } + + // Instantiate and load the keystore + KeyStore keyStore = KeyStore.getInstance(keystoreType); + FileInputStream fis = new FileInputStream(keystoreFile); + keyStore.load(fis, keystorePass.toCharArray()); + + // Get signing key and cert if in server mode + if (serverMode) + { + String privateKeyAlias = cryptoProperties.getProperty("org.apache.ws.security.crypto.merlin.keystore.alias"); + String privateKeyPass = cryptoProperties.getProperty("org.apache.ws.security.crypto.merlin.alias.password"); + String certificateAlias = cryptoProperties.getProperty("org.apache.ws.security.crypto.merlin.keystore.alias"); + if (privateKeyAlias == null + || privateKeyPass == null + || certificateAlias == null) + { + m_log.error("Constructor()- Missing crypto configuration"); + throw new Exception("SecureTokenUtil()- Missing crypto configuration"); + } + + // Get the key that will be used for signing tokens + m_signingKey = (PrivateKey) keyStore.getKey(privateKeyAlias, + privateKeyPass.toCharArray()); + if (m_signingKey == null) + { + m_log.error("Constructor()- Signing key not found in keystore"); + throw new Exception("SecureTokenUtil()- Signing key not found in keystore"); + } + + // Get the signing certificate + m_signingCert = (X509Certificate) keyStore.getCertificate(certificateAlias); + if (m_signingCert == null) + { + m_log.error("Constructor()- Signing cert not found in keystore"); + throw new Exception("SecureTokenUtil()- Signing cert not found in keystore"); + } + } + + // Create the Certificate issuer:sn map + m_x509ISNCertMap = new HashMap(); + Enumeration aliases = keyStore.aliases(); + while (aliases.hasMoreElements()) + { + X509Certificate cert = (X509Certificate) keyStore.getCertificate(aliases.nextElement()); + if (cert != null) + { + // Add this certificate to our map + m_x509ISNCertMap.put("IssuerDN=" + cert.getIssuerDN().getName() + " SN=" + cert.getSerialNumber().toString(), cert); + } + } + } + finally + { + // Make sure that the input stream has been closed + if (inStream != null) + inStream.close(); + } + } + + /** + * Returns the referenced X509Certificate. + * + * @param issuerName Name of the certificate issuer. + * @param serialNumber Certificate serial number. + * @return Referenced X509Certificate. + */ + private X509Certificate getCertWithX509IssuerSerialData(String issuerName, String serialNumber) + { + return m_x509ISNCertMap.get("IssuerDN=" + issuerName + " SN=" + serialNumber); + } + + /** + * Remove white space from XML. + *

+ * Note that this operation is recursively performed, + * thus limiting document depth. + * + * @param startNode Start node. + */ + private void removeWhiteSpace(Node startNode) + { + // Loop through child nodes + Node childNode; + Node nextNode = startNode.getFirstChild(); + while ((childNode = nextNode) != null) { + + // Set next before we change anything + nextNode = childNode.getNextSibling(); + + // Handle child by node type + if (childNode.getNodeType() == Node.TEXT_NODE) + { + // Trim whitespace from content text + String trimmed = childNode.getNodeValue().trim(); + if (trimmed.length() == 0) + { + // Delete child if nothing but whitespace + startNode.removeChild(childNode); + } + } + else if (childNode.getNodeType() == Node.ELEMENT_NODE) + { + // Handle child elements with recursive call + removeWhiteSpace(childNode); + } + } + } + + /** + * Set the specified prefix on elements in the specified namespace + * and remove the namespace attribute from them. + *

+ * Note that this operation is recursively performed, + * thus limiting document depth. + * + * @param startNode Start node. + * @param prefix Prefix. + * @param nsURI Name space URI. + */ + private void setPrefixSubtree(Node startNode, String prefix, String nsURI) + { + // Set the prefix on the element if necessary + if (startNode.getNodeType() == Node.ELEMENT_NODE) + { + NamedNodeMap attributes = startNode.getAttributes(); + Node nsAttr = attributes.getNamedItem("xmlns"); + if (nsAttr != null) + { + if (nsAttr.getTextContent().equalsIgnoreCase(nsURI)) + { + attributes.removeNamedItem("xmlns"); + startNode.setPrefix(prefix); + } + } + } + + // Loop through child nodes + Node childNode; + Node nextNode = startNode.getFirstChild(); + while ((childNode = nextNode) != null) { + + // Set next before we change anything + nextNode = childNode.getNextSibling(); + + // Handle child by node type + if (childNode.getNodeType() == Node.ELEMENT_NODE) + { + // Handle child elements with recursive call + setPrefixSubtree(childNode, prefix, nsURI); + } + } + } + + /** + * Find first child node with matching node name. + * + * @param parentNode Parent node. + * @param nodeName Name of node. + * @return Child node found or null. + */ + public static Node findChildNode(Node parentNode, String nodeName) + { + Node retNode = null; + Node childNode; + Node nextNode = parentNode.getFirstChild(); + while ((childNode = nextNode) != null) + { + // Set next before we change anything + nextNode = childNode.getNextSibling(); + + // Handle child by node type + if (childNode.getNodeType() == Node.ELEMENT_NODE) + { + // Check if this is the element node wanted + if (childNode.getNodeName().equalsIgnoreCase(nodeName)) + { + // Found the node + retNode = childNode; + break; + } + } + } + + return retNode; + } + + /** + * Find first child node with matching node name. + * + * @param parentNode Parent node. + * @param nsURI Namespace URI. + * @param nodeLocalName Local name of node. + * @return Child node found or null. + */ + public static Node findChildNodeNS(Node parentNode, String nsURI, String nodeLocalName) + { + Node retNode = null; + Node childNode; + Node next = parentNode.getFirstChild(); + while ((childNode = next) != null) + { + // Set next before we change anything + next = childNode.getNextSibling(); + + // Handle child by node type + if (childNode.getNodeType() == Node.ELEMENT_NODE) + { + // Check if this is the element node wanted + if (childNode.getLocalName().equalsIgnoreCase(nodeLocalName) + && childNode.getNamespaceURI().equals(nsURI)) + { + // Found the node + retNode = childNode; + break; + } + } + } + + return retNode; + } + + /** + * Sets the timestamp element. + * + * @param timeStampNode Timestamp node. + * @param ttl Time to live in seconds. + * @throws Exception + */ + private void setTimeStamp(Node timeStampNode, long ttl) throws Exception + { + boolean success = false; + + // Find the Created and Expires nodes + Node wsCreated = findChildNode(timeStampNode, "wsu:Created"); + Node wsExpires = findChildNode(timeStampNode, "wsu:Expires"); + if (wsCreated != null + && wsExpires != null) + { + // We found the nodes, now set the needed information in them. + SimpleDateFormat ISO8601UTC = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + ISO8601UTC.setTimeZone(TimeZone.getTimeZone("UTC")); + + Date date = new Date(); + + wsCreated.setTextContent(ISO8601UTC.format(date)); + + date.setTime(date.getTime() + (ttl * 1000)); + wsExpires.setTextContent(ISO8601UTC.format(date)); + + success = true; + } + + // Throw exception if not successful + if (!success) + { + m_log.error("setTimeStamp()- Failed to set timestamp"); + throw new Exception("SecureTokenUtil.setTimeStamp()- Failed to set timestamp"); + } + } + + /** + * Validates timestamp element. + * + * @param timeStampNode Timestamp node. + * @throws Exception + */ + private void validateTimeStamp(Node timeStampNode) throws Exception + { + // Find Expires node + Node wsExpires = findChildNodeNS(timeStampNode, + "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", + "Expires"); + if (wsExpires != null) + { + // We found the node, now check if it has expired. + SimpleDateFormat ISO8601UTC = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + ISO8601UTC.setTimeZone(TimeZone.getTimeZone("UTC")); + + Date currDate = new Date(); + Date expiresDate = ISO8601UTC.parse(wsExpires.getTextContent()); + if (currDate.compareTo(expiresDate) > 0) + { + m_log.warn("validateTimeStamp()- Timestamp expired"); + throw new Exception("SecureTokenUtil.validateTimeStamp()- Timestamp expired"); + } + } + else + { + m_log.error("validateTimeStamp()- Bad timestamp element"); + throw new Exception("SecureTokenUtil.validateTimeStamp()- Bad timestamp element"); + } + } + + /** + * Validates secure token. + * + * @param tokenDoc Token document. + * @return True if validation succeeded. + */ + public boolean valid(Document tokenDoc) + { + boolean msgVerificationStatus = false; + + try + { + // Get document element + Element docElement = tokenDoc.getDocumentElement(); + + // Find the relevant nodes in the document + Node soapHeaderNode = findChildNodeNS(docElement, "http://www.w3.org/2003/05/soap-envelope", "Header"); + Node soapBodyNode = findChildNodeNS(docElement, "http://www.w3.org/2003/05/soap-envelope", "Body"); + if (soapHeaderNode != null && soapBodyNode != null) + { + // We found the header of the message, now find the + // WS-Security node. + Node wsSecurityNode = findChildNodeNS(soapHeaderNode, + "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", + "Security"); + if (wsSecurityNode != null) + { + // We found the WS-Security node, now find the + // Signature and Timestamp nodes. + Node signatureNode = findChildNodeNS(wsSecurityNode, + "http://www.w3.org/2000/09/xmldsig#", + "Signature"); + Node timeStampNode = findChildNodeNS(wsSecurityNode, + "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", + "Timestamp"); + if (signatureNode != null && timeStampNode != null) + { + // Validate the timestamp before doing any other processing + validateTimeStamp(timeStampNode); + + Node signedInfoNode = findChildNodeNS(signatureNode, + "http://www.w3.org/2000/09/xmldsig#", + "SignedInfo"); + Node keyInfoNode = findChildNodeNS(signatureNode, + "http://www.w3.org/2000/09/xmldsig#", + "KeyInfo"); + if (signedInfoNode != null && keyInfoNode != null) + { + // Make sure that we are referencing the Timestamp and Soap Body nodes in the signature + boolean timeStampReferenced = false; + boolean soapBodyReferenced = false; + NamedNodeMap attributes = timeStampNode.getAttributes(); + Node timeStampIdNode = attributes.getNamedItemNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", + "Id"); + attributes = soapBodyNode.getAttributes(); + Node soapBodyIdNode = attributes.getNamedItemNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", + "Id"); + if (timeStampIdNode != null && soapBodyIdNode != null) + { + Node child; + Node next = signedInfoNode.getFirstChild(); + while ((child = next) != null) + { + // Set next + next = child.getNextSibling(); + + // Check if we are dealinf with a reference node + if (child.getNodeType() == Node.ELEMENT_NODE + && child.getLocalName().equalsIgnoreCase("Reference") + && child.getNamespaceURI().equals("http://www.w3.org/2000/09/xmldsig#")) + { + // Found a reference node, get its attributes. + attributes = child.getAttributes(); + Node refUriNode = attributes.getNamedItem("URI"); + if (refUriNode != null) + { + if (refUriNode.getTextContent().equals("#" + timeStampIdNode.getTextContent())) + { + timeStampReferenced = true; + } + else if (refUriNode.getTextContent().equals("#" + soapBodyIdNode.getTextContent())) + { + soapBodyReferenced = true; + } + } + } + } + } + + // Proceed if both the Timestamp and the Soap Body are referenced in the signature + if (timeStampReferenced && soapBodyReferenced) + { + Node secTokenRefNode = findChildNodeNS(keyInfoNode, + "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", + "SecurityTokenReference"); + if (secTokenRefNode != null) + { + Node x509DataNode = findChildNodeNS(secTokenRefNode, + "http://www.w3.org/2000/09/xmldsig#", + "X509Data"); + if (x509DataNode != null) + { + Node x509IssuerSerialNode = findChildNodeNS(x509DataNode, + "http://www.w3.org/2000/09/xmldsig#", + "X509IssuerSerial"); + if (x509IssuerSerialNode != null) + { + Element x509IssuerNameNode = (Element) findChildNodeNS(x509IssuerSerialNode, + "http://www.w3.org/2000/09/xmldsig#", + "X509IssuerName"); + Element x509SerialNumberNode = (Element) findChildNodeNS(x509IssuerSerialNode, + "http://www.w3.org/2000/09/xmldsig#", + "X509SerialNumber"); + if (x509IssuerNameNode != null && x509SerialNumberNode != null) + { + // Find the certificate in our KeyStore + X509Certificate cert = getCertWithX509IssuerSerialData(x509IssuerNameNode.getTextContent(), + x509SerialNumberNode.getTextContent()); + + // Verify signature that we found the referenced certificate + if (cert != null) + { + // Verify the signature + XMLSignature sig = new XMLSignature((Element) signatureNode, ""); + boolean signatureOk = sig.checkSignatureValue(cert); + if (signatureOk) + { + // Success + msgVerificationStatus = true; + } + else + { + m_log.warn("valid()- Signature verification failed"); + } + } + else + { + m_log.warn("valid()- Referenced certificate not found"); + } + } + else + { + m_log.warn("valid()- Not able to find X509IssuerSerial node child"); + } + } + else + { + m_log.warn("valid()- Not able to find X509IssuerSerial node"); + } + } + else + { + m_log.warn("valid()- Not able to find X509Data node"); + } + } + else + { + m_log.warn("valid()- Not able to find SecurityTokenReference node"); + } + } + else + { + m_log.warn("valid()- Signature does not cover necessary elements"); + } + } + else + { + m_log.warn("valid()- Not able to find Signature node child"); + } + } + else + { + m_log.warn("valid()- Not able to find Security node child"); + } + } + else + { + m_log.warn("valid()- Not able to find Security node"); + } + } + else + { + m_log.warn("valid()- Not able to find SOAP Header node"); + } + } + catch (Exception e) + { + m_log.warn("valid()- Exception caught, msg = " + e.getMessage()); + e.printStackTrace(); + } + + return msgVerificationStatus; + } + + /** + * Returns a secure token template document. + * + * @return Secure token template document. + */ + public static Document getSecureTokenTemplate() + { + Document tokenDoc = null; + + try + { + InputStream inStream = null; + try + { + Constants.setSignatureSpecNSprefix(""); + + // Get document from our template + inStream = new ByteArrayInputStream(m_secureTokenTemplate.getBytes()); + + DOMParser parser = new DOMParser(); + parser.setFeature("http://xml.org/sax/features/namespaces", true); + parser.parse(new InputSource(inStream)); + tokenDoc = parser.getDocument(); + } + finally + { + // Close input stream if necessary + if (inStream != null) + inStream.close(); + } + } + catch (Exception e) + { + m_log.error("getSecureTokenTemplate()- Exception caught, msg = " + e.getMessage()); + e.printStackTrace(); + } + + // Return token if successful + return tokenDoc; + } + + /** + * Secure token. + * + * @param tokenDoc Token document. + * @param timeToLive Token time to live in seconds. + * @throws Exception + */ + public void secure(Document tokenDoc, + int timeToLive) throws Exception + { + try + { + // Find all of the relevant nodes in the document + Element tokenElement = tokenDoc.getDocumentElement(); + Node soapHeaderNode = findChildNode(tokenElement, "SOAP-ENV:Header"); + Node soapBodyNode = findChildNode(tokenElement, "SOAP-ENV:Body"); + if (soapHeaderNode != null && soapBodyNode != null) + { + // We found the header of the message, now find the WS-Security node. + Node wsSecurityNode = findChildNode(soapHeaderNode, "wsse:Security"); + if (wsSecurityNode != null) + { + // We found the WS-Security node, now find the Timestamp node. + Node timeStampNode = findChildNode(wsSecurityNode, "wsu:Timestamp"); + if (timeStampNode != null) + { + // Set the timestamp + setTimeStamp(timeStampNode, timeToLive); + + // Get ready to sign the body and the timestamp elements. + XMLSignature sig; + if (m_signingKey.getAlgorithm().equalsIgnoreCase("DSA")) + { + sig = new XMLSignature(tokenDoc, "", XMLSignature.ALGO_ID_SIGNATURE_DSA, Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + } + else if (m_signingKey.getAlgorithm().equalsIgnoreCase("RSA")) + { + sig = new XMLSignature(tokenDoc, "", XMLSignature.ALGO_ID_SIGNATURE_RSA, Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + } + else + { + m_log.error("secure()- Unsupported signature algorithm - " + m_signingKey.getAlgorithm()); + throw new Exception("SecureTokenUtil.secure()- Unsupported signature algorithm - " + m_signingKey.getAlgorithm()); + } + + wsSecurityNode.insertBefore(sig.getElement(), timeStampNode); + + // Specify the transforms and the elements to be signed + Transforms transforms = new Transforms(tokenDoc); + transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); + Transforms transforms2 = new Transforms(tokenDoc); + transforms2.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); + sig.addDocument("#CASA-SOAPBODY", transforms, org.apache.xml.security.utils.Constants.ALGO_ID_DIGEST_SHA1); + sig.addDocument("#CASA-TIMESTAMP", transforms2, org.apache.xml.security.utils.Constants.ALGO_ID_DIGEST_SHA1); + + Node sigNode = sig.getElement(); + + // Add X509 stuff + XMLX509IssuerSerial x509IssuerSerial = new XMLX509IssuerSerial(tokenDoc, m_signingCert); + + X509Data x509Data = new X509Data(tokenDoc); + x509Data.add(x509IssuerSerial); + Node x509Element = x509Data.getElement(); + + Node keyInfoNode = tokenDoc.createElementNS("http://www.w3.org/2000/09/xmldsig#", "ds:KeyInfo"); + + Node secTokenRefNode = tokenDoc.createElementNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:SecurityTokenReference"); + + keyInfoNode.appendChild(secTokenRefNode); + secTokenRefNode.appendChild(x509Element); + sigNode.appendChild(keyInfoNode); + + // Perform some cleanup + setPrefixSubtree(sigNode, "ds", "http://www.w3.org/2000/09/xmldsig#"); + removeWhiteSpace(tokenElement); + + // Sign the appropriate elements + sig.sign(m_signingKey); + } + else + { + m_log.error("secure()- Missing template element"); + throw new Exception("SecureTokenUtil.secure()- Missing template element."); + } + } + else + { + m_log.error("secure()- Missing template element"); + throw new Exception("SecureTokenUtil.secure()- Missing template element."); + } + } + else + { + m_log.error("secure()- Missing template element"); + throw new Exception("SecureTokenUtil.secure()- Missing template element."); + } + } + catch (Exception e) + { + m_log.error("secure()- Exception caught, msg = " + e.getMessage()); + e.printStackTrace(); + throw e; + } + } +} diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java index 51897d6d..3decfe0e 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java @@ -26,18 +26,18 @@ package com.novell.casa.authtoksvc; import java.io.ByteArrayInputStream; -import org.apache.axis.Message; -import org.apache.axis.MessageContext; -import org.apache.axis.client.AxisClient; -import org.apache.axis.configuration.NullProvider; -import org.apache.axis.message.SOAPEnvelope; -import org.apache.axis.message.SOAPBody; -import org.apache.axis.message.MessageElement; import org.apache.log4j.Logger; +import org.apache.xml.serialize.XMLSerializer; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.security.utils.Constants; +import org.apache.xerces.parsers.DOMParser; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; -import javax.xml.namespace.QName; import java.io.*; + /** * SessionToken class. *

@@ -61,18 +61,7 @@ public final class SessionToken private String m_realm = null; private final String m_token; - static final String sessionTokenSoapMsg = - "" + - "" + - " " + - " " + - " " + - ""; - - static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider())); + static private SecureTokenUtil m_secTokenUtil = null; /** @@ -81,46 +70,79 @@ public final class SessionToken * @param id Id of the authenticated identity. * @param realm Realm where the identity id is valid. * @param lifetime Token lifetime. - * @param svcConfig Service configuration object. * @throws Exception */ public SessionToken(String id, String realm, - String lifetime, - SvcConfig svcConfig) throws Exception + String lifetime) throws Exception { - // Save copies of the input parameters + // Save some of the input parameters m_id = id; m_realm = realm; - // Create SessionTokenMessage - Message sessionTokenMessage = getMessage(realm, - id, - Integer.valueOf(lifetime).intValue(), - svcConfig); - - // Now save the message as a string - OutputStream outStream = null; - try + // Get secure token util object + SecureTokenUtil secTokenUtil = getSecureTokenUtilObj(); + if (secTokenUtil != null) { - outStream = new ByteArrayOutputStream(); - sessionTokenMessage.writeTo(outStream); - m_token = outStream.toString(); - } - finally - { - if (outStream != null) + // Obtain secure token template document + Document tokenDoc = SecureTokenUtil.getSecureTokenTemplate(); + if (tokenDoc != null) { + // Secure token template obtained, now get its top most element. + Node tokenElement = tokenDoc.getDocumentElement(); + + // Add session token payload to the token + Node soapBodyElement = SecureTokenUtil.findChildNodeNS(tokenElement, "http://www.w3.org/2003/05/soap-envelope", "Body"); + Node sessionTokenElement = tokenDoc.createElement("session_token"); + soapBodyElement.appendChild(sessionTokenElement); + Node realmElement = tokenDoc.createElement("realm"); + realmElement.setTextContent(m_realm); + sessionTokenElement.appendChild(realmElement); + Node idenIdElement = tokenDoc.createElement("ident_id"); + idenIdElement.setTextContent(m_id); + realmElement.appendChild(idenIdElement); + + // Secure the token + secTokenUtil.secure(tokenDoc, Integer.valueOf(lifetime).intValue()); + + // Now save the token as a string + OutputStream outStream = null; try { - outStream.flush(); - outStream.close(); + outStream = new ByteArrayOutputStream(); + OutputFormat format = new OutputFormat(tokenDoc); + XMLSerializer serializer = new XMLSerializer(outStream, format); + serializer.serialize(tokenDoc.getDocumentElement()); + m_token = outStream.toString(); } - catch (Exception e) + finally { - // Do nothing + if (outStream != null) + { + try + { + outStream.flush(); + outStream.close(); + } + catch (Exception e) + { + // Do nothing + } + } } } + else + { + // Failed to obtain secure token template + m_log.warn("Constructor()- Failed to obtain secure token template"); + throw new Exception("SessionToken.Constructor()- Failed to obtain secure token template"); + } + } + else + { + // Failed to obtain secure token util object + m_log.warn("Constructor()- Failed to obtain secure token util object"); + throw new Exception("SessionToken.Constructor()- Failed to obtain secure token util object"); } } @@ -140,45 +162,83 @@ public final class SessionToken // Decode the token string m_token = Base64Coder.decode(token); - // Now instantiate a SOAP message with the string + // Now instantiate token document with the token string inStream = new ByteArrayInputStream(m_token.getBytes()); - Message message = new Message(inStream); + Constants.setSignatureSpecNSprefix(""); - // Get access to the SOAP Envelope - SOAPEnvelope envelope = message.getSOAPEnvelope(); + DOMParser parser = new DOMParser(); + parser.setFeature("http://xml.org/sax/features/namespaces", true); + parser.parse(new InputSource(inStream)); + Document tokenDoc = parser.getDocument(); - // Verify the message - if (WSSecurity.verifyMessage(envelope)) + // Obtain secure token util object + SecureTokenUtil secTokenUtil = getSecureTokenUtilObj(); + if (secTokenUtil != null) { - // Message verification succeded, now obtain the realm and identity id - // from the message body. - SOAPBody body = (SOAPBody) envelope.getBody(); - QName sessionTokenElementName = new QName("session_token"); - MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName); - QName realmElementName = new QName("realm"); - MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName); - if (realmElement != null) + // Use the secure token util to validate the token + if (secTokenUtil.valid(tokenDoc)) { - m_realm = realmElement.getChildNodes().item(0).getNodeValue(); + // The session token is valid, now obtain the realm and identity id + // information from it. + Node tokenElement = tokenDoc.getDocumentElement(); + if (tokenElement != null) + { + Node soapBodyElement = SecureTokenUtil.findChildNodeNS(tokenElement, + "http://www.w3.org/2003/05/soap-envelope", + "Body"); + if (soapBodyElement != null) + { + Node sessionTokenElement = SecureTokenUtil.findChildNode(soapBodyElement, "session_token"); + if (sessionTokenElement != null) + { + Node realmElement = SecureTokenUtil.findChildNode(sessionTokenElement, "realm"); + Node identIdElement = SecureTokenUtil.findChildNode(sessionTokenElement, "ident_id"); + if (realmElement != null + && identIdElement != null) + { + m_realm = realmElement.getTextContent(); + m_id = identIdElement.getTextContent(); + } + else + { + // Missing session token element child + m_log.warn("Constructor(String)- Unable to obtain session token element child"); + throw new Exception("SessionToken.Constructor(String)- Unable to obtain session token element child"); + } + } + else + { + // Missing session token element + m_log.warn("Constructor(String)- Unable to obtain session token element"); + throw new Exception("SessionToken.Constructor(String)- Unable to obtain session token element"); + } + } + else + { + // Invalid SOAP message + m_log.warn("Constructor(String)- Unable to obtain soap body element"); + throw new Exception("SessionToken.Constructor(String)- Unable to obtain soap body element"); + } + } + else + { + // Invalid XML document + m_log.warn("Constructor(String)- Unable to obtain document element"); + throw new Exception("SessionToken.Constructor(String)- Unable to obtain document element"); + } } - QName identIdElementName = new QName("ident_id"); - MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName); - if (identIdElement != null) + else { - m_id = identIdElement.getChildNodes().item(0).getNodeValue(); - } - - if (m_realm == null || m_id == null) - { - m_log.warn("Constructor()- Required data missing from session token"); - throw new Exception("Error: Required data missing from session Token"); + // Message verification failed + m_log.warn("Constructor(String)- Invalid Session Token"); + throw new Exception("SessionToken.Constructor(String)- Invalid Session Token"); } } else { - // Message verification failed - m_log.warn("Constructor()- Invalid Session Token"); - throw new Exception("Invalid Session Token"); + // Failed to obtain secure token util object + m_log.warn("Constructor(String)- Failed to obtain secure token util object"); + throw new Exception("SessionToken.Constructor(String)- Failed to obtain secure token util object"); } } finally @@ -198,75 +258,29 @@ public final class SessionToken } /** - * Get SessionToken SOAP Message. + * Gets object to be utilized for creating and verifying secure tokens. * - * @param realm String containing the identity token that should be part of the message. - * @param identityId String containing the identity token type. - * @param lifetime Lifetime that should be specified in the message timestamp (seconds). - * @param svcConfig Service Config object. - * @return SessionToken message, null if the method fails. + * @return SecuteTokenUtil object or null if the method fails. */ - private static Message getMessage(String realm, - String identityId, - int lifetime, - SvcConfig svcConfig) + private static synchronized SecureTokenUtil getSecureTokenUtilObj() { - Message secureMessage; - InputStream inStream = null; - - try + // Instantiate the object if it has not been instantiated already + if (m_secTokenUtil == null) { - // Build SOAP Message with an identity token in the body - // - // First create a message and obtain its body - inStream = new ByteArrayInputStream(sessionTokenSoapMsg.getBytes()); - Message message = new Message(inStream); - message.setMessageContext(axisMsgContext); - SOAPBody body = (SOAPBody) message.getSOAPBody(); - - // Get access to the session_token element - QName sessionTokenElementName = new QName("session_token"); - MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName); - - // Get access to the realm element and set its value - QName realmElementName = new QName("realm"); - MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName); - realmElement.addTextNode(realm); - - // Get access to the ident_id element and set its value - QName identIdElementName = new QName("ident_id"); - MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName); - identIdElement.addTextNode(identityId); - - // Now we need to secure the SOAP message that we created, we are doing to - // do so by adding a timestamp and signing the timestamp as well as the body. - // To do this we are going to leverage WS-Security. - secureMessage = WSSecurity.secureSOAPEnvelope(message.getSOAPEnvelope(), - lifetime, - svcConfig, - false); - } - catch (Exception e) - { - m_log.error("getMessage() - Exception caught building message, error: " + e.getMessage()); - secureMessage = null; - } - finally - { - if (inStream != null) + try { - try - { - inStream.close(); - } - catch (IOException e) - { - // Do nothing - } + // Instantiate secure token object to be utilized in server type operations + m_secTokenUtil = new SecureTokenUtil(true); + } + catch (Exception e) + { + // Exception caught + m_log.warn("getSecureTokenUtilObj()- Exception caught, message = " + e.getMessage()); } } - return secureMessage; + // Return the object + return m_secTokenUtil; } /** diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/WSSecurity.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/WSSecurity.java deleted file mode 100644 index 88637492..00000000 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/WSSecurity.java +++ /dev/null @@ -1,311 +0,0 @@ -/*********************************************************************** - * - * Copyright (C) 2006 Novell, Inc. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, - * you may find current contact information at www.novell.com. - * - * Author: Juan Carlos Luciani - * - ***********************************************************************/ - -package com.novell.casa.authtoksvc; - -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import org.apache.axis.Message; -import org.apache.axis.message.SOAPEnvelope; -import org.apache.ws.security.*; -import org.apache.ws.security.components.crypto.Crypto; -import org.apache.ws.security.components.crypto.CryptoFactory; -import org.apache.ws.security.message.WSSecHeader; -import org.apache.ws.security.message.WSSecSignature; -import org.apache.ws.security.message.WSSecTimestamp; -import org.apache.xml.security.c14n.Canonicalizer; -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import javax.xml.soap.MessageFactory; -import java.util.Set; -import java.util.Vector; - - -/** - * WSSecurity Class. - *

- * This class provides static methods for securing and verifying SOAP messages. SOAP messages - * are secured by adding a timestamp and signing the appropriate elements using methods and - * headers defined by WS* specifications. - * - */ -public final class WSSecurity -{ - private static final Logger m_log = Logger.getLogger(WSSecurity.class); - - static final private WSSecurityEngine secEngine = new WSSecurityEngine(); - static final private Crypto crypto = CryptoFactory.getInstance(); - - /** - * Creates a SOAP message from a document. - * - * @param doc Message document. - * @return SOAP message. - * @throws Exception - */ - private static Message toSOAPMessage(Document doc) throws Exception - { - ByteArrayInputStream inStream = null; - Message msg = null; - - try - { - Canonicalizer c14n = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); - byte[] canonicalMessage = c14n.canonicalizeSubtree(doc); - inStream = new ByteArrayInputStream(canonicalMessage); - MessageFactory factory = MessageFactory.newInstance(); - msg = (org.apache.axis.Message) factory.createMessage(null, inStream); - } - finally - { - if (inStream != null) - { - try - { - inStream.close(); - } - catch (IOException e) - { - // Do nothing - } - } - } - - return msg; - } - - /** - * Returns the first element that containes an Id with value - * uri and namespace. - *

- * Copyright Note: The code for this function was copied from file - * WSSecurityUtil.java from package org.apache.ws.security.util. - * The Copyright notice on this file is as follows: - *

- * Copyright 2003-2006 The Apache Software Foundation, or their licensors, as - * appropriate. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @param startNode Where to start the search. - * @param value Value of the Id attribute. - * @param namespace Namespace URI of the Id. - * @return The found element or null. - */ - private static Element findElementById(Node startNode, - String value, - String namespace) - { - // Just return null if startNode is set to null - if (startNode == null) - { - return null; - } - - Node startParent = startNode.getParentNode(); - Node processedNode; - while (startNode != null) - { - // start node processing at this point - if (startNode.getNodeType() == Node.ELEMENT_NODE) - { - Element se = (Element) startNode; - if (se.hasAttributeNS(namespace, "Id") - && value.equals(se.getAttributeNS(namespace, "Id"))) - { - return se; - } - } - - processedNode = startNode; - startNode = startNode.getFirstChild(); - - // no child, this node is done. - if (startNode == null) - { - // close node processing, get sibling - startNode = processedNode.getNextSibling(); - } - - // no more siblings, get parent, all children - // of parent are processed. - while (startNode == null) - { - processedNode = processedNode.getParentNode(); - if (processedNode == startParent) - { - return null; - } - - // close parent node processing (processed node now) - startNode = processedNode.getNextSibling(); - } - } - - return null; - } - - /** - * Verifies SOAP envelope timestamp and signatures. - * - * @param envelope SOAP envelope with timestamp - * @return True if verification succeeds. - * @throws Exception - */ - public static boolean verifyMessage(SOAPEnvelope envelope) throws Exception - { - boolean msgVerificationStatus = false; - - try - { - boolean timeStampProcessed = false; - boolean signatureProcessed = false; - Vector results; - Document signedDoc = envelope.getAsDocument(); - results = secEngine.processSecurityHeader(signedDoc, null, null, crypto); - if (results != null) - { - for (WSSecurityEngineResult result : results) - { - if (result.getAction() == WSConstants.TS) - { - timeStampProcessed = true; - } - else if (result.getAction() == WSConstants.SIGN) - { - // A signature was processed, verify that the signature was over the timestamp - // and the body. - boolean timeStampSigned = false; - boolean bodySigned = false; - Set signedElements = result.getSignedElements(); - for (Object signedElement : signedElements) - { - String elementId = (String) signedElement; - Element element = findElementById(signedDoc.getDocumentElement(), elementId, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); - if (element != null) - { - if ("wsu:Timestamp".equalsIgnoreCase(element.getNodeName())) - { - timeStampSigned = true; - } - else if ("SOAP-ENV:Body".equalsIgnoreCase(element.getNodeName())) - { - bodySigned = true; - } - } - } - - if (timeStampSigned && bodySigned) - { - signatureProcessed = true; - } - } - } - } - - if (timeStampProcessed && signatureProcessed) - { - m_log.debug("verifyMessage() - Validation succeded"); - msgVerificationStatus = true; - } - else - { - m_log.warn("verifyMessage() - validation failed"); - } - } - catch (WSSecurityException e) - { - m_log.warn("verifyMessage() - Verification failed with error:" + e.getMessage() + " code = " + e.getErrorCode()); - } - - return msgVerificationStatus; - } - - /** - * Add timestamp and sign SOAP message in compliance with WS-Security. - * - * @param envelope String containing a SOAP envelope - * @param timeToLive Value to set the timestamp timeToLive parameter in seconds - * @param svcConfig Service Config object - * @param includeCert True if the message should include the Public Certificate - * @return Signed and timestamped SOAP message - * @throws Exception - */ - public static Message secureSOAPEnvelope(SOAPEnvelope envelope, - int timeToLive, - SvcConfig svcConfig, - boolean includeCert) throws Exception - { - WSSecSignature signer = new WSSecSignature(); - signer.setUserInfo(svcConfig.getSetting(SvcConfig.SigningKeyAliasName), - svcConfig.getSetting(SvcConfig.SigningKeyPassword)); - if (includeCert) - { - signer.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER); // Include X509 Cert in message - } - else - { - signer.setKeyIdentifierType(WSConstants.ISSUER_SERIAL); // Use X509 Cert Serial Number and issuer info - } - - Document doc = envelope.getAsDocument(); - - WSSecHeader secHeader = new WSSecHeader(); - secHeader.insertSecurityHeader(doc); - - WSSecTimestamp timeStamper = new WSSecTimestamp(); - timeStamper.setTimeToLive(timeToLive); - timeStamper.build(doc, secHeader); - - Vector parts = new Vector(); - - String soapNamespace = doc.getDocumentElement().getNamespaceURI(); - WSEncryptionPart bodyPart = new WSEncryptionPart("Body", soapNamespace, ""); - parts.add(bodyPart); - - WSEncryptionPart timeStampPart = new WSEncryptionPart(timeStamper.getId()); - parts.add(timeStampPart); - - signer.setParts(parts); - - Document signedDoc = signer.build(doc, crypto, secHeader); - - // Convert the signed document into a SOAP message and return it. - return toSOAPMessage(signedDoc); - } -}