From 36df2ee6b81950b8564b246fb9ee567633b2eddb Mon Sep 17 00:00:00 2001 From: oharsta Date: Tue, 21 Mar 2017 16:29:55 +0100 Subject: [PATCH] WIP for large refactoring --- NOTICE.TXT | 3 +- README.md | 43 ++ build.xml | 29 - mujina-common/pom.xml | 116 --- .../surfnet/mujina/controllers/CommonAPI.java | 87 --- .../model/AssertionConsumerServiceURL.java | 39 - .../nl/surfnet/mujina/model/Attribute.java | 38 - .../mujina/model/AuthenticationMethod.java | 51 -- .../mujina/model/CommonConfiguration.java | 47 -- .../mujina/model/CommonConfigurationImpl.java | 121 --- .../nl/surfnet/mujina/model/Credential.java | 48 -- .../nl/surfnet/mujina/model/Endpoint.java | 37 - .../nl/surfnet/mujina/model/EntityID.java | 38 - .../nl/surfnet/mujina/model/NeedsSigning.java | 39 - .../surfnet/mujina/model/ProtocolBinding.java | 39 - .../surfnet/mujina/model/SSOServiceURL.java | 39 - .../java/nl/surfnet/mujina/model/User.java | 60 -- .../mujina/saml/AuthnRequestGenerator.java | 63 -- .../saml/ConfigurableSAMLMessageHandler.java | 48 -- .../KeyStoreCredentialResolverDelegate.java | 48 -- .../mujina/saml/SAMLLogoutRequestHandler.java | 39 - .../mujina/saml/SAMLRequestHandler.java | 16 - .../surfnet/mujina/saml/SLORequestSender.java | 96 --- .../saml/SSOSuccessLogoutResponder.java | 113 --- .../mujina/saml/SecurityPolicyDelegate.java | 47 -- .../saml/SignatureSecurityPolicyRule.java | 90 --- .../surfnet/mujina/saml/SigningService.java | 71 -- .../mujina/saml/SingleSignOnService.java | 82 --- .../mujina/saml/xml/EndpointGenerator.java | 54 -- .../mujina/saml/xml/IssuerGenerator.java | 46 -- .../saml/xml/LogoutRequestGenerator.java | 48 -- .../saml/xml/LogoutResponseGenerator.java | 38 - .../mujina/saml/xml/SAML2ValidatorSuite.java | 35 - .../mujina/saml/xml/StatusGenerator.java | 73 -- .../spring/SLOLogoutSuccessHandler.java | 29 - .../nl/surfnet/mujina/util/IDService.java | 27 - .../nl/surfnet/mujina/util/TimeService.java | 27 - mujina-idp-dist/build.xml | 38 - mujina-idp-dist/pom.xml | 78 -- mujina-idp-dist/src/main/assembly/dep.xml | 65 -- .../src/main/resources/context/ROOT.xml | 18 - .../tomcat/mujina-idp-logback.xml.dev | 43 -- .../tomcat/mujina-idp-logback.xml.test | 43 -- .../tomcat/mujina-idp-logback.xml.vm | 43 -- .../tomcat/mujina-idp.properties.acc | 29 - .../tomcat/mujina-idp.properties.dev | 29 - .../tomcat/mujina-idp.properties.test | 29 - .../resources/tomcat/mujina-idp.properties.vm | 13 - mujina-idp/pom.xml | 211 ------ .../controllers/IdentityProviderAPI.java | 108 --- .../surfnet/mujina/model/AttributesMap.java | 6 - .../mujina/model/IdpConfiguration.java | 36 - .../mujina/model/IdpConfigurationImpl.java | 116 --- .../mujina/model/SimpleAuthentication.java | 107 --- .../mujina/saml/SAMLAuthnRequestHandler.java | 43 -- .../mujina/saml/SSOSuccessAuthnResponder.java | 150 ---- .../mujina/saml/xml/AssertionGenerator.java | 147 ---- .../saml/xml/AttributeStatementGenerator.java | 56 -- .../saml/xml/AuthnResponseGenerator.java | 96 --- .../saml/xml/AuthnStatementGenerator.java | 66 -- .../mujina/saml/xml/SubjectGenerator.java | 79 -- .../mujina/spring/AuthnRequestInfo.java | 54 -- .../RealAuthenticationFailureHandler.java | 123 ---- .../CustomAuthenticationProvider.java | 78 -- mujina-idp/src/main/resources/idp-crt.pem | 14 - mujina-idp/src/main/resources/idp-key.key | 15 - .../src/main/resources/idp-key.pkcs8.der | Bin 636 -> 0 bytes .../src/main/webapp/META-INF/MANIFEST.MF | 3 - .../src/main/webapp/WEB-INF/api-servlet.xml | 74 -- .../WEB-INF/applicationContext-idp-config.xml | 153 ---- .../applicationContext-property-mappings.xml | 27 - .../applicationContext-spring-security.xml | 87 --- mujina-idp/src/main/webapp/WEB-INF/web.xml | 98 --- mujina-idp/src/main/webapp/admin.jsp | 64 -- .../src/main/webapp/available_attributes.json | 86 --- mujina-idp/src/main/webapp/edit_attr.jsp | 127 ---- mujina-idp/src/main/webapp/index.jsp | 62 -- .../src/main/webapp/js/jquery-2.0.3.min.js | 6 - .../src/main/webapp/js/jquery.cookie.js | 90 --- mujina-idp/src/main/webapp/login.jsp | 66 -- mujina-idp/src/main/webapp/user.jsp | 63 -- .../controllers/tests/IdpRestAPITest.java | 211 ------ .../mujina/controllers/tests/TestHelper.java | 149 ---- mujina-idp/src/test/resources/logback.xml | 41 -- .../src/test/resources/mujina-idp.properties | 29 - mujina-idp/src/test/resources/test-beans.xml | 29 - mujina-sp-dist/build.xml | 38 - mujina-sp-dist/pom.xml | 81 -- mujina-sp-dist/src/main/assembly/dep.xml | 65 -- .../src/main/resources/context/ROOT.xml | 18 - .../tomcat/mujina-sp-logback.xml.dev | 44 -- .../tomcat/mujina-sp-logback.xml.test | 44 -- .../resources/tomcat/mujina-sp-logback.xml.vm | 44 -- .../resources/tomcat/mujina-sp.properties.acc | 35 - .../resources/tomcat/mujina-sp.properties.dev | 35 - .../tomcat/mujina-sp.properties.test | 35 - .../resources/tomcat/mujina-sp.properties.vm | 16 - mujina-sp/pom.xml | 173 ----- .../controllers/ServiceProviderAPI.java | 71 -- .../surfnet/mujina/model/SpConfiguration.java | 33 - .../mujina/model/SpConfigurationImpl.java | 88 --- .../mujina/saml/AssertionConsumer.java | 28 - .../mujina/saml/RealAssertionConsumer.java | 173 ----- ...entityProviderAuthenticationException.java | 34 - .../RealAuthenticationFailureHandler.java | 61 -- .../spring/SAMLAuthenticationEntryPoint.java | 149 ---- .../spring/SAMLAuthenticationToken.java | 89 --- ...esponseAuthenticationProcessingFilter.java | 86 --- .../SAMLResponseAuthenticationProvider.java | 61 -- ...erviceProviderAuthenticationException.java | 32 - .../java/nl/surfnet/mujina/spring/User.java | 166 ----- mujina-sp/src/main/resources/idp-crt.pem | 14 - mujina-sp/src/main/resources/idp-key.key | 15 - .../src/main/resources/idp-key.pkcs8.der | Bin 636 -> 0 bytes .../src/main/resources/multiple-persons.json | 689 ------------------ .../src/main/webapp/META-INF/MANIFEST.MF | 3 - .../src/main/webapp/WEB-INF/api-servlet.xml | 74 -- .../applicationContext-property-mappings.xml | 27 - .../WEB-INF/applicationContext-sp-config.xml | 148 ---- .../applicationContext-spring-security.xml | 99 --- mujina-sp/src/main/webapp/WEB-INF/web.xml | 93 --- mujina-sp/src/main/webapp/admin.jsp | 60 -- mujina-sp/src/main/webapp/favicon.ico | Bin 1150 -> 0 bytes mujina-sp/src/main/webapp/index.jsp | 86 --- mujina-sp/src/main/webapp/user.jsp | 88 --- .../controllers/tests/SpRestAPITest.java | 48 -- mujina-sp/src/test/resources/logback.xml | 29 - .../src/test/resources/mujina-sp.properties | 34 - pom.xml | 349 ++++----- src/main/java/mujina/MujinaApplication.java | 18 + .../java/mujina/api/SharedConfiguration.java | 75 ++ .../java/mujina/api/SharedController.java | 51 ++ .../mujina/api/idp/AuthenticationMethod.java | 5 + src/main/java/mujina/api/idp/Credential.java | 19 + .../java/mujina/api/idp/IdpConfiguration.java | 74 ++ .../java/mujina/api/idp/IdpController.java | 81 ++ src/main/java/mujina/api/idp/User.java | 18 + .../java/mujina/api/sp/SpConfiguration.java | 48 ++ src/main/java/mujina/api/sp/SpController.java | 43 ++ .../idp/AuthenticationSuccessHandler.java | 40 + .../idp/IdentityProviderAuthnFilter.java | 104 +++ .../mujina/idp/IdpAuthenticationProvider.java | 42 ++ .../mujina/idp/IdpMetadataController.java | 111 +++ .../java/mujina/idp/IdpUserController.java | 17 + .../mujina/idp/IdpWebSecurityConfigurer.java | 57 ++ .../saml/DefaultSAMLUserDetailsService.java | 33 + .../java/mujina/saml/KeyStoreLocator.java | 66 ++ ...eterDecodingHttpServletRequestWrapper.java | 25 + .../saml/ProxiedSAMLContextProviderLB.java | 31 + .../mujina/saml/ResourceMetadataProvider.java | 27 + .../saml/RoleSAMLAuthenticationProvider.java | 16 + src/main/java/mujina/saml/SAMLAttribute.java | 34 + .../java/mujina/saml/SAMLAuthentication.java | 25 + src/main/java/mujina/saml/SAMLBuilder.java | 201 +++++ .../java/mujina/saml/SAMLMessageHandler.java | 187 +++++ src/main/java/mujina/saml/SAMLPrincipal.java | 43 ++ .../sp/DefaultMetadataDisplayFilter.java | 25 + src/main/java/mujina/sp/SAMLConfig.java | 137 ++++ src/main/java/mujina/sp/SpUserController.java | 17 + .../mujina/sp/SpWebSecurityConfigurer.java | 293 ++++++++ src/main/resources/application.yml | 74 ++ src/main/resources/logback.xml | 15 + src/main/resources/saml/eb.idp.metadata.xml | 73 ++ src/main/resources/templates/login.html | 17 + src/main/resources/templates/test.html | 9 + src/main/resources/templates/user.html | 20 + 166 files changed, 2339 insertions(+), 8749 deletions(-) delete mode 100644 build.xml delete mode 100644 mujina-common/pom.xml delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/controllers/CommonAPI.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/AssertionConsumerServiceURL.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/Attribute.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/AuthenticationMethod.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfiguration.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfigurationImpl.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/Credential.java delete mode 100755 mujina-common/src/main/java/nl/surfnet/mujina/model/Endpoint.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/EntityID.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/NeedsSigning.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/ProtocolBinding.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/SSOServiceURL.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/model/User.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/AuthnRequestGenerator.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/ConfigurableSAMLMessageHandler.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/KeyStoreCredentialResolverDelegate.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLLogoutRequestHandler.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLRequestHandler.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/SLORequestSender.java delete mode 100755 mujina-common/src/main/java/nl/surfnet/mujina/saml/SSOSuccessLogoutResponder.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/SecurityPolicyDelegate.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/SignatureSecurityPolicyRule.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/SigningService.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/SingleSignOnService.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/EndpointGenerator.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/IssuerGenerator.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutRequestGenerator.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutResponseGenerator.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/SAML2ValidatorSuite.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/StatusGenerator.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/spring/SLOLogoutSuccessHandler.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/util/IDService.java delete mode 100644 mujina-common/src/main/java/nl/surfnet/mujina/util/TimeService.java delete mode 100644 mujina-idp-dist/build.xml delete mode 100644 mujina-idp-dist/pom.xml delete mode 100644 mujina-idp-dist/src/main/assembly/dep.xml delete mode 100644 mujina-idp-dist/src/main/resources/context/ROOT.xml delete mode 100644 mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.dev delete mode 100644 mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.test delete mode 100644 mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.vm delete mode 100644 mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.acc delete mode 100644 mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.dev delete mode 100644 mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.test delete mode 100644 mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.vm delete mode 100644 mujina-idp/pom.xml delete mode 100755 mujina-idp/src/main/java/nl/surfnet/mujina/controllers/IdentityProviderAPI.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/model/AttributesMap.java delete mode 100755 mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfiguration.java delete mode 100755 mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfigurationImpl.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/model/SimpleAuthentication.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/saml/SAMLAuthnRequestHandler.java delete mode 100755 mujina-idp/src/main/java/nl/surfnet/mujina/saml/SSOSuccessAuthnResponder.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AssertionGenerator.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AttributeStatementGenerator.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnResponseGenerator.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnStatementGenerator.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/SubjectGenerator.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/spring/AuthnRequestInfo.java delete mode 100755 mujina-idp/src/main/java/nl/surfnet/mujina/spring/RealAuthenticationFailureHandler.java delete mode 100644 mujina-idp/src/main/java/nl/surfnet/mujina/spring/security/CustomAuthenticationProvider.java delete mode 100644 mujina-idp/src/main/resources/idp-crt.pem delete mode 100644 mujina-idp/src/main/resources/idp-key.key delete mode 100644 mujina-idp/src/main/resources/idp-key.pkcs8.der delete mode 100644 mujina-idp/src/main/webapp/META-INF/MANIFEST.MF delete mode 100644 mujina-idp/src/main/webapp/WEB-INF/api-servlet.xml delete mode 100644 mujina-idp/src/main/webapp/WEB-INF/applicationContext-idp-config.xml delete mode 100644 mujina-idp/src/main/webapp/WEB-INF/applicationContext-property-mappings.xml delete mode 100644 mujina-idp/src/main/webapp/WEB-INF/applicationContext-spring-security.xml delete mode 100644 mujina-idp/src/main/webapp/WEB-INF/web.xml delete mode 100644 mujina-idp/src/main/webapp/admin.jsp delete mode 100644 mujina-idp/src/main/webapp/available_attributes.json delete mode 100644 mujina-idp/src/main/webapp/edit_attr.jsp delete mode 100644 mujina-idp/src/main/webapp/index.jsp delete mode 100644 mujina-idp/src/main/webapp/js/jquery-2.0.3.min.js delete mode 100755 mujina-idp/src/main/webapp/js/jquery.cookie.js delete mode 100644 mujina-idp/src/main/webapp/login.jsp delete mode 100644 mujina-idp/src/main/webapp/user.jsp delete mode 100755 mujina-idp/src/test/java/nl/surfnet/mujina/controllers/tests/IdpRestAPITest.java delete mode 100644 mujina-idp/src/test/java/nl/surfnet/mujina/controllers/tests/TestHelper.java delete mode 100644 mujina-idp/src/test/resources/logback.xml delete mode 100644 mujina-idp/src/test/resources/mujina-idp.properties delete mode 100644 mujina-idp/src/test/resources/test-beans.xml delete mode 100644 mujina-sp-dist/build.xml delete mode 100644 mujina-sp-dist/pom.xml delete mode 100644 mujina-sp-dist/src/main/assembly/dep.xml delete mode 100644 mujina-sp-dist/src/main/resources/context/ROOT.xml delete mode 100644 mujina-sp-dist/src/main/resources/tomcat/mujina-sp-logback.xml.dev delete mode 100644 mujina-sp-dist/src/main/resources/tomcat/mujina-sp-logback.xml.test delete mode 100644 mujina-sp-dist/src/main/resources/tomcat/mujina-sp-logback.xml.vm delete mode 100644 mujina-sp-dist/src/main/resources/tomcat/mujina-sp.properties.acc delete mode 100644 mujina-sp-dist/src/main/resources/tomcat/mujina-sp.properties.dev delete mode 100644 mujina-sp-dist/src/main/resources/tomcat/mujina-sp.properties.test delete mode 100644 mujina-sp-dist/src/main/resources/tomcat/mujina-sp.properties.vm delete mode 100644 mujina-sp/pom.xml delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/controllers/ServiceProviderAPI.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/model/SpConfiguration.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/model/SpConfigurationImpl.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/saml/AssertionConsumer.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/saml/RealAssertionConsumer.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/IdentityProviderAuthenticationException.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/RealAuthenticationFailureHandler.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/SAMLAuthenticationEntryPoint.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/SAMLAuthenticationToken.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/SAMLResponseAuthenticationProcessingFilter.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/SAMLResponseAuthenticationProvider.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/ServiceProviderAuthenticationException.java delete mode 100644 mujina-sp/src/main/java/nl/surfnet/mujina/spring/User.java delete mode 100644 mujina-sp/src/main/resources/idp-crt.pem delete mode 100644 mujina-sp/src/main/resources/idp-key.key delete mode 100644 mujina-sp/src/main/resources/idp-key.pkcs8.der delete mode 100644 mujina-sp/src/main/resources/multiple-persons.json delete mode 100644 mujina-sp/src/main/webapp/META-INF/MANIFEST.MF delete mode 100644 mujina-sp/src/main/webapp/WEB-INF/api-servlet.xml delete mode 100644 mujina-sp/src/main/webapp/WEB-INF/applicationContext-property-mappings.xml delete mode 100644 mujina-sp/src/main/webapp/WEB-INF/applicationContext-sp-config.xml delete mode 100644 mujina-sp/src/main/webapp/WEB-INF/applicationContext-spring-security.xml delete mode 100644 mujina-sp/src/main/webapp/WEB-INF/web.xml delete mode 100644 mujina-sp/src/main/webapp/admin.jsp delete mode 100644 mujina-sp/src/main/webapp/favicon.ico delete mode 100644 mujina-sp/src/main/webapp/index.jsp delete mode 100644 mujina-sp/src/main/webapp/user.jsp delete mode 100644 mujina-sp/src/test/java/nl/surfnet/mujina/controllers/tests/SpRestAPITest.java delete mode 100644 mujina-sp/src/test/resources/logback.xml delete mode 100644 mujina-sp/src/test/resources/mujina-sp.properties create mode 100644 src/main/java/mujina/MujinaApplication.java create mode 100644 src/main/java/mujina/api/SharedConfiguration.java create mode 100644 src/main/java/mujina/api/SharedController.java create mode 100644 src/main/java/mujina/api/idp/AuthenticationMethod.java create mode 100644 src/main/java/mujina/api/idp/Credential.java create mode 100755 src/main/java/mujina/api/idp/IdpConfiguration.java create mode 100644 src/main/java/mujina/api/idp/IdpController.java create mode 100644 src/main/java/mujina/api/idp/User.java create mode 100644 src/main/java/mujina/api/sp/SpConfiguration.java create mode 100644 src/main/java/mujina/api/sp/SpController.java create mode 100644 src/main/java/mujina/idp/AuthenticationSuccessHandler.java create mode 100644 src/main/java/mujina/idp/IdentityProviderAuthnFilter.java create mode 100644 src/main/java/mujina/idp/IdpAuthenticationProvider.java create mode 100644 src/main/java/mujina/idp/IdpMetadataController.java create mode 100644 src/main/java/mujina/idp/IdpUserController.java create mode 100644 src/main/java/mujina/idp/IdpWebSecurityConfigurer.java create mode 100755 src/main/java/mujina/saml/DefaultSAMLUserDetailsService.java create mode 100644 src/main/java/mujina/saml/KeyStoreLocator.java create mode 100644 src/main/java/mujina/saml/ParameterDecodingHttpServletRequestWrapper.java create mode 100644 src/main/java/mujina/saml/ProxiedSAMLContextProviderLB.java create mode 100644 src/main/java/mujina/saml/ResourceMetadataProvider.java create mode 100644 src/main/java/mujina/saml/RoleSAMLAuthenticationProvider.java create mode 100644 src/main/java/mujina/saml/SAMLAttribute.java create mode 100644 src/main/java/mujina/saml/SAMLAuthentication.java create mode 100644 src/main/java/mujina/saml/SAMLBuilder.java create mode 100644 src/main/java/mujina/saml/SAMLMessageHandler.java create mode 100644 src/main/java/mujina/saml/SAMLPrincipal.java create mode 100644 src/main/java/mujina/sp/DefaultMetadataDisplayFilter.java create mode 100644 src/main/java/mujina/sp/SAMLConfig.java create mode 100644 src/main/java/mujina/sp/SpUserController.java create mode 100755 src/main/java/mujina/sp/SpWebSecurityConfigurer.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/logback.xml create mode 100644 src/main/resources/saml/eb.idp.metadata.xml create mode 100644 src/main/resources/templates/login.html create mode 100644 src/main/resources/templates/test.html create mode 100644 src/main/resources/templates/user.html diff --git a/NOTICE.TXT b/NOTICE.TXT index 662f6ad1..9e331bd9 100644 --- a/NOTICE.TXT +++ b/NOTICE.TXT @@ -13,5 +13,4 @@ redistribution or general licensing terms than those stated in the Apache License. Users and redistributors are hereby requested to verify these conditions and agree upon them. -This project is based on spring saml recipe from Jim Cox. You can find his -excellent project here: http://sourceforge.net/projects/spring-saml/ \ No newline at end of file +This project is based on spring saml. diff --git a/README.md b/README.md index 3355ab1e..1e50a46f 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,49 @@ Changing port numbers Both the SP and IDP can be made to bind to a different tcp/ip port: `mvn jetty:run -DhttpPort=8082 -DhttpsPort=8444` +## [Private signing key and public certificate](#signing-keys) + +The SAML Spring Security library needs a private DSA key / public certificate pair for the IdP / SP which can be re-generated +if you want to use new key pairs. + +```bash +openssl req -subj '/O=Organization, CN=Mujina/' -newkey rsa:2048 -new -x509 -days 3652 -nodes -out mujina.crt -keyout mujina.pem +``` + +The Java KeyStore expects a pkcs8 DER format for RSA private keys so we have to re-format that key: + +```bash +openssl pkcs8 -nocrypt -in mujina.pem -topk8 -out mujina.der +``` + +Remove the whitespace, heading and footer from the mujina.crt and mujina.der: + +```bash +cat mujina.der |head -n -1 |tail -n +2 | tr -d '\n'; echo +cat mujina.crt |head -n -1 |tail -n +2 | tr -d '\n'; echo +``` + +Above commands work on linux distributions. On mac you can issue the same command with `ghead` after you install `coreutils`: + +```bash +brew install coreutils + +cat mujina.der |ghead -n -1 |tail -n +2 | tr -d '\n'; echo +cat mujina.crt |ghead -n -1 |tail -n +2 | tr -d '\n'; echo +``` + +Add the mujina key pair to the application.yml file: + +```yml +idp: + private_key: ${output from cleaning the der file} + certificate: ${output from cleaning the crt file} + +sp: + private_key: ${output from cleaning the der file} + certificate: ${output from cleaning the crt file} +``` + Resetting the IDP ----------------- diff --git a/build.xml b/build.xml deleted file mode 100644 index d30f13e8..00000000 --- a/build.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - Root build file to trigger both idp and sp - - - - - - - - - - - \ No newline at end of file diff --git a/mujina-common/pom.xml b/mujina-common/pom.xml deleted file mode 100644 index f5517c5d..00000000 --- a/mujina-common/pom.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - org.surfnet.coin - mujina - 4.1.3 - ../pom.xml - - - 4.0.0 - mujina-common - - - - - commons-io - commons-io - - - - commons-codec - commons-codec - ${commons-codec.version} - - - - org.springframework - spring-webmvc - - - - org.springframework - spring-test - - - - xml-apis - xml-apis - - - - javax.servlet - servlet-api - provided - - - - junit - junit - - - - org.mockito - mockito-all - - - - xmlunit - xmlunit - - - - org.slf4j - slf4j-api - - - - org.springframework.security - spring-security-core - - - org.surfnet.coin - spring-security-opensaml - - - - - - - - src/test/resources/ - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.3.1 - - - - test-jar - - - - - - - - diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/controllers/CommonAPI.java b/mujina-common/src/main/java/nl/surfnet/mujina/controllers/CommonAPI.java deleted file mode 100644 index 3fa920e9..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/controllers/CommonAPI.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.controllers; - -import nl.surfnet.mujina.model.CommonConfiguration; -import nl.surfnet.mujina.model.Credential; -import nl.surfnet.mujina.model.Endpoint; -import nl.surfnet.mujina.model.EntityID; -import nl.surfnet.mujina.model.NeedsSigning; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; - -@Controller -public class CommonAPI { - - private final static Logger log = LoggerFactory.getLogger(CommonAPI.class); - - private CommonConfiguration configuration; - - @Autowired - public CommonAPI(final CommonConfiguration configuration) { - this.configuration = configuration; - } - - @RequestMapping(value = {"/reset"}, method = RequestMethod.POST) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void reset() { - log.debug("Resetting to default configuration"); - configuration.reset(); - } - - @RequestMapping(value = {"/entityid"}, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setEntityID(@RequestBody EntityID entityID) { - log.debug("Request to set entityID {}", entityID.getValue()); - configuration.setEntityID(entityID.getValue()); - } - - @RequestMapping(value = {"/signing-credential"}, method = RequestMethod.POST) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setSigningCredential(@RequestBody Credential credential) { - log.debug("Request to set signing credential"); - configuration.injectCredential(credential.getCertificate(), credential.getKey()); - } - - @RequestMapping(value = {"/needs-signing"}, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setSigningNeeded(@RequestBody NeedsSigning needsSigning) { - log.debug("Request to set signing needed"); - configuration.setSigning(needsSigning.getValue()); - } - - @RequestMapping(value = {"/sloendpoint"}, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setSloEndpoint(@RequestBody Endpoint sloEndpoint) { - log.debug("Request to set SLO Service Endpoint to {}", sloEndpoint.getUrl()); - configuration.setSLOEndpoint(sloEndpoint); - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/AssertionConsumerServiceURL.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/AssertionConsumerServiceURL.java deleted file mode 100644 index 1ffe873a..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/AssertionConsumerServiceURL.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class AssertionConsumerServiceURL implements Serializable { - private static final long serialVersionUID = 1L; - - private String value; - - public String getValue() { - return value; - } - - @XmlElement - public void setValue(final String value) { - this.value = value; - } - -} \ No newline at end of file diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/Attribute.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/Attribute.java deleted file mode 100644 index 7754ccac..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/Attribute.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.List; - -@XmlRootElement -public class Attribute implements Serializable { - private static final long serialVersionUID = 1L; - - private List value; - - public List getValue() { - return value; - } - - @XmlElement - public void setValue(final List value) { - this.value = value; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/AuthenticationMethod.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/AuthenticationMethod.java deleted file mode 100644 index 5f414734..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/AuthenticationMethod.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@SuppressWarnings("serial") -@XmlRootElement -public class AuthenticationMethod implements Serializable { - - private String value; - - public AuthenticationMethod() { - super(); - } - - public AuthenticationMethod(String value) { - super(); - this.value = value; - } - - public String getValue() { - return value; - } - - @XmlElement - public void setValue(final String value) { - this.value = value; - } - - public enum Method { - USER, ALL - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfiguration.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfiguration.java deleted file mode 100644 index abc8b94d..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfiguration.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.security.KeyStore; -import java.util.Map; - -public interface CommonConfiguration { - - void reset(); - - KeyStore getKeyStore(); - - String getEntityID(); - - void setEntityID(String value); - - void injectCredential(String certificate, String key); - - Map getPrivateKeyPasswords(); - - boolean needsSigning(); - - void setSigning(boolean needsSigning); - - void setSignatureAlgorithm(String signatureAlgorithm); - - String getSignatureAlgorithm(); - - void setSLOEndpoint(Endpoint sloEndpoint); - - Endpoint getSLOEndpoint(); -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfigurationImpl.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfigurationImpl.java deleted file mode 100644 index 0e657cf1..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/CommonConfigurationImpl.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.ByteArrayInputStream; -import java.security.KeyStore; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.codec.binary.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import nl.surfnet.spring.security.opensaml.util.KeyStoreUtil; - -public abstract class CommonConfigurationImpl implements CommonConfiguration { - - private final static Logger LOGGER = LoggerFactory.getLogger(CommonConfigurationImpl.class); - - protected KeyStore keyStore; - protected String keystorePassword = "secret"; - private boolean needsSigning=false; - private String signatureAlgorithm; - private Endpoint sloEndpoint; - protected String entityId; - - protected Map privateKeyPasswords = new HashMap(); - - @Override - public Map getPrivateKeyPasswords() { - return privateKeyPasswords; - } - - @Override - public KeyStore getKeyStore() { - return keyStore; - } - - public boolean needsSigning() { - return needsSigning; - } - - public void setSigning(boolean needsSigning) { - this.needsSigning = needsSigning; - } - - @Override - public String getEntityID() { - return entityId; - } - - @Override - public void setEntityID(final String newEntityId) { - try { - final KeyStore.PasswordProtection passwordProtection = new KeyStore.PasswordProtection(keystorePassword.toCharArray()); - final KeyStore.Entry keyStoreEntry = keyStore.getEntry(this.entityId, passwordProtection); - keyStore.setEntry(newEntityId, keyStoreEntry, passwordProtection); - privateKeyPasswords.put(newEntityId, keystorePassword); - } catch (Exception e) { - LOGGER.warn("Unable to update signing key in key store", e); - } - this.entityId = newEntityId; - } - - @Override - public void injectCredential(final String certificate, final String key) { - try { - if (keyStore.containsAlias(entityId)) { - keyStore.deleteEntry(entityId); - } - injectKeyStore(entityId, certificate, key); - } catch (Exception e) { - throw new RuntimeException("Unable to append signing credential", e); - } - } - - private void injectKeyStore(String alias, String pemCert, String pemKey) throws Exception { - String wrappedCert = "-----BEGIN CERTIFICATE-----\n" + pemCert + "\n-----END CERTIFICATE-----"; - - ByteArrayInputStream certificateInputStream = new ByteArrayInputStream(wrappedCert.getBytes()); - - byte[] key = Base64.decodeBase64(pemKey); - KeyStoreUtil.appendKeyToKeyStore(keyStore, alias, certificateInputStream, new ByteArrayInputStream(key), keystorePassword.toCharArray()); - - } - - @Override - public void setSignatureAlgorithm(String signatureAlgorithm) { - this.signatureAlgorithm = signatureAlgorithm; - } - - @Override - public String getSignatureAlgorithm() { - return this.signatureAlgorithm; - } - - @Override - public void setSLOEndpoint(Endpoint sloEndpoint) { - this.sloEndpoint = sloEndpoint; - } - - @Override - public Endpoint getSLOEndpoint() { - return sloEndpoint; - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/Credential.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/Credential.java deleted file mode 100644 index dd45c7dc..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/Credential.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class Credential implements Serializable { - private static final long serialVersionUID = 1L; - - private String certificate; - private String key; - - public String getCertificate() { - return certificate; - } - - @XmlElement - public void setCertificate(final String certificate) { - this.certificate = certificate; - } - - public String getKey() { - return key; - } - - @XmlElement - public void setKey(final String key) { - this.key = key; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/Endpoint.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/Endpoint.java deleted file mode 100755 index 9acff6b9..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/Endpoint.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; - -@XmlRootElement -public class Endpoint implements Serializable { - private static final long serialVersionUID = 1L; - - private String url; - - public String getUrl() { - return url; - } - - @XmlElement - public void setUrl(final String url) { - this.url = url; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/EntityID.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/EntityID.java deleted file mode 100644 index 935dd043..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/EntityID.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class EntityID implements Serializable { - private static final long serialVersionUID = 1L; - - private String value; - - public String getValue() { - return value; - } - - @XmlElement - public void setValue(final String value) { - this.value = value; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/NeedsSigning.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/NeedsSigning.java deleted file mode 100644 index 675c32d0..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/NeedsSigning.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class NeedsSigning implements Serializable { - private static final long serialVersionUID = 1L; - - private boolean value; - - public boolean getValue() { - return value; - } - - @XmlElement - public void setValue(final boolean value) { - this.value = value; - } - -} \ No newline at end of file diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/ProtocolBinding.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/ProtocolBinding.java deleted file mode 100644 index 9b0c6b55..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/ProtocolBinding.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class ProtocolBinding implements Serializable { - private static final long serialVersionUID = 1L; - - private String value; - - public String getValue() { - return value; - } - - @XmlElement - public void setValue(final String value) { - this.value = value; - } - -} \ No newline at end of file diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/SSOServiceURL.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/SSOServiceURL.java deleted file mode 100644 index e6edda5c..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/SSOServiceURL.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class SSOServiceURL implements Serializable { - private static final long serialVersionUID = 1L; - - private String value; - - public String getValue() { - return value; - } - - @XmlElement - public void setValue(final String value) { - this.value = value; - } - -} \ No newline at end of file diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/model/User.java b/mujina-common/src/main/java/nl/surfnet/mujina/model/User.java deleted file mode 100644 index 08129df9..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/model/User.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.io.Serializable; -import java.util.List; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement -public class User implements Serializable { - - private static final long serialVersionUID = 1L; - - private String name; - private String password; - private List authorities; - - public String getName() { - return name; - } - - @XmlElement - public void setName(final String name) { - this.name = name; - } - - public String getPassword() { - return password; - } - - @XmlElement - public void setPassword(final String password) { - this.password = password; - } - - public List getAuthorities() { - return authorities; - } - - @XmlElement - public void setAuthorities(final List authorities) { - this.authorities = authorities; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/AuthnRequestGenerator.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/AuthnRequestGenerator.java deleted file mode 100644 index 65a264c1..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/AuthnRequestGenerator.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml; - -import nl.surfnet.mujina.saml.xml.IssuerGenerator; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; - -import org.opensaml.Configuration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.impl.AuthnRequestBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.springframework.util.StringUtils; - -public class AuthnRequestGenerator { - - private XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - - private final TimeService timeService; - private final IDService idService; - private IssuerGenerator issuerGenerator; - - public AuthnRequestGenerator(String issuingEntityName, TimeService timeService, IDService idService) { - super(); - this.timeService = timeService; - this.idService = idService; - - issuerGenerator = new IssuerGenerator(issuingEntityName); - } - - public AuthnRequest generateAuthnRequest(String destination, String responseLocation, String protocolBinding) { - AuthnRequestBuilder authnRequestBuilder = (AuthnRequestBuilder) builderFactory.getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME); - - AuthnRequest authnRequest = authnRequestBuilder.buildObject(); - if (StringUtils.hasText(responseLocation)) { - authnRequest.setAssertionConsumerServiceURL(responseLocation); - } - authnRequest.setID(idService.generateID()); - authnRequest.setIssueInstant(timeService.getCurrentDateTime()); - authnRequest.setDestination(destination); - if (StringUtils.hasText(protocolBinding)) { - authnRequest.setProtocolBinding(protocolBinding); - } - authnRequest.setIssuer(issuerGenerator.generateIssuer()); - - return authnRequest; - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/ConfigurableSAMLMessageHandler.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/ConfigurableSAMLMessageHandler.java deleted file mode 100644 index 4e786f87..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/ConfigurableSAMLMessageHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright 2012 SURFnet bv, The Netherlands - - 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. - */ - -package nl.surfnet.mujina.saml; - -import org.opensaml.common.binding.decoding.SAMLMessageDecoder; -import org.opensaml.ws.security.SecurityPolicyResolver; - -import nl.surfnet.mujina.model.CommonConfiguration; -import nl.surfnet.spring.security.opensaml.SAMLMessageHandlerImpl; - -/** - * Variant of SAMLMessageHandlerImpl that uses Mujina configuration for entity id and whether to sign. - */ -public class ConfigurableSAMLMessageHandler extends SAMLMessageHandlerImpl { - private CommonConfiguration configuration; - - public void setConfiguration(CommonConfiguration configuration) { - this.configuration = configuration; - } - - public ConfigurableSAMLMessageHandler(SAMLMessageDecoder decoder, SecurityPolicyResolver resolver) { - super(decoder, resolver); - } - - @Override - public String getEntityId() { - return configuration.getEntityID(); - } - - @Override - public boolean isNeedsSigning() { - return configuration.needsSigning(); - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/KeyStoreCredentialResolverDelegate.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/KeyStoreCredentialResolverDelegate.java deleted file mode 100644 index b9fc7b80..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/KeyStoreCredentialResolverDelegate.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml; - -import nl.surfnet.mujina.model.CommonConfiguration; - -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.CredentialResolver; -import org.opensaml.xml.security.credential.KeyStoreCredentialResolver; - -public class KeyStoreCredentialResolverDelegate implements CredentialResolver { - - private CommonConfiguration configuration; - - @Override - public Iterable resolve(CriteriaSet criteriaSet) throws SecurityException { - return getKeyStoreCredentialResolver().resolve(criteriaSet); - } - - @Override - public Credential resolveSingle(CriteriaSet criteriaSet) throws SecurityException { - return getKeyStoreCredentialResolver().resolveSingle(criteriaSet); - } - - public KeyStoreCredentialResolver getKeyStoreCredentialResolver() { - return new KeyStoreCredentialResolver(configuration.getKeyStore(), configuration.getPrivateKeyPasswords()); - } - - public void setConfiguration(final CommonConfiguration configuration) { - this.configuration = configuration; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLLogoutRequestHandler.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLLogoutRequestHandler.java deleted file mode 100644 index 6ea0af8e..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLLogoutRequestHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -package nl.surfnet.mujina.saml; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; - -import org.opensaml.saml2.core.LogoutRequest; -import org.springframework.security.core.session.SessionInformation; -import org.springframework.security.core.session.SessionRegistry; - -public class SAMLLogoutRequestHandler implements SAMLRequestHandler { - - private final String sloResponderURI; - private final SessionRegistry sessionRegistry; - - public SAMLLogoutRequestHandler(String sloResponderURI, SessionRegistry sessionRegistry) { - this.sloResponderURI = sloResponderURI; - this.sessionRegistry = sessionRegistry; - } - - @Override - public void handleSAMLRequest(HttpServletRequest request, HttpServletResponse response, LogoutRequest logoutRequest) - throws ServletException, IOException { - final List sessions = sessionRegistry.getAllSessions(logoutRequest.getNameID().getValue(), false); - - for (SessionInformation sessionInformation : sessions) { - sessionInformation.expireNow(); - } - - request.getRequestDispatcher(sloResponderURI).forward(request, response); - } - - @Override - public String getTypeLocalName() { - return LogoutRequest.DEFAULT_ELEMENT_LOCAL_NAME; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLRequestHandler.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLRequestHandler.java deleted file mode 100644 index 89b18dcf..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SAMLRequestHandler.java +++ /dev/null @@ -1,16 +0,0 @@ -package nl.surfnet.mujina.saml; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.io.IOException; - -import org.opensaml.saml2.core.RequestAbstractType; - -public interface SAMLRequestHandler { - void handleSAMLRequest(HttpServletRequest request, HttpServletResponse response, T samlRequest) - throws ServletException, IOException; - - String getTypeLocalName(); -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SLORequestSender.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SLORequestSender.java deleted file mode 100644 index 7d9a79dc..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SLORequestSender.java +++ /dev/null @@ -1,96 +0,0 @@ -package nl.surfnet.mujina.saml; - -import java.io.IOException; - -import nl.surfnet.mujina.model.CommonConfiguration; -import nl.surfnet.mujina.model.Endpoint; -import nl.surfnet.mujina.saml.xml.LogoutRequestGenerator; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.params.HttpConnectionManagerParams; -import org.apache.commons.httpclient.params.HttpParams; -import org.apache.xml.security.utils.Base64; -import org.opensaml.saml2.core.LogoutRequest; -import org.opensaml.ws.soap.client.http.HttpClientBuilder; -import org.opensaml.xml.Configuration; -import org.opensaml.xml.io.Marshaller; -import org.opensaml.xml.io.MarshallerFactory; -import org.opensaml.xml.io.MarshallingException; -import org.opensaml.xml.util.XMLHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -public class SLORequestSender { - private final static Logger logger = LoggerFactory.getLogger(SLORequestSender.class); - - private final CommonConfiguration configuration; - private final TimeService timeService; - private final IDService idService; - - private final HttpClient httpClient; - private final SigningService signingService; - - @Autowired - public SLORequestSender(CommonConfiguration configuration, TimeService timeService, IDService idService, - SigningService signingService) { - - this.configuration = configuration; - this.timeService = timeService; - this.idService = idService; - this.signingService = signingService; - - HttpClientBuilder clientBuilder = new HttpClientBuilder(); - - clientBuilder.setConnectionRetryAttempts(3); - clientBuilder.setConnectionTimeout(2000); - clientBuilder.setMaxConnectionsPerHost(10); - clientBuilder.setMaxTotalConnections(20); - this.httpClient = clientBuilder.buildClient(); - HttpParams httpParams = httpClient.getParams(); - httpParams.setParameter(HttpConnectionManagerParams.SO_TIMEOUT, 5000); - - } - - public void sendSLORequest(String subject, String reason) { - final Endpoint sloEndpoint = configuration.getSLOEndpoint(); - - if (sloEndpoint == null) { - return; - } - - LogoutRequestGenerator logoutRequestGenerator = new LogoutRequestGenerator(signingService, configuration.getEntityID(), - timeService, idService); - - final LogoutRequest logoutRequest = logoutRequestGenerator.buildLogoutRequest(subject, reason); - sendSLORequestViaPOST(logoutRequest); - } - - private void sendSLORequestViaPOST(LogoutRequest logoutRequest) { - final Endpoint sloEndpoint = configuration.getSLOEndpoint(); - - MarshallerFactory marshallerFactory = Configuration.getMarshallerFactory(); - final Marshaller marshaller = marshallerFactory.getMarshaller(logoutRequest); - String requestString = ""; - try { - requestString = XMLHelper.prettyPrintXML(marshaller.marshall(logoutRequest)); - } - catch (MarshallingException e) { - logger.error("Marshalling exception: ", e); - throw new RuntimeException(e); - } - - try { - final PostMethod method = new PostMethod(sloEndpoint.getUrl()); - method.addParameter("SAMLRequest", Base64.encode(requestString.getBytes())); - httpClient.executeMethod(method); - } - catch (IOException e) { - logger.error("IO exception when sending SLO Request ", e); - throw new RuntimeException(e); - } - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SSOSuccessLogoutResponder.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SSOSuccessLogoutResponder.java deleted file mode 100755 index 3fb8cb0f..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SSOSuccessLogoutResponder.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -import nl.surfnet.mujina.model.CommonConfiguration; -import nl.surfnet.mujina.saml.xml.EndpointGenerator; -import nl.surfnet.mujina.saml.xml.LogoutResponseGenerator; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; -import nl.surfnet.spring.security.opensaml.SAMLMessageHandler; -import org.apache.commons.lang.Validate; -import org.opensaml.saml2.core.LogoutResponse; -import org.opensaml.saml2.metadata.Endpoint; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.CredentialResolver; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.HttpRequestHandler; - -public class SSOSuccessLogoutResponder implements HttpRequestHandler { - - private final TimeService timeService; - private final IDService idService; - private final SAMLMessageHandler adapter; - private CredentialResolver credentialResolver; - - private final CommonConfiguration configuration; - - private static final Logger logger = LoggerFactory.getLogger(SSOSuccessLogoutResponder.class); - - public SSOSuccessLogoutResponder(TimeService timeService, IDService idService, SAMLMessageHandler adapter, - CredentialResolver credentialResolver, CommonConfiguration configuration) { - super(); - this.timeService = timeService; - this.idService = idService; - this.adapter = adapter; - this.credentialResolver = credentialResolver; - this.configuration = configuration; - } - - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add(new EntityIDCriteria(configuration.getEntityID())); - criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); - Credential signingCredential = getCredential(response, criteriaSet); - - if (signingCredential == null) - return; - - LogoutResponseGenerator logoutResponseGenerator = new LogoutResponseGenerator(configuration.getEntityID(), timeService, idService); - EndpointGenerator endpointGenerator = new EndpointGenerator(); - - LogoutResponse logoutResponse = logoutResponseGenerator.buildLogoutResponse(); - - String relayState = request.getParameter("RelayState"); - - if (configuration.getSLOEndpoint() == null) { - return; - } - - String sloEndpointURL = configuration.getSLOEndpoint().getUrl(); - - Endpoint endpoint = endpointGenerator.generateEndpoint(org.opensaml.saml2.metadata.SingleSignOnService.DEFAULT_ELEMENT_NAME, - sloEndpointURL, null); - - try { - adapter.sendSAMLMessage(logoutResponse, endpoint, response, relayState, signingCredential); - } catch (MessageEncodingException mee) { - logger.error("Exception encoding SAML message", mee); - response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - } - } - - private Credential getCredential(HttpServletResponse response, CriteriaSet criteriaSet) throws IOException { - Credential signingCredential; - try { - signingCredential = credentialResolver.resolveSingle(criteriaSet); - } catch (org.opensaml.xml.security.SecurityException e) { - logger.warn("Unable to resolve EntityID while signing", e); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - return null; - } - Validate.notNull(signingCredential); - return signingCredential; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SecurityPolicyDelegate.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SecurityPolicyDelegate.java deleted file mode 100644 index 74834aa2..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SecurityPolicyDelegate.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml; - -import java.util.List; - -import org.opensaml.ws.message.MessageContext; -import org.opensaml.ws.security.SecurityPolicy; -import org.opensaml.ws.security.SecurityPolicyException; -import org.opensaml.ws.security.SecurityPolicyRule; -import org.opensaml.ws.security.provider.BasicSecurityPolicy; - -public class SecurityPolicyDelegate implements SecurityPolicy { - - private final BasicSecurityPolicy basicSecurityPolicy; - - public SecurityPolicyDelegate(List securityPolicyRules) { - super(); - basicSecurityPolicy = new BasicSecurityPolicy(); - basicSecurityPolicy.getPolicyRules().addAll(securityPolicyRules); - } - - @Override - public void evaluate(MessageContext messageContext) throws SecurityPolicyException { - basicSecurityPolicy.evaluate(messageContext); - } - - @Override - public List getPolicyRules() { - return basicSecurityPolicy.getPolicyRules(); - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SignatureSecurityPolicyRule.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SignatureSecurityPolicyRule.java deleted file mode 100644 index 1576fbc2..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SignatureSecurityPolicyRule.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml; - -import org.opensaml.Configuration; -import org.opensaml.common.SignableSAMLObject; -import org.opensaml.security.SAMLSignatureProfileValidator; -import org.opensaml.ws.message.MessageContext; -import org.opensaml.ws.security.SecurityPolicyException; -import org.opensaml.ws.security.SecurityPolicyRule; -import org.opensaml.xml.security.credential.CredentialResolver; -import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver; -import org.opensaml.xml.signature.Signature; -import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine; -import org.opensaml.xml.validation.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; - -/** - * Rule to check that the message has been signed by an issuer that has - * credentials in the keystore. - * - * We could use a SAMLProtocolMessageXMLSignatureSecurityPolicyRule, but, that - * relies on role info to be set (which we will not be using). Also, we will - * insist that the message be signed and not rely on an additional rule to check - * the isAuthenticated flag on the message context. - */ -public class SignatureSecurityPolicyRule implements InitializingBean, SecurityPolicyRule { - - private final static Logger log = LoggerFactory.getLogger(SignatureSecurityPolicyRule.class); - - private final CredentialResolver credentialResolver; - private final SAMLSignatureProfileValidator samlSignatureProfileValidator; - ExplicitKeySignatureTrustEngine trustEngine; - - public SignatureSecurityPolicyRule(CredentialResolver credentialResolver, SAMLSignatureProfileValidator samlSignatureProfileValidator) { - super(); - this.credentialResolver = credentialResolver; - this.samlSignatureProfileValidator = samlSignatureProfileValidator; - } - - @Override - public void afterPropertiesSet() throws Exception { - - KeyInfoCredentialResolver keyInfoCredResolver = Configuration.getGlobalSecurityConfiguration().getDefaultKeyInfoCredentialResolver(); - - trustEngine = new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoCredResolver); - } - - @Override - public void evaluate(MessageContext messageContext) throws SecurityPolicyException { - - log.debug("evaluating signature of {}", messageContext); - - if (!(messageContext.getInboundMessage() instanceof SignableSAMLObject)) { - throw new SecurityPolicyException("Inbound Message is not a SignableSAMLObject"); - } - - SignableSAMLObject samlMessage = (SignableSAMLObject) messageContext.getInboundMessage(); - - checkSignatureProfile(samlMessage); - } - - private void checkSignatureProfile(SignableSAMLObject samlMessage) throws SecurityPolicyException { - try { - final Signature signature = samlMessage.getSignature(); - if (signature != null) { - samlSignatureProfileValidator.validate(signature); - } - } catch (ValidationException ve) { - - throw new SecurityPolicyException("Signature did not conform to SAML Signature profile", ve); - } - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SigningService.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SigningService.java deleted file mode 100644 index 360020c0..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SigningService.java +++ /dev/null @@ -1,71 +0,0 @@ -package nl.surfnet.mujina.saml; - -import nl.surfnet.mujina.model.CommonConfiguration; -import org.opensaml.xml.io.MarshallingException; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.CredentialResolver; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.opensaml.xml.signature.SignableXMLObject; -import org.opensaml.xml.signature.Signature; -import org.opensaml.xml.signature.SignatureConstants; -import org.opensaml.xml.signature.SignatureException; -import org.opensaml.xml.signature.Signer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -public class SigningService { - private static final Logger logger = LoggerFactory.getLogger(SigningService.class); - private final CommonConfiguration idpConfiguration; - private final CredentialResolver credentialResolver; - - @Autowired - public SigningService(CommonConfiguration configuration, CredentialResolver credentialResolver) { - this.idpConfiguration = configuration; - this.credentialResolver = credentialResolver; - } - - public void signXMLObject(final SignableXMLObject signableXMLObject) { - - Signature signature = (Signature) org.opensaml.Configuration.getBuilderFactory().getBuilder( - Signature.DEFAULT_ELEMENT_NAME).buildObject(Signature.DEFAULT_ELEMENT_NAME); - - signature.setSigningCredential(getCredential()); - signature.setSignatureAlgorithm(idpConfiguration.getSignatureAlgorithm()); - signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); - - signableXMLObject.setSignature(signature); - - try { - org.opensaml.Configuration.getMarshallerFactory().getMarshaller(signableXMLObject).marshall(signableXMLObject); - } - catch (MarshallingException e) { - logger.error("Cannot marshal signed object: ", e); - throw new RuntimeException(e); - } - try { - Signer.signObject(signature); - } - catch (SignatureException e) { - logger.error("SignatureException when signing object: ", e); - throw new RuntimeException(e); - } - } - - public Credential getCredential() { - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add(new EntityIDCriteria(idpConfiguration.getEntityID())); - criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); - try { - return credentialResolver.resolveSingle(criteriaSet); - } - catch (org.opensaml.xml.security.SecurityException e) { - logger.error("Unable to resolve EntityID while signing", e); - throw new RuntimeException(e); - } - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SingleSignOnService.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/SingleSignOnService.java deleted file mode 100644 index ac084fd1..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/SingleSignOnService.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; - -import nl.surfnet.mujina.saml.xml.SAML2ValidatorSuite; -import nl.surfnet.spring.security.opensaml.SAMLMessageHandler; -import org.opensaml.common.binding.SAMLMessageContext; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.ws.message.decoder.MessageDecodingException; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.validation.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.HttpRequestHandler; - -public class SingleSignOnService implements HttpRequestHandler { - - private static final Logger logger = LoggerFactory.getLogger(SingleSignOnService.class); - - private final SAMLMessageHandler adapter; - private final SAML2ValidatorSuite validatorSuite; - private final List> requestHandlerList; - - public SingleSignOnService(SAMLMessageHandler adapter, SAML2ValidatorSuite validatorSuite, - List> requestHandlerList) { - super(); - this.adapter = adapter; - this.validatorSuite = validatorSuite; - this.requestHandlerList = requestHandlerList; - } - - @SuppressWarnings("rawtypes") - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - SAMLMessageContext messageContext = null; - try { - messageContext = adapter.extractSAMLMessageContext(request); - } catch (MessageDecodingException | SecurityException mde) { - logger.error("Exception decoding SAML message", mde); - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - return; - } - - final RequestAbstractType inboundSAMLMessage = (RequestAbstractType) messageContext.getInboundSAMLMessage(); - - try { - validatorSuite.validate(inboundSAMLMessage); - } catch (ValidationException ve) { - logger.warn("SAML Message failed Validation", ve); - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - return; - } - - for (SAMLRequestHandler samlRequestHandler : requestHandlerList) { - if (samlRequestHandler.getTypeLocalName().equals(inboundSAMLMessage.getElementQName().getLocalPart())) { - samlRequestHandler.handleSAMLRequest(request, response, inboundSAMLMessage); - } - } - - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/EndpointGenerator.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/EndpointGenerator.java deleted file mode 100644 index 6341ceba..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/EndpointGenerator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import javax.xml.namespace.QName; - -import org.apache.commons.lang.StringUtils; -import org.opensaml.Configuration; -import org.opensaml.common.SAMLObjectBuilder; -import org.opensaml.saml2.metadata.Endpoint; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EndpointGenerator { - - private final static Logger logger = LoggerFactory.getLogger(EndpointGenerator.class); - - private XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - - @SuppressWarnings("unchecked") - public Endpoint generateEndpoint(QName service, String location, String responseLocation) { - - logger.debug("end point service: {}", service); - logger.debug("end point location: {}", location); - logger.debug("end point responseLocation: {}", responseLocation); - - SAMLObjectBuilder endpointBuilder = (SAMLObjectBuilder) builderFactory.getBuilder(service); - Endpoint samlEndpoint = endpointBuilder.buildObject(); - - samlEndpoint.setLocation(location); - - // this does not have to be set - if (StringUtils.isNotEmpty(responseLocation)) - samlEndpoint.setResponseLocation(responseLocation); - - return samlEndpoint; - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/IssuerGenerator.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/IssuerGenerator.java deleted file mode 100644 index 482eb97e..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/IssuerGenerator.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import org.opensaml.Configuration; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.impl.IssuerBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; - -public class IssuerGenerator { - - private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - - private final String issuingEntityName; - - public IssuerGenerator(String issuingEntityName) { - super(); - this.issuingEntityName = issuingEntityName; - } - - public Issuer generateIssuer() { - // Issuer - IssuerBuilder issuerBuilder = (IssuerBuilder) builderFactory.getBuilder(Issuer.DEFAULT_ELEMENT_NAME); - Issuer issuer = issuerBuilder.buildObject(); - - issuer.setValue(issuingEntityName); - issuer.setFormat(NameIDType.ENTITY); - - return issuer; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutRequestGenerator.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutRequestGenerator.java deleted file mode 100644 index 3f955a0e..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutRequestGenerator.java +++ /dev/null @@ -1,48 +0,0 @@ -package nl.surfnet.mujina.saml.xml; - -import nl.surfnet.mujina.saml.SigningService; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; -import org.opensaml.saml2.core.LogoutRequest; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.impl.LogoutRequestBuilder; -import org.opensaml.saml2.core.impl.NameIDBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; - -public class LogoutRequestGenerator { - private final XMLObjectBuilderFactory builderFactory = org.opensaml.Configuration.getBuilderFactory(); - private final SigningService signingService; - private final IDService idService; - private final TimeService timeService; - private final IssuerGenerator issuerGenerator; - - public LogoutRequestGenerator(SigningService signingService, String issuingEntityName, TimeService timeService, - IDService idService) { - this.signingService = signingService; - this.idService = idService; - this.timeService = timeService; - this.issuerGenerator = new IssuerGenerator(issuingEntityName); - } - - public LogoutRequest buildLogoutRequest(String subject, String reason) { - LogoutRequestBuilder logoutRequestBuilder = (LogoutRequestBuilder) builderFactory.getBuilder( - LogoutRequest.DEFAULT_ELEMENT_NAME); - - LogoutRequest logoutRequest = logoutRequestBuilder.buildObject(); - - logoutRequest.setID(idService.generateID()); - logoutRequest.setIssuer(issuerGenerator.generateIssuer()); - logoutRequest.setIssueInstant(timeService.getCurrentDateTime()); - - NameID nameId = new NameIDBuilder().buildObject(); - nameId.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"); - nameId.setValue(subject); - logoutRequest.setNameID(nameId); - - logoutRequest.setReason(reason); - - signingService.signXMLObject(logoutRequest); - - return logoutRequest; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutResponseGenerator.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutResponseGenerator.java deleted file mode 100644 index 06d73b6f..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/LogoutResponseGenerator.java +++ /dev/null @@ -1,38 +0,0 @@ -package nl.surfnet.mujina.saml.xml; - -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; -import org.opensaml.saml2.core.LogoutResponse; -import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.core.impl.LogoutResponseBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.opensaml.xml.security.credential.Credential; - -public class LogoutResponseGenerator { - private final XMLObjectBuilderFactory builderFactory = org.opensaml.Configuration.getBuilderFactory(); - private final IDService idService; - private final TimeService timeService; - private final IssuerGenerator issuerGenerator; - private final StatusGenerator statusGenerator; - - public LogoutResponseGenerator(String issuingEntityName, TimeService timeService, IDService idService) { - this.idService = idService; - this.timeService = timeService; - this.issuerGenerator = new IssuerGenerator(issuingEntityName); - this.statusGenerator = new StatusGenerator(); - } - - public LogoutResponse buildLogoutResponse() { - LogoutResponseBuilder logoutRequestBuilder = (LogoutResponseBuilder) builderFactory.getBuilder( - LogoutResponse.DEFAULT_ELEMENT_NAME); - - LogoutResponse logoutResponse = logoutRequestBuilder.buildObject(); - - logoutResponse.setID(idService.generateID()); - logoutResponse.setIssuer(issuerGenerator.generateIssuer()); - logoutResponse.setIssueInstant(timeService.getCurrentDateTime()); - logoutResponse.setStatus(statusGenerator.generateStatus(StatusCode.SUCCESS_URI)); - - return logoutResponse; - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/SAML2ValidatorSuite.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/SAML2ValidatorSuite.java deleted file mode 100644 index d9803b5e..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/SAML2ValidatorSuite.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import org.opensaml.xml.Configuration; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.validation.ValidationException; -import org.opensaml.xml.validation.ValidatorSuite; - -public class SAML2ValidatorSuite { - - public void validate(XMLObject xmlObject) throws ValidationException { - - ValidatorSuite schemaValidator = Configuration.getValidatorSuite("saml2-core-schema-validator"); - schemaValidator.validate(xmlObject); - ValidatorSuite specValidator = Configuration.getValidatorSuite("saml2-core-spec-validator"); - specValidator.validate(xmlObject); - - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/StatusGenerator.java b/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/StatusGenerator.java deleted file mode 100644 index 5b0b1703..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/saml/xml/StatusGenerator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import org.opensaml.Configuration; -import org.opensaml.saml2.core.Status; -import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.core.StatusMessage; -import org.opensaml.saml2.core.impl.StatusBuilder; -import org.opensaml.saml2.core.impl.StatusCodeBuilder; -import org.opensaml.saml2.core.impl.StatusMessageBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; - -public class StatusGenerator { - - private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - - public Status generateStatus(String value) { - - StatusBuilder builder = (StatusBuilder) builderFactory.getBuilder(Status.DEFAULT_ELEMENT_NAME); - - Status status = builder.buildObject(); - - StatusCodeBuilder codeBuilder = (StatusCodeBuilder) builderFactory.getBuilder(StatusCode.DEFAULT_ELEMENT_NAME); - - StatusCode statusCode = codeBuilder.buildObject(); - statusCode.setValue(value); - status.setStatusCode(statusCode); - - return status; - } - - public Status generateStatus(String value, String subStatus, String message) { - - StatusBuilder builder = (StatusBuilder) builderFactory.getBuilder(Status.DEFAULT_ELEMENT_NAME); - - Status status = builder.buildObject(); - - StatusCodeBuilder codeBuilder = (StatusCodeBuilder) builderFactory.getBuilder(StatusCode.DEFAULT_ELEMENT_NAME); - StatusCode statusCode = codeBuilder.buildObject(); - statusCode.setValue(value); - - StatusCode subStatusCode = codeBuilder.buildObject(); - subStatusCode.setValue(subStatus); - statusCode.setStatusCode(subStatusCode); - - status.setStatusCode(statusCode); - - StatusMessageBuilder statusMessageBuilder = (StatusMessageBuilder) builderFactory.getBuilder(StatusMessage.DEFAULT_ELEMENT_NAME); - - StatusMessage statusMessage = statusMessageBuilder.buildObject(); - - statusMessage.setMessage(message); - status.setStatusMessage(statusMessage); - - return status; - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/spring/SLOLogoutSuccessHandler.java b/mujina-common/src/main/java/nl/surfnet/mujina/spring/SLOLogoutSuccessHandler.java deleted file mode 100644 index e0067815..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/spring/SLOLogoutSuccessHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package nl.surfnet.mujina.spring; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -import nl.surfnet.mujina.saml.SLORequestSender; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.AbstractAuthenticationTargetUrlRequestHandler; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; - -public class SLOLogoutSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler implements LogoutSuccessHandler { - private final SLORequestSender sloRequestSender; - - @Autowired public SLOLogoutSuccessHandler(SLORequestSender sloRequestSender) { - this.sloRequestSender = sloRequestSender; - } - - @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) - throws IOException, ServletException { - if (authentication != null) { - sloRequestSender.sendSLORequest(authentication.getPrincipal().toString(), ""); - } - - super.handle(request, response, authentication); - } -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/util/IDService.java b/mujina-common/src/main/java/nl/surfnet/mujina/util/IDService.java deleted file mode 100644 index 2caa6144..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/util/IDService.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.util; - -import java.util.UUID; - -public class IDService { - - public String generateID() { - return UUID.randomUUID().toString(); - } - -} diff --git a/mujina-common/src/main/java/nl/surfnet/mujina/util/TimeService.java b/mujina-common/src/main/java/nl/surfnet/mujina/util/TimeService.java deleted file mode 100644 index c259942f..00000000 --- a/mujina-common/src/main/java/nl/surfnet/mujina/util/TimeService.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.util; - -import org.joda.time.DateTime; - -public class TimeService { - - public DateTime getCurrentDateTime() { - return new DateTime(); - } - -} diff --git a/mujina-idp-dist/build.xml b/mujina-idp-dist/build.xml deleted file mode 100644 index f8a0a6df..00000000 --- a/mujina-idp-dist/build.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mujina-idp-dist/pom.xml b/mujina-idp-dist/pom.xml deleted file mode 100644 index 6aea5972..00000000 --- a/mujina-idp-dist/pom.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - mujina - org.surfnet.coin - 4.1.3 - ../pom.xml - - 4.0.0 - - mujina-idp-dist - pom - Mujina Idp distribution package - - - - - maven-antrun-plugin - - - replace-version - test - - run - - - - - - - - - - - - - maven-assembly-plugin - - - - attached - - package - - - - src/main/assembly/dep.xml - - - - - - - - org.surfnet.coin - mujina-idp - war - ${project.version} - - - - diff --git a/mujina-idp-dist/src/main/assembly/dep.xml b/mujina-idp-dist/src/main/assembly/dep.xml deleted file mode 100644 index 8a2270dc..00000000 --- a/mujina-idp-dist/src/main/assembly/dep.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - bin - - tar.gz - - - - - src/main/resources/tomcat - tomcat/conf/classpath_properties - - **/*.* - - - - - target/resources/context - tomcat/conf/context - - **/*.* - - - - - src/main/resources/db - db - - **/*.* - - - - - src/main/docs - docs - - **/*.* - - - - - - - - /tomcat/webapps - false - runtime - - - diff --git a/mujina-idp-dist/src/main/resources/context/ROOT.xml b/mujina-idp-dist/src/main/resources/context/ROOT.xml deleted file mode 100644 index d74b460e..00000000 --- a/mujina-idp-dist/src/main/resources/context/ROOT.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - diff --git a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.dev b/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.dev deleted file mode 100644 index f006e39f..00000000 --- a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.dev +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - logs/mujina-idp.log - - - logs/mujina-idp-%d{yyyy-MM-dd}.log.gz - 60 - - - %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.test b/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.test deleted file mode 100644 index f006e39f..00000000 --- a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.test +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - logs/mujina-idp.log - - - logs/mujina-idp-%d{yyyy-MM-dd}.log.gz - 60 - - - %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.vm b/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.vm deleted file mode 100644 index 42de1b6f..00000000 --- a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp-logback.xml.vm +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - logs/mujina-idp.log - - - logs/mujina-idp-%d{yyyy-MM-dd}.log.gz - 60 - - - %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.acc b/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.acc deleted file mode 100644 index 027c9daa..00000000 --- a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.acc +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2012 SURFnet bv, The Netherlands -# -# 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. -# - -ASSERTION_VALIDITY_TIME_INS_SECONDS=90 - -REPLAY_CACHE_LIFE_IN_MILLIS=14400000 -ISSUE_INSTANT_CHECK_CLOCK_SKEW_IN_SECONDS=90 -ISSUE_INSTANT_CHECK_VALIDITY_TIME_IN_SECONDS=300 - -MAX_PARSER_POOL_SIZE=2 -AUTHN_RESPONDER_URI=/AuthnResponder -LOGOUT_RESPONDER_URI=/LogoutResponder -SSO_SERVICE_URI=/SingleSignOnService - -#SIGNATURE_ALGORITHM=http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 -SIGNATURE_ALGORITHM=http://www.w3.org/2000/09/xmldsig#rsa-sha1 diff --git a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.dev b/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.dev deleted file mode 100644 index 027c9daa..00000000 --- a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.dev +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2012 SURFnet bv, The Netherlands -# -# 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. -# - -ASSERTION_VALIDITY_TIME_INS_SECONDS=90 - -REPLAY_CACHE_LIFE_IN_MILLIS=14400000 -ISSUE_INSTANT_CHECK_CLOCK_SKEW_IN_SECONDS=90 -ISSUE_INSTANT_CHECK_VALIDITY_TIME_IN_SECONDS=300 - -MAX_PARSER_POOL_SIZE=2 -AUTHN_RESPONDER_URI=/AuthnResponder -LOGOUT_RESPONDER_URI=/LogoutResponder -SSO_SERVICE_URI=/SingleSignOnService - -#SIGNATURE_ALGORITHM=http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 -SIGNATURE_ALGORITHM=http://www.w3.org/2000/09/xmldsig#rsa-sha1 diff --git a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.test b/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.test deleted file mode 100644 index 027c9daa..00000000 --- a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.test +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2012 SURFnet bv, The Netherlands -# -# 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. -# - -ASSERTION_VALIDITY_TIME_INS_SECONDS=90 - -REPLAY_CACHE_LIFE_IN_MILLIS=14400000 -ISSUE_INSTANT_CHECK_CLOCK_SKEW_IN_SECONDS=90 -ISSUE_INSTANT_CHECK_VALIDITY_TIME_IN_SECONDS=300 - -MAX_PARSER_POOL_SIZE=2 -AUTHN_RESPONDER_URI=/AuthnResponder -LOGOUT_RESPONDER_URI=/LogoutResponder -SSO_SERVICE_URI=/SingleSignOnService - -#SIGNATURE_ALGORITHM=http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 -SIGNATURE_ALGORITHM=http://www.w3.org/2000/09/xmldsig#rsa-sha1 diff --git a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.vm b/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.vm deleted file mode 100644 index 388db52f..00000000 --- a/mujina-idp-dist/src/main/resources/tomcat/mujina-idp.properties.vm +++ /dev/null @@ -1,13 +0,0 @@ -ASSERTION_VALIDITY_TIME_INS_SECONDS=90 - -REPLAY_CACHE_LIFE_IN_MILLIS=14400000 -ISSUE_INSTANT_CHECK_CLOCK_SKEW_IN_SECONDS=90 -ISSUE_INSTANT_CHECK_VALIDITY_TIME_IN_SECONDS=300 - -MAX_PARSER_POOL_SIZE=2 -AUTHN_RESPONDER_URI=/AuthnResponder -LOGOUT_RESPONDER_URI=/LogoutResponder -SSO_SERVICE_URI=/SingleSignOnService - -#SIGNATURE_ALGORITHM=http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 -SIGNATURE_ALGORITHM=http://www.w3.org/2000/09/xmldsig#rsa-sha1 diff --git a/mujina-idp/pom.xml b/mujina-idp/pom.xml deleted file mode 100644 index d11d70e4..00000000 --- a/mujina-idp/pom.xml +++ /dev/null @@ -1,211 +0,0 @@ - - - - 4.0.0 - mujina-idp - war - - - org.surfnet.coin - mujina - 4.1.3 - ../pom.xml - - - 8080 - 8443 - - - - - org.surfnet.coin - mujina-common - ${project.parent.version} - - - - org.surfnet.coin - mujina-common - ${project.parent.version} - test-jar - test - - - - org.springframework - spring-webmvc - - - - org.codehaus.jackson - jackson-mapper-asl - - - - org.codehaus.jackson - jackson-jaxrs - - - - org.springframework - spring-test - - - - org.springframework.security - spring-security-core - - - - org.springframework.security - spring-security-web - - - - org.springframework.security - spring-security-config - - - - org.springframework.security - spring-security-taglibs - - - - javax.servlet - servlet-api - provided - - - - javax.servlet - jstl - - - - junit - junit - - - - org.mockito - mockito-all - - - - xmlunit - xmlunit - - - - org.slf4j - slf4j-api - - - ch.qos.logback - logback-classic - - - - org.surfnet.coin - spring-security-opensaml - - - - nl.iprofs.modules.context-logging - context-logging - - - org.slf4j - jcl-over-slf4j - - - - - - - ${project.basedir}/src/main/webapp/WEB-INF - - - ${project.basedir}/src/main/resources - - - ${project.basedir}/src/test/resources - - - - - - org.apache.maven.plugins - maven-war-plugin - 2.2 - - - org.codehaus.mojo - keytool-maven-plugin - 1.5 - - - generate-resources - clean - - clean - - - - generate-resources - genkey - - generateKeyPair - - - - - ${project.build.directory}/jetty-ssl.keystore - cn=localhost - jetty6 - jetty6 - jetty6 - RSA - - - - org.mortbay.jetty - maven-jetty-plugin - 6.1.26 - - / - 3 - - - ${httpsPort} - 60000 - ${project.build.directory}/jetty-ssl.keystore - jetty6 - jetty6 - - - ${httpPort} - 60000 - - - true - - - - - diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/controllers/IdentityProviderAPI.java b/mujina-idp/src/main/java/nl/surfnet/mujina/controllers/IdentityProviderAPI.java deleted file mode 100755 index 652ff8ee..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/controllers/IdentityProviderAPI.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.controllers; - -import java.util.ArrayList; -import java.util.List; - -import nl.surfnet.mujina.model.*; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; - -@Controller -public class IdentityProviderAPI { - - private final static Logger log = LoggerFactory.getLogger(IdentityProviderAPI.class); - - final IdpConfiguration configuration; - - @Autowired - public IdentityProviderAPI(final IdpConfiguration configuration) { - this.configuration = configuration; - } - - @RequestMapping(value = { "/attributes" }, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setAttributes(@RequestBody AttributesMap attribues) { - log.debug("Request to replace all attributes"); - configuration.getAttributes().clear(); - for(String name : attribues.keySet()) { - Attribute attribute = attribues.get(name); - configuration.getAttributes().put(name, attribute.getValue()); - } - } - - @RequestMapping(value = { "/attributes/{name:.+}" }, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setAttribute(@PathVariable String name, @RequestBody Attribute attribute) { - log.debug("Request to set attribute {} to {}", attribute.getValue(), name); - configuration.getAttributes().put(name, attribute.getValue()); - } - - @RequestMapping(value = { "/attributes/{name:.+}" }, method = RequestMethod.DELETE) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void removeAttribute(@PathVariable String name) { - log.debug("Request to remove attribute {}", name); - configuration.getAttributes().remove(name); - } - - @RequestMapping(value = { "/users" }, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void addUser(@RequestBody User user) { - log.debug("Request to add user {} with password {}", user.getName(), user.getPassword()); - final List grants = new ArrayList(); - final List authorities = user.getAuthorities(); - for (String authority : authorities) { - grants.add(new SimpleGrantedAuthority(authority)); - } - SimpleAuthentication auth = new SimpleAuthentication(user.getName(), user.getPassword(), grants); - configuration.getUsers().add(auth); - } - - @RequestMapping(value = { "/authmethod" }, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setAuthenticationMethod(@RequestBody AuthenticationMethod authenticationMethod) { - log.debug("Request to set auth method to {}", authenticationMethod.getValue()); - final AuthenticationMethod.Method method = AuthenticationMethod.Method.valueOf(authenticationMethod.getValue()); - configuration.setAuthentication(method); - } - - @RequestMapping(value = { "/acsendpoint" }, method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.NO_CONTENT) - @ResponseBody - public void setAcsEndpoint(@RequestBody Endpoint acsEndpoint) { - log.debug("Request to set Assertion Consumer Service Endpoint to {}", acsEndpoint.getUrl()); - configuration.setAcsEndpoint(acsEndpoint); - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/model/AttributesMap.java b/mujina-idp/src/main/java/nl/surfnet/mujina/model/AttributesMap.java deleted file mode 100644 index f65b358c..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/model/AttributesMap.java +++ /dev/null @@ -1,6 +0,0 @@ -package nl.surfnet.mujina.model; - -import java.util.HashMap; - -// workaround for this: http://stackoverflow.com/a/24318963 -public class AttributesMap extends HashMap {} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfiguration.java b/mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfiguration.java deleted file mode 100755 index 85f5ee09..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfiguration.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.util.Collection; -import java.util.Map; - -public interface IdpConfiguration extends CommonConfiguration { - - Map> getAttributes(); - - Collection getUsers(); - - AuthenticationMethod.Method getAuthentication(); - - void setAuthentication(AuthenticationMethod.Method method); - - Endpoint getAcsEndpoint(); - - void setAcsEndpoint(Endpoint acsEndpoint); - -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfigurationImpl.java b/mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfigurationImpl.java deleted file mode 100755 index 07fbec7f..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/model/IdpConfigurationImpl.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.security.KeyStore; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import nl.surfnet.spring.security.opensaml.util.KeyStoreUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.io.ClassPathResource; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.GrantedAuthorityImpl; - -public class IdpConfigurationImpl extends CommonConfigurationImpl implements IdpConfiguration { - - private final static Logger LOGGER = LoggerFactory.getLogger(IdpConfigurationImpl.class); - - private Map> attributes = new TreeMap<>(); - private Collection users = new ArrayList(); - private AuthenticationMethod.Method authMethod; - private Endpoint acsEndpoint; - - public IdpConfigurationImpl() { - reset(); - } - - @Override - public void reset() { - authMethod = AuthenticationMethod.Method.ALL; - entityId = "http://mock-idp"; - attributes.clear(); - putAttribute("urn:mace:dir:attribute-def:uid", "john.doe"); - putAttribute("urn:mace:dir:attribute-def:cn", "John Doe"); - putAttribute("urn:mace:dir:attribute-def:givenName", "John"); - putAttribute("urn:mace:dir:attribute-def:sn", "Doe"); - putAttribute("urn:mace:dir:attribute-def:displayName", "John Doe"); - putAttribute("urn:mace:dir:attribute-def:mail", "j.doe@example.com"); - putAttribute("urn:mace:terena.org:attribute-def:schacHomeOrganization", "example.com"); - putAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName", "j.doe@example.com"); - putAttribute("urn:oid:1.3.6.1.4.1.1076.20.100.10.10.1", "guest"); - try { - keyStore = KeyStore.getInstance("JKS"); - keyStore.load(null, keystorePassword.toCharArray()); - KeyStoreUtil.appendKeyToKeyStore(keyStore, "http://mock-idp", new ClassPathResource("idp-crt.pem").getInputStream(), - new ClassPathResource("idp-key.pkcs8.der").getInputStream(), keystorePassword.toCharArray()); - privateKeyPasswords.put("http://mock-idp", keystorePassword); - } catch (Exception e) { - LOGGER.error("Unable to create default keystore", e); - } - users.clear(); - List authorities = new ArrayList(); - authorities.add(new GrantedAuthorityImpl("ROLE_USER")); - authorities.add(new GrantedAuthorityImpl("ROLE_ADMIN")); - final SimpleAuthentication admin = new SimpleAuthentication("admin", "secret", authorities); - users.add(admin); - authorities = new ArrayList(); - authorities.add(new GrantedAuthorityImpl("ROLE_USER")); - final SimpleAuthentication user = new SimpleAuthentication("user", "secret", authorities); - users.add(user); - setAcsEndpoint(null); - } - - private void putAttribute(String key, String... values) { - this.attributes.put(key, Arrays.asList(values)); - } - - @Override - public Map> getAttributes() { - return attributes; - } - - @Override - public Collection getUsers() { - return users; - } - - @Override - public AuthenticationMethod.Method getAuthentication() { - return authMethod; - } - - @Override - public void setAuthentication(final AuthenticationMethod.Method method) { - this.authMethod = method; - } - - @Override - public Endpoint getAcsEndpoint() { - return acsEndpoint; - } - - @Override - public void setAcsEndpoint(final Endpoint acsEndpoint) { - this.acsEndpoint = acsEndpoint; - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/model/SimpleAuthentication.java b/mujina-idp/src/main/java/nl/surfnet/mujina/model/SimpleAuthentication.java deleted file mode 100644 index 3a9bdf25..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/model/SimpleAuthentication.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.model; - -import java.util.Collection; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; - -@SuppressWarnings("serial") -public class SimpleAuthentication implements Authentication { - - private String username; - private String password; - private Collection authorities; - - public SimpleAuthentication(String username, String password, Collection authorities) { - this.username = username; - this.password = password; - this.authorities = authorities; - } - - @Override - public Collection getAuthorities() { - return authorities; - } - - @Override - public Object getCredentials() { - return password; - } - - @Override - public Object getDetails() { - return null; - } - - @Override - public Object getPrincipal() { - return username; - } - - @Override - public boolean isAuthenticated() { - return true; - } - - @Override - public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException { - } - - @Override - public String toString() { - return username + " / " + password; - } - - @Override - public String getName() { - return username; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - final SimpleAuthentication that = (SimpleAuthentication) o; - - if (authorities != null ? !authorities.equals(that.authorities) : that.authorities != null) { - return false; - } - if (password != null ? !password.equals(that.password) : that.password != null) { - return false; - } - if (username != null ? !username.equals(that.username) : that.username != null) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = username != null ? username.hashCode() : 0; - result = 31 * result + (password != null ? password.hashCode() : 0); - result = 31 * result + (authorities != null ? authorities.hashCode() : 0); - return result; - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/SAMLAuthnRequestHandler.java b/mujina-idp/src/main/java/nl/surfnet/mujina/saml/SAMLAuthnRequestHandler.java deleted file mode 100644 index 45c13bb7..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/SAMLAuthnRequestHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package nl.surfnet.mujina.saml; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -import nl.surfnet.mujina.spring.AuthnRequestInfo; -import org.opensaml.saml2.core.AuthnRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.web.WebAttributes; - -public class SAMLAuthnRequestHandler implements SAMLRequestHandler { - private static final Logger logger = LoggerFactory.getLogger(SAMLAuthnRequestHandler.class); - - private final String authnResponderURI; - - public SAMLAuthnRequestHandler(String authnResponderURI) { - this.authnResponderURI = authnResponderURI; - } - - @Override public void handleSAMLRequest(HttpServletRequest request, HttpServletResponse response, AuthnRequest authnRequest) - throws ServletException, IOException { - - AuthnRequestInfo info = new AuthnRequestInfo(authnRequest.getAssertionConsumerServiceURL(), authnRequest.getID(), - authnRequest.getIssuer().getValue()); - - logger.debug("AuthnRequest {} verified. Forwarding to SSOSuccessAuthnResponder", info); - request.getSession().setAttribute(AuthnRequestInfo.class.getName(), info); - - logger.debug("request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) is {}", - request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION)); - - logger.debug("forwarding to authnResponderURI: {}", authnResponderURI); - - request.getRequestDispatcher(authnResponderURI).forward(request, response); - } - - @Override public String getTypeLocalName() { - return AuthnRequest.DEFAULT_ELEMENT_LOCAL_NAME; - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/SSOSuccessAuthnResponder.java b/mujina-idp/src/main/java/nl/surfnet/mujina/saml/SSOSuccessAuthnResponder.java deleted file mode 100755 index dac418c7..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/SSOSuccessAuthnResponder.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml; - -import javax.servlet.ServletException; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.net.URLDecoder; - -import nl.surfnet.mujina.model.IdpConfiguration; -import nl.surfnet.mujina.model.SimpleAuthentication; -import nl.surfnet.mujina.saml.xml.AuthnResponseGenerator; -import nl.surfnet.mujina.saml.xml.EndpointGenerator; -import nl.surfnet.mujina.spring.AuthnRequestInfo; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; -import nl.surfnet.spring.security.opensaml.SAMLMessageHandler; -import org.apache.commons.lang.Validate; -import org.joda.time.DateTime; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.metadata.Endpoint; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.CredentialResolver; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Required; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.web.HttpRequestHandler; - -public class SSOSuccessAuthnResponder implements HttpRequestHandler { - - private final TimeService timeService; - private final IDService idService; - private int responseValidityTimeInSeconds; - private final SAMLMessageHandler adapter; - private CredentialResolver credentialResolver; - private SigningService signingService; - - @Autowired - IdpConfiguration idpConfiguration; - - private final static Logger logger = LoggerFactory - .getLogger(SSOSuccessAuthnResponder.class); - - - public SSOSuccessAuthnResponder(TimeService timeService, - IDService idService, - SAMLMessageHandler adapter, - CredentialResolver credentialResolver, SigningService signingService) { - super(); - this.timeService = timeService; - this.idService = idService; - this.adapter = adapter; - this.credentialResolver = credentialResolver; - this.signingService = signingService; - } - - - @Required - public void setResponseValidityTimeInSeconds(int responseValidityTimeInSeconds) { - this.responseValidityTimeInSeconds = responseValidityTimeInSeconds; - } - - @Override - public void handleRequest(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - AuthnRequestInfo info = (AuthnRequestInfo) request.getSession().getAttribute(AuthnRequestInfo.class.getName()); - - if (info == null) { - logger.warn("Could not find AuthnRequest on the request. Responding with SC_FORBIDDEN."); - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return; - } - - logger.debug("AuthnRequestInfo: {}", info); - - SimpleAuthentication authToken = (SimpleAuthentication) SecurityContextHolder.getContext().getAuthentication(); - DateTime authnInstant = new DateTime(request.getSession().getCreationTime()); - - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add(new EntityIDCriteria(idpConfiguration.getEntityID())); - criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); - Credential signingCredential = null; - try { - signingCredential = credentialResolver.resolveSingle(criteriaSet); - } catch (org.opensaml.xml.security.SecurityException e) { - logger.warn("Unable to resolve EntityID while signing", e); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - return; - } - Validate.notNull(signingCredential); - - AuthnResponseGenerator authnResponseGenerator = new AuthnResponseGenerator(signingService, idpConfiguration.getEntityID(), timeService, idService, idpConfiguration); - EndpointGenerator endpointGenerator = new EndpointGenerator(); - - final String remoteIP = request.getRemoteAddr(); - String attributeJson = null; - - if (null != request.getCookies()) { - for (Cookie current : request.getCookies()) { - if (current.getName().equalsIgnoreCase("mujina-attr")) { - logger.info("Found a attribute cookie, this is used for the assertion response"); - attributeJson = URLDecoder.decode(current.getValue(), "UTF-8"); - } - } - } - String acsEndpointURL = info.getAssertionConsumerURL(); - if (idpConfiguration.getAcsEndpoint() != null) { - acsEndpointURL = idpConfiguration.getAcsEndpoint().getUrl(); - } - Response authResponse = authnResponseGenerator.generateAuthnResponse(remoteIP, authToken, acsEndpointURL, - responseValidityTimeInSeconds, info.getAuthnRequestID(), authnInstant, attributeJson, info.getEntityId()); - Endpoint endpoint = endpointGenerator.generateEndpoint(org.opensaml.saml2.metadata.AssertionConsumerService.DEFAULT_ELEMENT_NAME, - acsEndpointURL, null); - - request.getSession().removeAttribute(AuthnRequestInfo.class.getName()); - - String relayState = request.getParameter("RelayState"); - - //we could use a different adapter to send the response based on request issuer... - try { - adapter.sendSAMLMessage(authResponse, endpoint, response, relayState, signingCredential); - } catch (MessageEncodingException mee) { - logger.error("Exception encoding SAML message", mee); - response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - } - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AssertionGenerator.java b/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AssertionGenerator.java deleted file mode 100644 index c1d85228..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AssertionGenerator.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import nl.surfnet.mujina.model.AuthenticationMethod; -import nl.surfnet.mujina.model.IdpConfiguration; -import nl.surfnet.mujina.model.SimpleAuthentication; -import nl.surfnet.mujina.saml.SigningService; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; -import org.joda.time.DateTime; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.Audience; -import org.opensaml.saml2.core.AudienceRestriction; -import org.opensaml.saml2.core.AuthnStatement; -import org.opensaml.saml2.core.Conditions; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.core.impl.AssertionBuilder; -import org.opensaml.saml2.core.impl.AudienceBuilder; -import org.opensaml.saml2.core.impl.AudienceRestrictionBuilder; -import org.opensaml.saml2.core.impl.ConditionsBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static java.util.Arrays.asList; - -public class AssertionGenerator { - private static final Logger logger = LoggerFactory.getLogger(AssertionGenerator.class); - private final XMLObjectBuilderFactory builderFactory = org.opensaml.Configuration.getBuilderFactory(); - - private final IssuerGenerator issuerGenerator; - private final SubjectGenerator subjectGenerator; - private final IDService idService; - private final SigningService signingService; - private final TimeService timeService; - private final AuthnStatementGenerator authnStatementGenerator = new AuthnStatementGenerator(); - private final AttributeStatementGenerator attributeStatementGenerator = new AttributeStatementGenerator(); - private IdpConfiguration idpConfiguration; - - public AssertionGenerator(SigningService signingService, String issuingEntityName, TimeService timeService, IDService idService, - IdpConfiguration idpConfiguration) { - super(); - this.signingService = signingService; - this.timeService = timeService; - this.idService = idService; - this.idpConfiguration = idpConfiguration; - issuerGenerator = new IssuerGenerator(issuingEntityName); - subjectGenerator = new SubjectGenerator(timeService); - } - - public Assertion generateAssertion(String remoteIP, SimpleAuthentication authToken, String recipientAssertionConsumerURL, - int validForInSeconds, String inResponseTo, DateTime authnInstant, String attributeJson, String requestingEntityId) { - - AssertionBuilder assertionBuilder = (AssertionBuilder) builderFactory.getBuilder(Assertion.DEFAULT_ELEMENT_NAME); - Assertion assertion = assertionBuilder.buildObject(); - - String name = authToken.getName(); - Subject subject = subjectGenerator.generateSubject(recipientAssertionConsumerURL, validForInSeconds, name, inResponseTo, - remoteIP); - - Issuer issuer = issuerGenerator.generateIssuer(); - - // include audience as per spec - final Audience audience = new AudienceBuilder().buildObject(); - audience.setAudienceURI(requestingEntityId); - final AudienceRestriction audienceRestriction = new AudienceRestrictionBuilder().buildObject(); - audienceRestriction.getAudiences().add(audience); - - final Conditions conditions = new ConditionsBuilder().buildObject(); - conditions.getAudienceRestrictions().add(audienceRestriction); - assertion.setConditions(conditions); - - - AuthnStatement authnStatement = authnStatementGenerator.generateAuthnStatement(authnInstant, idpConfiguration.getEntityID()); - - assertion.setIssuer(issuer); - assertion.getAuthnStatements().add(authnStatement); - assertion.setSubject(subject); - - final Map> attributes = new HashMap<>(); - - if (null != attributeJson) { - attributes.putAll(getAttributesFromCookie(attributeJson)); - } else { - // use the attributes from the IDP Configuration - attributes.putAll(idpConfiguration.getAttributes()); - if (idpConfiguration.getAuthentication() == AuthenticationMethod.Method.ALL) { - attributes.put("urn:mace:dir:attribute-def:uid", asList(name)); - attributes.put("urn:mace:dir:attribute-def:displayName", asList(name)); - } - } - - assertion.getAttributeStatements().add(attributeStatementGenerator.generateAttributeStatement(attributes)); - - assertion.setID(idService.generateID()); - assertion.setIssueInstant(timeService.getCurrentDateTime()); - - signingService.signXMLObject(assertion); - - return assertion; - } - - private Map> getAttributesFromCookie(String attributeJson) { - ObjectMapper mapper = new ObjectMapper(); - Map> result = null; - try { - TypeReference>> typeReference = new TypeReference>>() { - }; - result = mapper.readValue(attributeJson, typeReference); - } catch (JsonParseException e) { - logger.warn("could not parse json file for IDP attributes", e); - throw new RuntimeException(e); - } catch (JsonMappingException e) { - logger.warn("could not parse json file for IDP attributes", e); - throw new RuntimeException(e); - } catch (IOException e) { - logger.warn("could not parse json file for IDP attributes", e); - throw new RuntimeException(e); - } - return result; - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AttributeStatementGenerator.java b/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AttributeStatementGenerator.java deleted file mode 100644 index 0f34f5db..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AttributeStatementGenerator.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import java.util.Map; -import java.util.List; - -import org.opensaml.Configuration; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeStatement; -import org.opensaml.saml2.core.AttributeValue; -import org.opensaml.saml2.core.impl.AttributeBuilder; -import org.opensaml.saml2.core.impl.AttributeStatementBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.opensaml.xml.schema.XSString; -import org.opensaml.xml.schema.impl.XSStringBuilder; - -public class AttributeStatementGenerator { - private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - - public AttributeStatement generateAttributeStatement(final Map> attributes) { - AttributeStatementBuilder attributeStatementBuilder = (AttributeStatementBuilder) builderFactory - .getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME); - AttributeStatement attributeStatement = attributeStatementBuilder.buildObject(); - - AttributeBuilder attributeBuilder = (AttributeBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME); - XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); - - for (Map.Entry> entry : attributes.entrySet()) { - Attribute attribute = attributeBuilder.buildObject(); - attribute.setName(entry.getKey()); - for (String value : entry.getValue()) { - XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); - stringValue.setValue(value); - attribute.getAttributeValues().add(stringValue); - } - attributeStatement.getAttributes().add(attribute); - } - - return attributeStatement; - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnResponseGenerator.java b/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnResponseGenerator.java deleted file mode 100644 index 6959a62c..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnResponseGenerator.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import nl.surfnet.mujina.model.IdpConfiguration; -import nl.surfnet.mujina.model.SimpleAuthentication; -import nl.surfnet.mujina.saml.SigningService; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; - -import org.joda.time.DateTime; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.core.impl.ResponseBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.opensaml.xml.security.credential.Credential; -import org.springframework.security.core.AuthenticationException; - -public class AuthnResponseGenerator { - - private final XMLObjectBuilderFactory builderFactory = org.opensaml.Configuration.getBuilderFactory(); - - private final IssuerGenerator issuerGenerator; - private final AssertionGenerator assertionGenerator; - private final IDService idService; - private final TimeService timeService; - - StatusGenerator statusGenerator; - - public AuthnResponseGenerator(SigningService signingService, String issuingEntityName, TimeService timeService, IDService idService, - IdpConfiguration idpConfiguration) { - super(); - this.idService = idService; - this.timeService = timeService; - issuerGenerator = new IssuerGenerator(issuingEntityName); - assertionGenerator = new AssertionGenerator(signingService, issuingEntityName, timeService, idService, idpConfiguration); - statusGenerator = new StatusGenerator(); - } - - public Response generateAuthnResponse(String remoteIP, SimpleAuthentication authToken, String recepientAssertionConsumerURL, - int validForInSeconds, String inResponseTo, DateTime authnInstant, String attributeJson, String requestingEntityId) { - - ResponseBuilder responseBuilder = (ResponseBuilder) builderFactory.getBuilder(Response.DEFAULT_ELEMENT_NAME); - Response authResponse = responseBuilder.buildObject(); - - Issuer responseIssuer = issuerGenerator.generateIssuer(); - - Assertion assertion = assertionGenerator.generateAssertion(remoteIP, authToken, recepientAssertionConsumerURL, validForInSeconds, - inResponseTo, authnInstant, attributeJson, requestingEntityId); - - authResponse.setIssuer(responseIssuer); - authResponse.setID(idService.generateID()); - authResponse.setIssueInstant(timeService.getCurrentDateTime()); - authResponse.setInResponseTo(inResponseTo); - authResponse.getAssertions().add(assertion); - authResponse.setDestination(recepientAssertionConsumerURL); - authResponse.setStatus(statusGenerator.generateStatus(StatusCode.SUCCESS_URI)); - - return authResponse; - } - - public Response generateAuthnResponseFailure(String recepientAssertionConsumerURL, String inResponseTo, AuthenticationException ae) { - - ResponseBuilder responseBuilder = (ResponseBuilder) builderFactory.getBuilder(Response.DEFAULT_ELEMENT_NAME); - Response authResponse = responseBuilder.buildObject(); - - Issuer responseIssuer = issuerGenerator.generateIssuer(); - - authResponse.setIssuer(responseIssuer); - authResponse.setID(idService.generateID()); - authResponse.setIssueInstant(timeService.getCurrentDateTime()); - authResponse.setInResponseTo(inResponseTo); - authResponse.setDestination(recepientAssertionConsumerURL); - authResponse.setStatus(statusGenerator.generateStatus(StatusCode.RESPONDER_URI, StatusCode.AUTHN_FAILED_URI, ae.getClass().getName())); - - return authResponse; - - } - -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnStatementGenerator.java b/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnStatementGenerator.java deleted file mode 100644 index ee071b4c..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/AuthnStatementGenerator.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import org.joda.time.DateTime; -import org.opensaml.Configuration; -import org.opensaml.saml2.core.AuthenticatingAuthority; -import org.opensaml.saml2.core.AuthnContext; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnStatement; -import org.opensaml.saml2.core.impl.AuthenticatingAuthorityBuilder; -import org.opensaml.saml2.core.impl.AuthnContextBuilder; -import org.opensaml.saml2.core.impl.AuthnContextClassRefBuilder; -import org.opensaml.saml2.core.impl.AuthnStatementBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; - -public class AuthnStatementGenerator { - - private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - - public AuthnStatement generateAuthnStatement(DateTime authnInstant, String entityID) { - - // Response/Assertion/AuthnStatement/AuthContext/AuthContextClassRef - AuthnContextClassRefBuilder authnContextClassRefBuilder = (AuthnContextClassRefBuilder) builderFactory - .getBuilder(AuthnContextClassRef.DEFAULT_ELEMENT_NAME); - AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject(); - // urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport - authnContextClassRef.setAuthnContextClassRef(AuthnContext.PASSWORD_AUTHN_CTX); - - // Response/Assertion/AuthnStatement/AuthContext/AuthenticatingAuthority - AuthenticatingAuthorityBuilder authenticatingAuthorityBuilder = - (AuthenticatingAuthorityBuilder) builderFactory.getBuilder(AuthenticatingAuthority.DEFAULT_ELEMENT_NAME); - AuthenticatingAuthority authenticatingAuthority = authenticatingAuthorityBuilder.buildObject(); - authenticatingAuthority.setURI(entityID); - - // Response/Assertion/AuthnStatement/AuthContext - AuthnContextBuilder authnContextBuilder = (AuthnContextBuilder) builderFactory.getBuilder(AuthnContext.DEFAULT_ELEMENT_NAME); - AuthnContext authnContext = authnContextBuilder.buildObject(); - authnContext.setAuthnContextClassRef(authnContextClassRef); - authnContext.getAuthenticatingAuthorities().add(authenticatingAuthority); - - // Response/Assertion/AuthnStatement - AuthnStatementBuilder authnStatementBuilder = (AuthnStatementBuilder) builderFactory.getBuilder(AuthnStatement.DEFAULT_ELEMENT_NAME); - AuthnStatement authnStatement = authnStatementBuilder.buildObject(); - authnStatement.setAuthnContext(authnContext); - - authnStatement.setAuthnInstant(authnInstant); - - return authnStatement; - - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/SubjectGenerator.java b/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/SubjectGenerator.java deleted file mode 100644 index f85966ed..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/saml/xml/SubjectGenerator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.saml.xml; - -import nl.surfnet.mujina.util.TimeService; - -import org.opensaml.Configuration; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.core.SubjectConfirmation; -import org.opensaml.saml2.core.SubjectConfirmationData; -import org.opensaml.saml2.core.impl.NameIDBuilder; -import org.opensaml.saml2.core.impl.SubjectBuilder; -import org.opensaml.saml2.core.impl.SubjectConfirmationBuilder; -import org.opensaml.saml2.core.impl.SubjectConfirmationDataBuilder; -import org.opensaml.xml.XMLObjectBuilderFactory; - -public class SubjectGenerator { - - private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - private final TimeService timeService; - - public SubjectGenerator(TimeService timeService) { - super(); - this.timeService = timeService; - } - - public Subject generateSubject(String recepientAssertionConsumerURL, int validForInSeconds, String subjectName, String inResponseTo, - String clientAddress) { - - // Response/Assertion/Subject/NameID - NameIDBuilder nameIDBuilder = (NameIDBuilder) builderFactory.getBuilder(NameID.DEFAULT_ELEMENT_NAME); - NameID nameID = nameIDBuilder.buildObject(); - nameID.setValue(subjectName); - nameID.setFormat(NameIDType.UNSPECIFIED); - - // Response/Assertion/Subject - SubjectBuilder subjectBuilder = (SubjectBuilder) builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME); - Subject subject = subjectBuilder.buildObject(); - - subject.setNameID(nameID); - - SubjectConfirmationBuilder subjectConfirmationBuilder = (SubjectConfirmationBuilder) builderFactory - .getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME); - SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject(); - subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER); - - SubjectConfirmationDataBuilder subjectConfirmationDataBuilder = (SubjectConfirmationDataBuilder) builderFactory - .getBuilder(SubjectConfirmationData.DEFAULT_ELEMENT_NAME); - SubjectConfirmationData subjectConfirmationData = subjectConfirmationDataBuilder.buildObject(); - - subjectConfirmationData.setRecipient(recepientAssertionConsumerURL); - subjectConfirmationData.setInResponseTo(inResponseTo); - subjectConfirmationData.setNotOnOrAfter(timeService.getCurrentDateTime().plusSeconds(validForInSeconds)); - subjectConfirmationData.setAddress(clientAddress); - - subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData); - - subject.getSubjectConfirmations().add(subjectConfirmation); - - return subject; - } - -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/spring/AuthnRequestInfo.java b/mujina-idp/src/main/java/nl/surfnet/mujina/spring/AuthnRequestInfo.java deleted file mode 100644 index 44d588eb..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/spring/AuthnRequestInfo.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.spring; - -import java.io.Serializable; - -import org.apache.commons.lang.builder.ToStringBuilder; - -@SuppressWarnings("serial") -public class AuthnRequestInfo implements Serializable { - - private final String assertionConsumerURL; - private final String authnRequestID; - private final String entityId; - - public AuthnRequestInfo(String assertionConsumerURL, String authnRequestID, String entityId) { - this.assertionConsumerURL = assertionConsumerURL; - this.authnRequestID = authnRequestID; - this.entityId = entityId; - } - - public String getEntityId() { - return entityId; - } - - public String getAssertionConsumerURL() { - return assertionConsumerURL; - } - - public String getAuthnRequestID() { - return authnRequestID; - } - - @Override - public String toString() { - return new ToStringBuilder(this).append("assertionConsumerURL", assertionConsumerURL).append("authnRequestID", authnRequestID).append("entityId", entityId).toString(); - - } - -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/spring/RealAuthenticationFailureHandler.java b/mujina-idp/src/main/java/nl/surfnet/mujina/spring/RealAuthenticationFailureHandler.java deleted file mode 100755 index f1dff9dc..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/spring/RealAuthenticationFailureHandler.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.spring; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import nl.surfnet.mujina.saml.SigningService; -import org.apache.commons.lang.Validate; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.Endpoint; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.*; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.CredentialResolver; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.WebAttributes; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; - -import nl.surfnet.mujina.model.IdpConfiguration; -import nl.surfnet.mujina.saml.xml.AuthnResponseGenerator; -import nl.surfnet.mujina.saml.xml.EndpointGenerator; -import nl.surfnet.mujina.util.IDService; -import nl.surfnet.mujina.util.TimeService; -import nl.surfnet.spring.security.opensaml.SAMLMessageHandler; - -public class RealAuthenticationFailureHandler implements AuthenticationFailureHandler { - - - private final static Logger logger = LoggerFactory - .getLogger(RealAuthenticationFailureHandler.class); - - private final TimeService timeService; - private final IDService idService; - private final SigningService signingService; - private final SAMLMessageHandler bindingAdapter; - private final AuthenticationFailureHandler nonSSOAuthnFailureHandler; - - - @Autowired - IdpConfiguration idpConfiguration; - - public RealAuthenticationFailureHandler(TimeService timeService, - IDService idService, - SigningService signingService, - SAMLMessageHandler bindingAdapter, - AuthenticationFailureHandler nonSSOAuthnFailureHandler) { - super(); - this.timeService = timeService; - this.idService = idService; - this.signingService = signingService; - this.bindingAdapter = bindingAdapter; - this.nonSSOAuthnFailureHandler = nonSSOAuthnFailureHandler; - } - - @Override - public void onAuthenticationFailure(HttpServletRequest request, - HttpServletResponse response, - AuthenticationException authenticationException) - throws IOException, ServletException { - logger.debug("commencing RealAuthenticationFailureHandler because of {}", authenticationException.getClass()); - - AuthnRequestInfo authnRequestInfo = (AuthnRequestInfo) request.getSession().getAttribute(AuthnRequestInfo.class.getName()); - - if (authnRequestInfo == null) { - logger.warn("Could not find AuthnRequestInfo on the request. Delegating to nonSSOAuthnFailureHandler."); - nonSSOAuthnFailureHandler.onAuthenticationFailure(request, response, authenticationException); - return; - } - - logger.debug("AuthnRequestInfo is {}", authnRequestInfo); - - request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, authenticationException); - - AuthnResponseGenerator authnResponseGenerator = new AuthnResponseGenerator(signingService, idpConfiguration.getEntityID(), - timeService, idService, idpConfiguration); - EndpointGenerator endpointGenerator = new EndpointGenerator(); - - String acsEndpointURL = authnRequestInfo.getAssertionConsumerURL(); - if (idpConfiguration.getAcsEndpoint() != null) { - acsEndpointURL = idpConfiguration.getAcsEndpoint().getUrl(); - } - - Response authResponse = authnResponseGenerator.generateAuthnResponseFailure(acsEndpointURL, - authnRequestInfo.getAuthnRequestID(), authenticationException); - Endpoint endpoint = endpointGenerator.generateEndpoint(AssertionConsumerService.DEFAULT_ELEMENT_NAME, - acsEndpointURL, null); - - request.getSession().removeAttribute(AuthnRequestInfo.class.getName()); - - String relayState = request.getParameter("RelayState"); - try { - bindingAdapter.sendSAMLMessage(authResponse, endpoint, response, relayState, signingService.getCredential()); - } catch (MessageEncodingException mee) { - logger.error("Exception encoding SAML message", mee); - response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - } - } -} diff --git a/mujina-idp/src/main/java/nl/surfnet/mujina/spring/security/CustomAuthenticationProvider.java b/mujina-idp/src/main/java/nl/surfnet/mujina/spring/security/CustomAuthenticationProvider.java deleted file mode 100644 index f7067210..00000000 --- a/mujina-idp/src/main/java/nl/surfnet/mujina/spring/security/CustomAuthenticationProvider.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012 SURFnet bv, The Netherlands - * - * 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. - */ - -package nl.surfnet.mujina.spring.security; - -import java.util.Arrays; -import java.util.Collection; - -import nl.surfnet.mujina.model.AuthenticationMethod; -import nl.surfnet.mujina.model.IdpConfiguration; -import nl.surfnet.mujina.model.SimpleAuthentication; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.GrantedAuthorityImpl; - -public class CustomAuthenticationProvider implements AuthenticationProvider { - - @Autowired - private IdpConfiguration idpConfiguration; - - @SuppressWarnings("serial") - @Override - public Authentication authenticate(final Authentication authentication) throws AuthenticationException { - final String name = authentication.getName(); - final String password = authentication.getCredentials().toString(); - - /* - * First check if we know this user. Fallback user if Method.ALL otherwise - * an Exception - */ - Authentication authenticationForUser = getAuthenticationForUser(name, password); - if (idpConfiguration.getAuthentication() == AuthenticationMethod.Method.ALL) { - return authenticationForUser != null ? authenticationForUser : new SimpleAuthentication(name, password, Arrays.asList( - (GrantedAuthority) new GrantedAuthorityImpl("ROLE_USER"), (GrantedAuthority) new GrantedAuthorityImpl("ROLE_ADMIN"))); - } else { - if (authenticationForUser == null) { - throw new AuthenticationException("Can not log in") { - }; - } - return authenticationForUser; - - } - } - - private Authentication getAuthenticationForUser(String name, String password) { - final Collection users = idpConfiguration.getUsers(); - for (SimpleAuthentication user : users) { - if (user.getPrincipal().equals(name) && user.getCredentials().equals(password)) { - return user; - } - } - return null; - } - - @SuppressWarnings("rawtypes") - @Override - public boolean supports(final Class method) { - return method.equals(UsernamePasswordAuthenticationToken.class); - } -} diff --git a/mujina-idp/src/main/resources/idp-crt.pem b/mujina-idp/src/main/resources/idp-crt.pem deleted file mode 100644 index 3ce0dbe2..00000000 --- a/mujina-idp/src/main/resources/idp-crt.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICHzCCAYgCCQD7KMJ17XQa7TANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJO -TDEQMA4GA1UECAwHVXRyZWNodDEQMA4GA1UEBwwHVXRyZWNodDEQMA4GA1UECgwH -U3VyZm5ldDEPMA0GA1UECwwGQ29uZXh0MB4XDTEyMDMwODA4NTQyNFoXDTEzMDMw -ODA4NTQyNFowVDELMAkGA1UEBhMCTkwxEDAOBgNVBAgMB1V0cmVjaHQxEDAOBgNV -BAcMB1V0cmVjaHQxEDAOBgNVBAoMB1N1cmZuZXQxDzANBgNVBAsMBkNvbmV4dDCB -nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2slVe459WUDL4RXxJf5h5t5oUbPk -PlFZ9lQysSoS3fnFTdCgzA6FzQzGRDcfRj0HnWBdA1YH+LxBjNcBIJ/nBc7Ssu4e -4rMO3MSAV5Ouo3MaGgHqVq6dCD47f52b98df6QTAA3C+7sHqOdiQ0UDCAK0C+qP5 -LtTcmB8QrJhKmV8CAwEAATANBgkqhkiG9w0BAQUFAAOBgQCvPhO0aSbqX7g7IkR7 -9IFVdJ/P7uSlYFtJ9cMxec85cYLmWL1aVgF5ZFFJqC25blyPJu2GRcSxoVwB3ae8 -sPCECWwqRQA4AHKIjiW5NgrAGYR++ssTOQR8mcAucEBfNaNdlJoy8GdZIhHZNkGl -yHfY8kWS3OWkGzhWSsuRCLl78A== ------END CERTIFICATE----- \ No newline at end of file diff --git a/mujina-idp/src/main/resources/idp-key.key b/mujina-idp/src/main/resources/idp-key.key deleted file mode 100644 index a4dd69b8..00000000 --- a/mujina-idp/src/main/resources/idp-key.key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDayVV7jn1ZQMvhFfEl/mHm3mhRs+Q+UVn2VDKxKhLd+cVN0KDM -DoXNDMZENx9GPQedYF0DVgf4vEGM1wEgn+cFztKy7h7isw7cxIBXk66jcxoaAepW -rp0IPjt/nZv3x1/pBMADcL7uweo52JDRQMIArQL6o/ku1NyYHxCsmEqZXwIDAQAB -AoGAWj78JMgkymEg+AqN+ycQCSQqkbELb+0sl6ApfMynFasGiM+K1EEVTfx79/1o -yBc6gd8S3uJozWASBd9WFrf+mbJWiy+WCSFyEqzIA7kMzyi/Far77B/VxKYv6klL -FQFmvVWqqsGvCUzxCyvEIRyml08RrWrRLltcepEjVxQqGrECQQD1GmHY/aAgzhk2 -jmrqRdBgekyICCLaUBEmNQ36Z+HL8AdIx/MASUgVXgakmunYOESOcnQ9yfNsZRez -a0J71qWJAkEA5INuis0HJKCd/R19oGEuKJUnkAwMiA83gjJI+zHA4YoMtHC+pPZz -kKypauld75ASEk0YOyXHieM90BNNHnV1pwJBAKIIL9lgScSGGzrqyZlYT9oH36Iq -JshGGCA3AKeily3X3yjpLibpSyL9Bs04sBDFmeTFmzzhze/BoPp2lPwDOWkCQQC3 -27ADabeHltvHHgVIFyjGakvssGUcy/GDheYGhh+E2Egknlol7E1LaEDfzmhQKgEA -TJtka59CqF3BnuX7zdIdAkEA4DS8VXAcq1YJkZkz08C4UnyL3jqhOowZUPKNCsqE -JeMwkgw7TBG/TRBccbyOzTY4HWYdUSq82eSQgFEHHaxECQ== ------END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/mujina-idp/src/main/resources/idp-key.pkcs8.der b/mujina-idp/src/main/resources/idp-key.pkcs8.der deleted file mode 100644 index 5b103444a84b57310efff97daa748bfef699d997..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 636 zcmV-?0)zc9f&zE~0RS)!1_>&LNQUpVlaXNUIGCC0)c@5+R0UWj(u4` z%i$IACH`UN-e^&?)(7aK7%r>N(hu(Lllg ztpfU^`7YGlm>&?Vm`a&n0s{d60Rn-5T0ZHr28hp!)Ik+Z{CoHPXvh~jf!`9|;%Loa5(VE@7PtPHvQ~>PmI)zp60FDrxeU)J zzZI(c>>t&{rZ4JAOBDfTy;Z8J!LJES@e3=&AsnWcPZ6zZ(JotDdXXbn6e=3A0zm-v z8e!P|pdii}HjZlQMbKb+Oo#{~+E5WDH4XY_;mhy`NXPR4Nk|o52Bezl*f>Ova&$e( z^K4}ovui?o)}@I8K>*}~Zi>wZB%q!B9eto-E+~~JkPHln4>y7`Nc%Cs;ff5jaK5DW zbC9g5YUy3?kP;G27&|4$iQ_%c6HOj7rZX#zn2x7)A-X}5=# z+s7USNEax^YD?^}WgN@#gN5b>h9893NF<(GCG1U0Xh7f2XizEv08E=?Yo9`>UBRB^ z`_0lF0zm-aG`v-C9II9dk(o2oz_?O;i{3h+I*b`m@{J10geBuJk_tV9XIG#Zuw diff --git a/mujina-idp/src/main/webapp/META-INF/MANIFEST.MF b/mujina-idp/src/main/webapp/META-INF/MANIFEST.MF deleted file mode 100644 index 5e949512..00000000 --- a/mujina-idp/src/main/webapp/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/mujina-idp/src/main/webapp/WEB-INF/api-servlet.xml b/mujina-idp/src/main/webapp/WEB-INF/api-servlet.xml deleted file mode 100644 index d4ae0a07..00000000 --- a/mujina-idp/src/main/webapp/WEB-INF/api-servlet.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mujina-idp/src/main/webapp/WEB-INF/applicationContext-idp-config.xml b/mujina-idp/src/main/webapp/WEB-INF/applicationContext-idp-config.xml deleted file mode 100644 index 505362f6..00000000 --- a/mujina-idp/src/main/webapp/WEB-INF/applicationContext-idp-config.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - classpath - - org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mujina-idp/src/main/webapp/WEB-INF/applicationContext-property-mappings.xml b/mujina-idp/src/main/webapp/WEB-INF/applicationContext-property-mappings.xml deleted file mode 100644 index 685a5def..00000000 --- a/mujina-idp/src/main/webapp/WEB-INF/applicationContext-property-mappings.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - diff --git a/mujina-idp/src/main/webapp/WEB-INF/applicationContext-spring-security.xml b/mujina-idp/src/main/webapp/WEB-INF/applicationContext-spring-security.xml deleted file mode 100644 index c125ac15..00000000 --- a/mujina-idp/src/main/webapp/WEB-INF/applicationContext-spring-security.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mujina-idp/src/main/webapp/WEB-INF/web.xml b/mujina-idp/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 60f38ba5..00000000 --- a/mujina-idp/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - spring-saml-idp - - - nl.iprofs.modules.contextlogging.InitParameterLogbackContextListener - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - - springSecurityFilterChain - /* - REQUEST - FORWARD - - - - org.springframework.web.context.ContextLoaderListener - - - - - org.springframework.security.web.session.HttpSessionEventPublisher - - - - - contextConfigLocation - /WEB-INF/applicationContext*.xml - - - - singleSignOnService - org.springframework.web.context.support.HttpRequestHandlerServlet - - - - authnResponder - org.springframework.web.context.support.HttpRequestHandlerServlet - - - - ssoSuccessLogoutResponder - org.springframework.web.context.support.HttpRequestHandlerServlet - - - - api - org.springframework.web.servlet.DispatcherServlet - 1 - - - - singleSignOnService - /SingleSignOnService - - - - authnResponder - /AuthnResponder - - - - ssoSuccessLogoutResponder - /LogoutResponder - - - - api - /api/* - - - - index.jsp - - diff --git a/mujina-idp/src/main/webapp/admin.jsp b/mujina-idp/src/main/webapp/admin.jsp deleted file mode 100644 index b2b107a6..00000000 --- a/mujina-idp/src/main/webapp/admin.jsp +++ /dev/null @@ -1,64 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8" %> -<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> - -<%-- - Copyright 2012 SURFnet bv, The Netherlands - - 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. - --%> - - - - - - Mujina - - - -
-___  ___        _  _
-|  \/  |       (_)(_)
-| .  . | _   _  _  _  _ __    __ _
-| |\/| || | | || || || '_ \  / _` |
-| |  | || |_| || || || | | || (_| |
-\_|  |_/ \__,_|| ||_||_| |_| \__,_|
-              _/ |
-             |__/
-
-          Identity Provider
-
-
- -

Identity Provider Admin Page

- -

This page is secured. You must have the ROLE_ADMIN authority to be here.

- -unprotected home page
-protected user page
-End your session with the Identity Provider
- -

Your current Spring Security Credentials are:

- -

Authentication Principal is:

- -

-

Authentication Credentials are:

- -

-

Authentication Details are:

- -

- - - diff --git a/mujina-idp/src/main/webapp/available_attributes.json b/mujina-idp/src/main/webapp/available_attributes.json deleted file mode 100644 index 0d0b6098..00000000 --- a/mujina-idp/src/main/webapp/available_attributes.json +++ /dev/null @@ -1,86 +0,0 @@ -var available_attributes = { - "urn:mace:dir:attribute-def:eduPersonTargetedID" : { - desc : "ID (or NameId)" - }, - "urn:oid:1.3.6.1.4.1.5923.1.1.1.10" : { - desc : "ID (or NameId)" - }, - "urn:mace:dir:attribute-def:sn" : { - desc : "Surname" - }, - "urn:oid:2.5.4.4" : { - desc : "Surname" - }, - "urn:mace:dir:attribute-def:givenName" : { - desc : "given name" - }, - "urn:oid:2.5.4.42" : { - desc : "given name" - }, - "urn:mace:dir:attribute-def:cn" : { - desc : "common name" - }, - "urn:oid:2.5.4.3" : { - desc : "common name" - }, - "urn:mace:dir:attribute-def:displayName" : { - desc : "display name" - }, - "urn:oid:2.16.840.1.113730.3.1.241" : { - desc : "display name" - }, - "urn:mace:dir:attribute-def:mail" : { - desc : "email address" - }, - "urn:oid:0.9.2342.19200300.100.1.3" : { - desc : "email address" - }, - "urn:mace:terena.org:attribute-def:schacHomeOrganization" : { - desc : "organization" - }, - "urn:oid:1.3.6.1.4.1.25178.1.2.9" : { - desc : "organization" - }, - "urn:mace:terena.org:attribute-def:schacHomeOrganizationType" : { - desc : "organization type" - }, - "urn:oid:1.3.6.1.4.1.25178.1.2.10" : { - desc : "organization type" - }, - "urn:mace:dir:attribute-def:eduPersonAffiliation" : { - desc : "affiliation" - }, - "urn:oid:1.3.6.1.4.1.5923.1.1.1.1" : { - desc : "affiliation" - }, - "urn:mace:dir:attribute-def:eduPersonEntitlement" : { - desc : "entitlement" - }, - "urn:oid:1.3.6.1.4.1.5923.1.1.1.7" : { - desc : "entitlement" - }, - "urn:mace:dir:attribute-def:eduPersonPrincipalName" : { - desc : "principalname" - }, - "urn:oid:1.3.6.1.4.1.5923.1.1.1.6" : { - desc : "principalname" - }, - "urn:mace:dir:attribute-def:isMemberOf" : { - desc : "isMemberOf" - }, - "urn:oid:1.3.6.1.4.1.5923.1.5.1.1" : { - desc : "isMemberOf" - }, - "urn:mace:dir:attribute-def:uid" : { - desc : "UID" - }, - "urn:oid:0.9.2342.19200300.100.1.1" : { - desc : "UID" - }, - "urn:mace:dir:attribute-def:preferredLanguage" : { - desc : "preferredLanguage" - }, - "urn:oid:2.16.840.1.113730.3.1.39" : { - desc : "preferredLanguage" - } -} \ No newline at end of file diff --git a/mujina-idp/src/main/webapp/edit_attr.jsp b/mujina-idp/src/main/webapp/edit_attr.jsp deleted file mode 100644 index 23fa9403..00000000 --- a/mujina-idp/src/main/webapp/edit_attr.jsp +++ /dev/null @@ -1,127 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8" %> -<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> - -<%-- - Copyright 2012 SURFnet bv, The Netherlands - - 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. - --%> - - - - - - Mujina - - - -
-___  ___        _  _
-|  \/  |       (_)(_)
-| .  . | _   _  _  _  _ __    __ _
-| |\/| || | | || || || '_ \  / _` |
-| |  | || |_| || || || | | || (_| |
-\_|  |_/ \__,_|| ||_||_| |_| \__,_|
-              _/ |
-             |__/
-
-          Identity Provider
-
-
-

Identity Provider Attribute Editor

-
- -
- -
- -- Remove Entire Cookie -- Back to Home --  - - - - - - diff --git a/mujina-idp/src/main/webapp/index.jsp b/mujina-idp/src/main/webapp/index.jsp deleted file mode 100644 index 04fcca1d..00000000 --- a/mujina-idp/src/main/webapp/index.jsp +++ /dev/null @@ -1,62 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8" %> -<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> - -<%-- - Copyright 2012 SURFnet bv, The Netherlands - - 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. - --%> - - - - - - Identity Provider Home Page - - - -
-___  ___        _  _
-|  \/  |       (_)(_)
-| .  . | _   _  _  _  _ __    __ _
-| |\/| || | | || || || '_ \  / _` |
-| |  | || |_| || || || | | || (_| |
-\_|  |_/ \__,_|| ||_||_| |_| \__,_|
-              _/ |
-             |__/
-
-          Identity Provider
-
- -

This page is not secured.

- -protected IDP user page
-protected IDP admin page
-End your session with the Identity Provider
-Edit the attributes that are stored in the browsers cookie - -

Your current Spring Security Credentials are:

- -

Authentication Principal is:

- -

-

Authentication Credentials are:

- -

-

Authentication Details are:

- -

- - - diff --git a/mujina-idp/src/main/webapp/js/jquery-2.0.3.min.js b/mujina-idp/src/main/webapp/js/jquery-2.0.3.min.js deleted file mode 100644 index 2be209dd..00000000 --- a/mujina-idp/src/main/webapp/js/jquery-2.0.3.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license -//@ sourceMappingURL=jquery-2.0.3.min.map -*/ -(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) -};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("