From d9d5573aa4a5c9479a6d46265f425c8d770c90fc Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 5 Feb 2017 15:02:10 -0500 Subject: [PATCH 01/76] GUACAMOLE-197: Initial code for the guacamole-auth-radius authentication module. --- extensions/guacamole-auth-radius/.gitignore | 3 + extensions/guacamole-auth-radius/pom.xml | 264 +++++++++++++++++ .../src/licenses/DISCLAIMER | 7 + .../src/licenses/LICENSE | 274 ++++++++++++++++++ .../guacamole-auth-radius/src/licenses/NOTICE | 5 + .../src/licenses/bundled/README | 4 + .../licenses/bundled/aopalliance-1.0/LICENSE | 4 + .../licenses/bundled/duo-java-56570d1/LICENSE | 25 ++ .../src/licenses/bundled/guice-3.0/COPYING | 202 +++++++++++++ .../bundled/javax.inject-1/LICENSE-2.0.txt | 202 +++++++++++++ .../src/main/assembly/dist.xml | 53 ++++ .../radius/AuthenticationProviderService.java | 147 ++++++++++ .../auth/radius/ConfigurationService.java | 145 +++++++++ .../radius/RadiusAuthenticationProvider.java | 98 +++++++ .../RadiusAuthenticationProviderModule.java | 81 ++++++ .../auth/radius/RadiusConnectionService.java | 233 +++++++++++++++ .../radius/RadiusGuacamoleProperties.java | 112 +++++++ .../form/RadiusChallengeResponseField.java | 55 ++++ .../auth/radius/user/AuthenticatedUser.java | 68 +++++ .../src/main/resources/config/radiusConfig.js | 34 +++ .../controllers/guacRadiusController.js | 36 +++ .../src/main/resources/guac-manifest.json | 28 ++ .../src/main/resources/license.txt | 18 ++ .../src/main/resources/radiusModule.js | 31 ++ .../src/main/resources/styles/radius.css | 43 +++ .../radiusChallengeResponseField.html | 9 + .../src/main/resources/translations/en.json | 14 + pom.xml | 1 + 28 files changed, 2196 insertions(+) create mode 100644 extensions/guacamole-auth-radius/.gitignore create mode 100644 extensions/guacamole-auth-radius/pom.xml create mode 100644 extensions/guacamole-auth-radius/src/licenses/DISCLAIMER create mode 100644 extensions/guacamole-auth-radius/src/licenses/LICENSE create mode 100644 extensions/guacamole-auth-radius/src/licenses/NOTICE create mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/README create mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/aopalliance-1.0/LICENSE create mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE create mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/guice-3.0/COPYING create mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/javax.inject-1/LICENSE-2.0.txt create mode 100644 extensions/guacamole-auth-radius/src/main/assembly/dist.xml create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java create mode 100644 extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js create mode 100644 extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js create mode 100644 extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json create mode 100644 extensions/guacamole-auth-radius/src/main/resources/license.txt create mode 100644 extensions/guacamole-auth-radius/src/main/resources/radiusModule.js create mode 100644 extensions/guacamole-auth-radius/src/main/resources/styles/radius.css create mode 100644 extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html create mode 100644 extensions/guacamole-auth-radius/src/main/resources/translations/en.json diff --git a/extensions/guacamole-auth-radius/.gitignore b/extensions/guacamole-auth-radius/.gitignore new file mode 100644 index 000000000..1de9633ae --- /dev/null +++ b/extensions/guacamole-auth-radius/.gitignore @@ -0,0 +1,3 @@ +src/main/resources/generated/ +target/ +*~ diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml new file mode 100644 index 000000000..e9d5b5ca7 --- /dev/null +++ b/extensions/guacamole-auth-radius/pom.xml @@ -0,0 +1,264 @@ + + + + + 4.0.0 + org.apache.guacamole + guacamole-auth-radius + jar + 0.9.11-incubating + guacamole-auth-radius + http://guacamole.incubator.apache.org/ + + + UTF-8 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.6 + 1.6 + + -Xlint:all + -Werror + + true + + + + + + com.keithbranton.mojo + angular-maven-plugin + 0.3.2 + + + generate-resources + + html2js + + + + + ${basedir}/src/main/resources + **/*.html + ${basedir}/src/main/resources/generated/templates-main/templates.js + app/ext/radius + + + + + + com.samaxes.maven + minify-maven-plugin + 1.7.5 + + + default-cli + + UTF-8 + + ${basedir}/src/main/resources + ${project.build.directory}/classes + + / + / + radius.css + + + license.txt + + + + **/*.css + + + / + / + radius.js + + + license.txt + + + + **/*.js + + + + + **/*.test.js + + CLOSURE + + + + OFF + OFF + + + + + minify + + + + + + + + + maven-assembly-plugin + 2.5.3 + + ${project.artifactId}-${project.version} + false + + src/main/assembly/dist.xml + + + + + make-dist-archive + package + + single + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.10 + + + unpack-dependencies + prepare-package + + unpack-dependencies + + + runtime + ${project.build.directory}/classes + + + + + + + + org.apache.rat + apache-rat-plugin + 0.12 + + + + **/*.json + src/licenses/**/* + src/main/resources/templates/*.html + + + + + + + validate + validate + + check + + + + + + + + + + + + + + org.apache.guacamole + guacamole-common + 0.9.10-incubating + provided + + + + + org.apache.guacamole + guacamole-ext + 0.9.11-incubating + provided + + + + + com.google.inject + guice + 3.0 + + + com.google.inject.extensions + guice-multibindings + 3.0 + + + + + javax.servlet + servlet-api + 2.5 + provided + + + + + + net.jradius + jradius-core + 1.1.5 + + + + + net.jradius + jradius-dictionary + 1.1.5 + + + + + + diff --git a/extensions/guacamole-auth-radius/src/licenses/DISCLAIMER b/extensions/guacamole-auth-radius/src/licenses/DISCLAIMER new file mode 100644 index 000000000..1a9c3be8d --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/DISCLAIMER @@ -0,0 +1,7 @@ +Apache Guacamole is an effort undergoing incubation at The Apache Software +Foundation (ASF). Incubation is required of all newly accepted projects until a +further review indicates that the infrastructure, communications, and decision +making process have stabilized in a manner consistent with other successful ASF +projects. While incubation status is not necessarily a reflection of the +completeness or stability of the code, it does indicate that the project has +yet to be fully endorsed by the ASF. diff --git a/extensions/guacamole-auth-radius/src/licenses/LICENSE b/extensions/guacamole-auth-radius/src/licenses/LICENSE new file mode 100644 index 000000000..4ae92c4fe --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/LICENSE @@ -0,0 +1,274 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +============================================================================== + +APACHE GUACAMOLE SUBCOMPONENTS + +Apache Guacamole includes a number of subcomponents with separate copyright +notices and license terms. Your use of these subcomponents is subject to the +terms and conditions of the following licenses. + + +AOP Alliance (http://aopalliance.sourceforge.net/) +-------------------------------------------------- + + Version: 1.0 + From: 'AOP Alliance' (http://aopalliance.sourceforge.net/members.html) + License(s): + Public Domain (bundled/aopalliance-1.0/LICENSE) + + +DuoWeb Java SDK (https://github.com/duosecurity/duo_java) +--------------------------------------------------------- + + Verson: commit 56570d18a1f98642500e6c1158a3f41e448963ff + From: `Duo Security, Inc.' (https://duo.com/) + License(s): + BSD 3-clause (bundled/duo-java-56570d1/LICENSE) + +Copyright (c) 2011, Duo Security, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Google Guice (https://github.com/google/guice) +---------------------------------------------- + + Version: 3.0 + From: 'Google Inc.' (http://www.google.com/) + License(s): + Apache v2.0 (bundled/guice-3.0/COPYING) + + +JSR-330 / Dependency Injection for Java (http://code.google.com/p/atinject/) +---------------------------------------------------------------------------- + + Version: 1 + From: 'JSR-330 Expert Group' (https://jcp.org/en/jsr/detail?id=330) + License(s): + Apache v2.0 (bundled/javax.inject-1/LICENSE-2.0.txt) + diff --git a/extensions/guacamole-auth-radius/src/licenses/NOTICE b/extensions/guacamole-auth-radius/src/licenses/NOTICE new file mode 100644 index 000000000..2ef7e548b --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/NOTICE @@ -0,0 +1,5 @@ +Apache Guacamole +Copyright 2016 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/README b/extensions/guacamole-auth-radius/src/licenses/bundled/README new file mode 100644 index 000000000..47ba19db0 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/bundled/README @@ -0,0 +1,4 @@ +Apache Guacamole includes a number of subcomponents with separate copyright +notices and license terms. Your use of these subcomponents is subject to the +terms and conditions of their respective licenses, included within this +directory for reference. diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/aopalliance-1.0/LICENSE b/extensions/guacamole-auth-radius/src/licenses/bundled/aopalliance-1.0/LICENSE new file mode 100644 index 000000000..8e0e3786b --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/bundled/aopalliance-1.0/LICENSE @@ -0,0 +1,4 @@ +From http://aopalliance.sourceforge.net/: + + LICENCE: all the source code provided by AOP Alliance is Public Domain. + diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE b/extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE new file mode 100644 index 000000000..66e1f74d5 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2011, Duo Security, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/guice-3.0/COPYING b/extensions/guacamole-auth-radius/src/licenses/bundled/guice-3.0/COPYING new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/bundled/guice-3.0/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/javax.inject-1/LICENSE-2.0.txt b/extensions/guacamole-auth-radius/src/licenses/bundled/javax.inject-1/LICENSE-2.0.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/bundled/javax.inject-1/LICENSE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/extensions/guacamole-auth-radius/src/main/assembly/dist.xml b/extensions/guacamole-auth-radius/src/main/assembly/dist.xml new file mode 100644 index 000000000..b89fd534c --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/assembly/dist.xml @@ -0,0 +1,53 @@ + + + + + dist + ${project.artifactId}-${project.version} + + + + tar.gz + + + + + + + + + src/licenses + + + + + target + + + *.jar + + + + + + diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java new file mode 100644 index 000000000..d803af6af --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import java.util.Collections; +import org.apache.guacamole.auth.radius.user.AuthenticatedUser; +import org.apache.guacamole.auth.radius.form.RadiusChallengeResponseField; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.form.Field; +import org.apache.guacamole.net.auth.Credentials; +import org.apache.guacamole.net.auth.credentials.CredentialsInfo; +import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException; +import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import net.jradius.exception.UnknownAttributeException; +import net.jradius.packet.RadiusPacket; +import net.jradius.packet.AccessAccept; +import net.jradius.packet.AccessChallenge; +import net.jradius.packet.AccessReject; +import net.jradius.packet.AccessRequest; +import net.jradius.packet.AccessResponse; +import net.jradius.packet.attribute.RadiusAttribute; + +/** + * Service providing convenience functions for the RADIUS AuthenticationProvider + * implementation. + * + * @author Michael Jumper + */ +public class AuthenticationProviderService { + + /** + * Logger for this class. + */ + private final Logger logger = LoggerFactory.getLogger(AuthenticationProviderService.class); + + /** + * Service for creating and managing connections to RADIUS servers. + */ + @Inject + private RadiusConnectionService radiusService; + + /** + * Service for retrieving RADIUS server configuration information. + */ + @Inject + private ConfigurationService confService; + + /** + * Provider for AuthenticatedUser objects. + */ + @Inject + private Provider authenticatedUserProvider; + + /** + * Returns an AuthenticatedUser representing the user authenticated by the + * given credentials. + * + * @param credentials + * The credentials to use for authentication. + * + * @return + * An AuthenticatedUser representing the user authenticated by the + * given credentials. + * + * @throws GuacamoleException + * If an error occurs while authenticating the user, or if access is + * denied. + */ + public AuthenticatedUser authenticateUser(Credentials credentials) + throws GuacamoleException { + + // Attempt bind + RadiusPacket radPack; + try { + radPack = radiusService.authenticate(credentials.getUsername(), + credentials.getPassword()); + } + catch (GuacamoleException e) { + logger.error("Cannot configure RADIUS server: {}", e.getMessage()); + logger.debug("Error configuring RADIUS server.", e); + radPack = null; + } + + // If configure fails, permission to login is denied + if(radPack == null) { + logger.debug("Nothing in the RADIUS packet."); + throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); + } + else if(radPack instanceof AccessReject) { + logger.debug("Login has been rejected by RADIUS server."); + throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); + } + else if(radPack instanceof AccessChallenge) { + try { + String replyMsg = radPack.getAttributeValue("Reply-Message").toString(); + String radState = radPack.getAttributeValue("State").toString(); + logger.debug("RADIUS sent challenge response: {}", replyMsg); + logger.debug("RADIUS sent state: {}", radState); + Field radiusResponseField = new RadiusChallengeResponseField(replyMsg, radState); + CredentialsInfo responseCredentials = new CredentialsInfo(Collections.singletonList(radiusResponseField)); + throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", responseCredentials); + } + catch(UnknownAttributeException e) { + logger.error("Error in talks with RADIUS server."); + logger.debug("RADIUS challenged by didn't provide right attributes."); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } + } + else if(radPack instanceof AccessAccept) { + try { + + // Return AuthenticatedUser if bind succeeds + AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); + authenticatedUser.init(credentials); + return authenticatedUser; + } + finally { + radiusService.disconnect(); + } + } + else + throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); + + } + +} diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java new file mode 100644 index 000000000..d30e33489 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -0,0 +1,145 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius; + +import com.google.inject.Inject; +import java.util.Collections; +import java.util.List; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.environment.Environment; + +/** + * Service for retrieving configuration information regarding the RADIUS server. + * + * @author Michael Jumper + */ +public class ConfigurationService { + + /** + * The Guacamole server environment. + */ + @Inject + private Environment environment; + + /** + * Returns the hostname of the RADIUS server as configured with + * guacamole.properties. By default, this will be "localhost". + * + * @return + * The hostname of the RADIUS server, as configured with + * guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ + public String getRadiusServer() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_SERVER, + "localhost" + ); + } + + /** + * Returns the authentication port of the RADIUS server configured with + * guacamole.properties. + * + * @return + * The authentication port of the RADIUS server, as configured with + * guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ + public int getRadiusAuthPort() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_AUTH_PORT, + 1812 + ); + } + + /** + * Returns the accounting port of the RADIUS server configured with + * guacamole.properties. + * + * @return + * The accouting port of the RADIUS server, as configured with + * guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ + public int getRadiusAcctPort() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_ACCT_PORT, + 1813 + ); + } + + /** + * Returns the shared secret of the RADIUS server configured with + * guacamole.properties. + * + * @return + * The shared secret of the RADIUS server, as configured with + * guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ + public String getRadiusSharedSecret() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_SHARED_SECRET, + null + ); + } + + /** + * Returns the authentication protocol of the RADIUS server + * from guacamole.properties. + * + * @return + * The authentication protocol of the RADIUS server, + * from guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ + public String getRadiusAuthProtocol() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_AUTH_PROTOCOL, + null + ); + } + + public int getRadiusRetries() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_RETRIES, + 5 + ); + } + + public int getRadiusTimeout() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_TIMEOUT, + 60 + ); + } + +} diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java new file mode 100644 index 000000000..461eb0a1a --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius; + + +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.net.auth.AuthenticatedUser; +import org.apache.guacamole.net.auth.AuthenticationProvider; +import org.apache.guacamole.net.auth.Credentials; +import org.apache.guacamole.net.auth.UserContext; + +/** + * Allows users to be authenticated against an RADIUS server. Each user may have + * any number of authorized configurations. Authorized configurations may be + * shared. + * + * @author Michael Jumper + */ +public class RadiusAuthenticationProvider implements AuthenticationProvider { + + /** + * Injector which will manage the object graph of this authentication + * provider. + */ + private final Injector injector; + + /** + * Creates a new RadiusAuthenticationProvider that authenticates users + * against an RADIUS service. + * + * @throws GuacamoleException + * If a required property is missing, or an error occurs while parsing + * a property. + */ + public RadiusAuthenticationProvider() throws GuacamoleException { + + // Set up Guice injector. + injector = Guice.createInjector( + new RadiusAuthenticationProviderModule(this) + ); + + } + + @Override + public String getIdentifier() { + return "radius"; + } + + @Override + public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { + + AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class); + return authProviderService.authenticateUser(credentials); + + } + + @Override + public AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser, + Credentials credentials) throws GuacamoleException { + return authenticatedUser; + } + + @Override + public UserContext getUserContext(AuthenticatedUser authenticatedUser) + throws GuacamoleException { + + return null; + + } + + @Override + public UserContext updateUserContext(UserContext context, + AuthenticatedUser authenticatedUser, + Credentials credentials) throws GuacamoleException { + return context; + } + +} + diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java new file mode 100644 index 000000000..af6d02de6 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius; + +import com.google.inject.AbstractModule; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.environment.Environment; +import org.apache.guacamole.environment.LocalEnvironment; +import org.apache.guacamole.net.auth.AuthenticationProvider; + +/** + * Guice module which configures RADIUS-specific injections. + * + * @author Michael Jumper + */ +public class RadiusAuthenticationProviderModule extends AbstractModule { + + /** + * Guacamole server environment. + */ + private final Environment environment; + + /** + * A reference to the RadiusAuthenticationProvider on behalf of which this + * module has configured injection. + */ + private final AuthenticationProvider authProvider; + + /** + * Creates a new RADIUS authentication provider module which configures + * injection for the RadiusAuthenticationProvider. + * + * @param authProvider + * The AuthenticationProvider for which injection is being configured. + * + * @throws GuacamoleException + * If an error occurs while retrieving the Guacamole server + * environment. + */ + public RadiusAuthenticationProviderModule(AuthenticationProvider authProvider) + throws GuacamoleException { + + // Get local environment + this.environment = new LocalEnvironment(); + + // Store associated auth provider + this.authProvider = authProvider; + + } + + @Override + protected void configure() { + + // Bind core implementations of guacamole-ext classes + bind(AuthenticationProvider.class).toInstance(authProvider); + bind(Environment.class).toInstance(environment); + + // Bind RADIUS-specific services + bind(ConfigurationService.class); + bind(RadiusConnectionService.class); + + } + +} diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java new file mode 100644 index 000000000..0357fbe76 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius; + +import com.google.inject.Inject; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.NoSuchAlgorithmException; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleUnsupportedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import net.jradius.client.RadiusClient; +import net.jradius.exception.RadiusException; +import net.jradius.packet.RadiusPacket; +import net.jradius.packet.AccessRequest; +import net.jradius.dictionary.*; +import net.jradius.packet.attribute.AttributeList; +import net.jradius.client.auth.RadiusAuthenticator; +import net.jradius.packet.attribute.AttributeFactory; + +/** + * Service for creating and managing connections to RADIUS servers. + * + * @author Michael Jumper + */ +public class RadiusConnectionService { + + /** + * Logger for this class. + */ + private final Logger logger = LoggerFactory.getLogger(RadiusConnectionService.class); + + /** + * Service for retrieving RADIUS server configuration information. + */ + @Inject + private ConfigurationService confService; + + + /** + * The RADIUS client; + */ + private RadiusClient radiusClient; + + /** + * Creates a new instance of RadiusConnection, configured as required to use + * whichever encryption method is requested within guacamole.properties. + * + * @return + * A new RadiusConnection instance which has already been configured to + * use the encryption method requested within guacamole.properties. + * + * @throws GuacamoleException + * If an error occurs while parsing guacamole.properties, or if the + * requested encryption method is actually not implemented (a bug). + */ + private void createRadiusConnection() { + + /* + // Map encryption method to proper connection and socket factory + EncryptionMethod encryptionMethod = confService.getEncryptionMethod(); + switch (encryptionMethod) { + + // Unencrypted RADIUS connection + case NONE: + logger.debug("Connection to RADIUS server without encryption."); + radiusClient = new RadiusClient(); + return radiusClient; + + // Radius over TTLS (EAP-TTLS) + case TTLS: + logger.debug("Connecting to RADIUS server using TTLS."); + radiusClient = new RadiusClient(); + return radiusClient; + + // We default to unencrypted connections. + default: + logger.debug("Defaulting an unencrypted RADIUS connection."); + radiusClient = new RadiusClient(); + return radiusClient; + + } + */ + try { + radiusClient = new RadiusClient(InetAddress.getByName(confService.getRadiusServer()), + confService.getRadiusSharedSecret(), + confService.getRadiusAuthPort(), + confService.getRadiusAcctPort(), + confService.getRadiusTimeout()); + } + catch (GuacamoleException e) { + logger.error("Unable to initialize RADIUS client: {}", e.getMessage()); + logger.debug("Failed to init RADIUS client.", e); + return; + } + catch (UnknownHostException e) { + logger.error("Unable to resolve host: {}", e.getMessage()); + logger.debug("Failed to resolve host.", e); + return; + } + catch (IOException e) { + logger.error("Unable to communicate with host: {}", e.getMessage()); + logger.debug("Failed to communicate with host.", e); + return; + } + + } + + public RadiusPacket authenticate(String username, String password) + throws GuacamoleException { + + createRadiusConnection(); + AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); + + if(radiusClient == null) + return null; + + if(username == null || username.isEmpty()) { + logger.warn("Anonymous access not allowed with RADIUS client."); + return null; + } + if(password == null || password.isEmpty()) { + logger.warn("Password required for RADIUS authentication."); + return null; + } + + RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); + if(radAuth == null) + throw new GuacamoleException("Unknown RADIUS authentication protocol."); + try { + AttributeList radAttrs = new AttributeList(); + radAttrs.add(new Attr_UserName(username)); + radAttrs.add(new Attr_UserPassword(password)); + AccessRequest radAcc = new AccessRequest(radiusClient, radAttrs); + logger.debug("Sending authentication request to radius server for user {}.", username); + radAuth.setupRequest(radiusClient, radAcc); + radAuth.processRequest(radAcc); + return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + } + catch (RadiusException e) { + logger.error("Unable to complete authentication.", e.getMessage()); + logger.debug("Authentication with RADIUS failed.", e); + return null; + } + catch (NoSuchAlgorithmException e) { + logger.error("No such RADIUS algorithm: {}", e.getMessage()); + logger.debug("Unknown RADIUS algorithm.", e); + return null; + } + } + + public RadiusPacket authenticate(String username, String state, String response) + throws GuacamoleException { + + createRadiusConnection(); + AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); + + if(radiusClient == null) + return null; + + if(username == null || username.isEmpty()) { + logger.warn("Anonymous access not allowed with RADIUS client."); + return null; + } + if(state == null || state.isEmpty()) { + logger.warn("This method needs a previous RADIUS state to respond to."); + return null; + } + if(response == null || response.isEmpty()) { + logger.warn("Response required for RADIUS authentication."); + return null; + } + + RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); + if(radAuth == null) + throw new GuacamoleException("Unknown RADIUS authentication protocol."); + try { + AttributeList radAttrs = new AttributeList(); + radAttrs.add(new Attr_UserName(username)); + radAttrs.add(new Attr_State(state)); + radAttrs.add(new Attr_UserPassword(response)); + AccessRequest radAcc = new AccessRequest(radiusClient, radAttrs); + logger.debug("Sending authentication response to radius server for user {}.", username); + radAuth.setupRequest(radiusClient, radAcc); + radAuth.processRequest(radAcc); + return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + } + catch (RadiusException e) { + logger.error("Unable to complete authentication.", e.getMessage()); + logger.debug("Authentication with RADIUS failed.", e); + return null; + } + catch (NoSuchAlgorithmException e) { + logger.error("No such RADIUS algorithm: {}", e.getMessage()); + logger.debug("Unknown RADIUS algorithm.", e); + return null; + } + } + + /** + * Disconnects the given RADIUS connection, logging any failure to do so + * appropriately. + * + * @param radiusConnection + * The RADIUS connection to disconnect. + */ + public void disconnect() { + + radiusClient.close(); + + } + +} diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java new file mode 100644 index 000000000..02b9df72b --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius; + +import org.apache.guacamole.properties.IntegerGuacamoleProperty; +import org.apache.guacamole.properties.StringGuacamoleProperty; + + +/** + * Provides properties required for use of the RADIUS authentication provider. + * These properties will be read from guacamole.properties when the RADIUS + * authentication provider is used. + * + * @author Michael Jumper + */ +public class RadiusGuacamoleProperties { + + /** + * This class should not be instantiated. + */ + private RadiusGuacamoleProperties() {} + + /** + * The port on the RADIUS server to connect to when authenticating users. + */ + public static final IntegerGuacamoleProperty RADIUS_AUTH_PORT = new IntegerGuacamoleProperty() { + + @Override + public String getName() { return "radius-auth-port"; } + + }; + + /** + * The port on the RADIUS server to connect to when accounting users. + */ + public static final IntegerGuacamoleProperty RADIUS_ACCT_PORT = new IntegerGuacamoleProperty() { + + @Override + public String getName() { return "radius-acct-port"; } + + }; + + + /** + * The hostname or ip of the RADIUS server to connect to when authenticating users. + */ + public static final StringGuacamoleProperty RADIUS_SERVER = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-server"; } + + }; + + /** + * The shared secret of the RADIUS server to connect to when authenticating users. + */ + public static final StringGuacamoleProperty RADIUS_SHARED_SECRET = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-shared-secret"; } + + }; + + /** + * The authentication protocol of the RADIUS server to connect to when authenticating users. + */ + public static final StringGuacamoleProperty RADIUS_AUTH_PROTOCOL = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-auth-protocol"; } + + }; + + /** + * The number of retries when attempting a radius packet transaction. + */ + public static final IntegerGuacamoleProperty RADIUS_RETRIES = new IntegerGuacamoleProperty() { + + @Override + public String getName() { return "radius-retries"; } + + }; + + /** + * The network timeout when attempting a radius packet transaction. + */ + public static final IntegerGuacamoleProperty RADIUS_TIMEOUT = new IntegerGuacamoleProperty() { + + @Override + public String getName() { return "radius-timeout"; } + + }; + + +} diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java new file mode 100644 index 000000000..4721d6175 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius.form; + +import org.apache.guacamole.form.Field; +import org.codehaus.jackson.annotate.JsonProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RadiusChallengeResponseField extends Field { + + /** + * Logger for this class. + */ + private final Logger logger = LoggerFactory.getLogger(RadiusChallengeResponseField.class); + + private static final String RADIUS_FIELD_NAME = "guac-radius-challenge-response"; + private static final String RADIUS_FIELD_TYPE = "GUAC_RADIUS_CHALLENGE_RESPONSE"; + private final String radiusState; + private final String replyMsg; + + public RadiusChallengeResponseField(String replyMsg, String radiusState) { + super(RADIUS_FIELD_NAME, RADIUS_FIELD_TYPE); + logger.debug("Initializing the RADIUS challenge/response field: {}", replyMsg); + + this.replyMsg = replyMsg; + this.radiusState = radiusState; + + } + + public String getRadiusState() { + return radiusState; + } + + public String getReplyMsg() { + return replyMsg; + } +} diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java new file mode 100644 index 000000000..d4d55b98e --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius.user; + +import com.google.inject.Inject; +import org.apache.guacamole.net.auth.AbstractAuthenticatedUser; +import org.apache.guacamole.net.auth.AuthenticationProvider; +import org.apache.guacamole.net.auth.Credentials; + +/** + * An RADIUS-specific implementation of AuthenticatedUser, associating a + * particular set of credentials with the RADIUS authentication provider. + * + * @author Michael Jumper + */ +public class AuthenticatedUser extends AbstractAuthenticatedUser { + + /** + * Reference to the authentication provider associated with this + * authenticated user. + */ + @Inject + private AuthenticationProvider authProvider; + + /** + * The credentials provided when this user was authenticated. + */ + private Credentials credentials; + + /** + * Initializes this AuthenticatedUser using the given credentials. + * + * @param credentials + * The credentials provided when this user was authenticated. + */ + public void init(Credentials credentials) { + this.credentials = credentials; + setIdentifier(credentials.getUsername().toLowerCase()); + } + + @Override + public AuthenticationProvider getAuthenticationProvider() { + return authProvider; + } + + @Override + public Credentials getCredentials() { + return credentials; + } + +} diff --git a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js new file mode 100644 index 000000000..4f5036234 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * Config block which registers Radius-specific field types. + */ +angular.module('guacRadius').config(['formServiceProvider', + function guacRadiusConfig(formServiceProvider) { + console.log("In guacRadiusConfig() method."); + + // Define field for the signed response from the RADIUS service + formServiceProvider.registerFieldType('GUAC_RADIUS_CHALLENGE_RESPONSE', { + module : 'guacRadius', + controller : 'guacRadiusController', + templateUrl : 'app/ext/radius/templates/radiusChallengeResponseField.html' + }); + +}]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js new file mode 100644 index 000000000..6a5f7e263 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * Controller for the "GUAC_RADIUS_CHALLENGE_RESPONSE" field which uses the DuoWeb + * API to prompt the user for additional credentials, ultimately receiving a + * signed response from the Duo service. + */ +angular.module('guacRadius').controller('guacRadiusController', ['$scope', '$element', + function guacRadiusController($scope, $element) { + console.log("In guacRadiusController() method."); + + var radiusChallenge = $element.find(document.querySelector('#radius-challenge-text')); + var radiusState = $element.find(document.querySelector('#radius-state')); + console.log("RADIUS Reply Message: " + $scope.field.replyMsg); + radiusChellenge.html($scope.field.replyMsg); + console.log("RADIUS State: " + scope.field.radiusState); + radiusState.value = $scope.field.radiusState; + +}]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json new file mode 100644 index 000000000..a82956434 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json @@ -0,0 +1,28 @@ +{ + + "guacamoleVersion" : "0.9.11-incubating", + + "name" : "RADIUS Authentication Backend", + "namespace" : "radius", + + "authProviders" : [ + "org.apache.guacamole.auth.radius.RadiusAuthenticationProvider" + ], + + "translations" : [ + "translations/en.json" + ], + + "js" : [ + "radius.min.js" + ], + + "css" : [ + "radius.min.css" + ], + + "resources" : { + "templates/radiusChallengeResponseField.html" : "text/html" + } + +} diff --git a/extensions/guacamole-auth-radius/src/main/resources/license.txt b/extensions/guacamole-auth-radius/src/main/resources/license.txt new file mode 100644 index 000000000..042f3ce1f --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/license.txt @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ diff --git a/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js b/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js new file mode 100644 index 000000000..6806a9242 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +console.log("Loading guac-radius Angular module."); + +/** + * Module which provides handling for RADIUS challenge-response + * authentication. + */ +angular.module('guacRadius', [ + 'form' +]); + +// Ensure the guacDuo module is loaded along with the rest of the app +angular.module('index').requires.push('guacRadius'); diff --git a/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css b/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css new file mode 100644 index 000000000..00d7988fa --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + + +.radius-challenge-response-field-container { + height: 100%; + width: 100%; + position: fixed; + left: 0; + top: 0; + display: table; + background: white; +} + +.radius-challenge-response-field { + width: 100%; + display: table-cell; + vertical-align: middle; +} + +.radius-challenge-response-field input[type="submit"] { + display: none !important; +} + +.radius-challenge-response-field.loading iframe { + opacity: 0; +} diff --git a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html new file mode 100644 index 000000000..6dedcda7b --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html @@ -0,0 +1,9 @@ +
+
+
+ +
+
+ + +
diff --git a/extensions/guacamole-auth-radius/src/main/resources/translations/en.json b/extensions/guacamole-auth-radius/src/main/resources/translations/en.json new file mode 100644 index 000000000..4e61f2ced --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/translations/en.json @@ -0,0 +1,14 @@ +{ + + "DATA_SOURCE_RADIUS" : { + "NAME" : "RADIUS Backend" + }, + + "LOGIN" : { + "FIELD_HEADER_RADIUS_RESPONSE" : "", + "INFO_RADIUS_RESPONSE_INCORRECT" : "RADIUS response incorrect.", + "INFO_RADIUS_AUTH_REQUIRED" : "Please authenticate with RADIUS to continue.", + "INFO_RADIUS_ADDL_REQUIRED" : "Additional credentials required." + } + +} diff --git a/pom.xml b/pom.xml index fcd65030e..b2203a9e3 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,7 @@ extensions/guacamole-auth-ldap extensions/guacamole-auth-noauth extensions/guacamole-auth-openid + extensions/guacamole-auth-radius doc/guacamole-example From efad91adb0aa166eb89b1a0046da136f7cf4e27c Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 5 Feb 2017 19:51:40 -0500 Subject: [PATCH 02/76] GUACAMOLE-197: Fix if-is-not-a-function style issues, again... --- .../radius/AuthenticationProviderService.java | 8 ++++---- .../auth/radius/RadiusConnectionService.java | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index d803af6af..860f83189 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -103,15 +103,15 @@ public class AuthenticationProviderService { } // If configure fails, permission to login is denied - if(radPack == null) { + if (radPack == null) { logger.debug("Nothing in the RADIUS packet."); throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); } - else if(radPack instanceof AccessReject) { + else if (radPack instanceof AccessReject) { logger.debug("Login has been rejected by RADIUS server."); throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); } - else if(radPack instanceof AccessChallenge) { + else if (radPack instanceof AccessChallenge) { try { String replyMsg = radPack.getAttributeValue("Reply-Message").toString(); String radState = radPack.getAttributeValue("State").toString(); @@ -127,7 +127,7 @@ public class AuthenticationProviderService { throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } } - else if(radPack instanceof AccessAccept) { + else if (radPack instanceof AccessAccept) { try { // Return AuthenticatedUser if bind succeeds diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 0357fbe76..8562ec9fe 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -132,20 +132,20 @@ public class RadiusConnectionService { createRadiusConnection(); AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); - if(radiusClient == null) + if (radiusClient == null) return null; - if(username == null || username.isEmpty()) { + if (username == null || username.isEmpty()) { logger.warn("Anonymous access not allowed with RADIUS client."); return null; } - if(password == null || password.isEmpty()) { + if (password == null || password.isEmpty()) { logger.warn("Password required for RADIUS authentication."); return null; } RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); - if(radAuth == null) + if (radAuth == null) throw new GuacamoleException("Unknown RADIUS authentication protocol."); try { AttributeList radAttrs = new AttributeList(); @@ -175,24 +175,24 @@ public class RadiusConnectionService { createRadiusConnection(); AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); - if(radiusClient == null) + if (radiusClient == null) return null; - if(username == null || username.isEmpty()) { + if (username == null || username.isEmpty()) { logger.warn("Anonymous access not allowed with RADIUS client."); return null; } - if(state == null || state.isEmpty()) { + if (state == null || state.isEmpty()) { logger.warn("This method needs a previous RADIUS state to respond to."); return null; } - if(response == null || response.isEmpty()) { + if (response == null || response.isEmpty()) { logger.warn("Response required for RADIUS authentication."); return null; } RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); - if(radAuth == null) + if (radAuth == null) throw new GuacamoleException("Unknown RADIUS authentication protocol."); try { AttributeList radAttrs = new AttributeList(); From 731c622e8fa5aabaa3af021310863fbc5a2245f0 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 5 Feb 2017 20:24:14 -0500 Subject: [PATCH 03/76] GUACAMOLE-197: Add some comments to document the logic and the functions. --- .../radius/AuthenticationProviderService.java | 13 ++++- .../auth/radius/ConfigurationService.java | 22 +++++++ .../auth/radius/RadiusConnectionService.java | 58 ++++++++++++++++++- .../form/RadiusChallengeResponseField.java | 18 ++++++ 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index 860f83189..e4965b2a1 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -90,7 +90,7 @@ public class AuthenticationProviderService { public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { - // Attempt bind + // Initialize Radius Packet and try to authenticate RadiusPacket radPack; try { radPack = radiusService.authenticate(credentials.getUsername(), @@ -107,10 +107,17 @@ public class AuthenticationProviderService { logger.debug("Nothing in the RADIUS packet."); throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); } + + // If we get back an AccessReject packet, login is denied. else if (radPack instanceof AccessReject) { logger.debug("Login has been rejected by RADIUS server."); throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); } + + /** + * If we receive an AccessChallenge package, the server needs more information - + * We create a new form/field with the challenge message. + */ else if (radPack instanceof AccessChallenge) { try { String replyMsg = radPack.getAttributeValue("Reply-Message").toString(); @@ -127,6 +134,8 @@ public class AuthenticationProviderService { throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } } + + // If we receive AccessAccept, authentication has succeeded else if (radPack instanceof AccessAccept) { try { @@ -139,6 +148,8 @@ public class AuthenticationProviderService { radiusService.disconnect(); } } + + // Something else we haven't thought of has happened, so we throw an error else throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index d30e33489..461243b0f 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -128,6 +128,17 @@ public class ConfigurationService { ); } + /** + * Returns the number of retries for connecting to the RADIUS server + * from guacamole.properties. + * + * @return + * The number of retries for connection to the RADIUS server, + * from guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public int getRadiusRetries() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_RETRIES, @@ -135,6 +146,17 @@ public class ConfigurationService { ); } + /** + * Returns the timeout for connecting to the RADIUS server + * from guacamole.properties. + * + * @return + * The timeout for connection to the RADIUS server, + * from guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public int getRadiusTimeout() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_TIMEOUT, diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 8562ec9fe..02ad9869c 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -77,6 +77,7 @@ public class RadiusConnectionService { private void createRadiusConnection() { /* + * This is commented out right now because it isn't implemented, yet. // Map encryption method to proper connection and socket factory EncryptionMethod encryptionMethod = confService.getEncryptionMethod(); switch (encryptionMethod) { @@ -101,6 +102,8 @@ public class RadiusConnectionService { } */ + + // Create the RADIUS client with the configuration parameters try { radiusClient = new RadiusClient(InetAddress.getByName(confService.getRadiusServer()), confService.getRadiusSharedSecret(), @@ -126,27 +129,50 @@ public class RadiusConnectionService { } + /** + * Authenticate to the RADIUS server and return the response from the + * server. + * + * @param username + * The username for authentication. + * @param password + * The password for authentication. + * + * @return + * A RadiusPacket with the response of the server. + * + * @throws GuacamoleException + * If an error occurs while talking to the server. + */ public RadiusPacket authenticate(String username, String password) throws GuacamoleException { + // Create the connection and load the attribute dictionary createRadiusConnection(); AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); + // If the client is null, we return null - something has gone wrong if (radiusClient == null) return null; + // If a username hasn't been provided, stop if (username == null || username.isEmpty()) { logger.warn("Anonymous access not allowed with RADIUS client."); return null; } + + // If a password hasn't been provided, stop if (password == null || password.isEmpty()) { logger.warn("Password required for RADIUS authentication."); return null; } + // Set up the authentication protocol as configured RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); if (radAuth == null) throw new GuacamoleException("Unknown RADIUS authentication protocol."); + + // Set up attributes, create the access request, and send the packet try { AttributeList radAttrs = new AttributeList(); radAttrs.add(new Attr_UserName(username)); @@ -157,11 +183,13 @@ public class RadiusConnectionService { radAuth.processRequest(radAcc); return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); } + catch (RadiusException e) { logger.error("Unable to complete authentication.", e.getMessage()); logger.debug("Authentication with RADIUS failed.", e); return null; } + catch (NoSuchAlgorithmException e) { logger.error("No such RADIUS algorithm: {}", e.getMessage()); logger.debug("Unknown RADIUS algorithm.", e); @@ -169,28 +197,56 @@ public class RadiusConnectionService { } } + /** + * Authenticate to the RADIUS server using existing state and a response + * + * @param username + * The username for the authentication + * @param state + * The previous state of the RADIUS connection + * @param response + * The response to the RADIUS challenge + * + * @return + * A RadiusPacket with the response of the server. + * + * @throws GuacamoleException + * If an error occurs while talking to the server. + */ public RadiusPacket authenticate(String username, String state, String response) throws GuacamoleException { + // Create the RADIUS connection and set up the dictionary createRadiusConnection(); AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); + // Client failed to set up, so we return null if (radiusClient == null) return null; + // If a username wasn't passed, we quit if (username == null || username.isEmpty()) { logger.warn("Anonymous access not allowed with RADIUS client."); return null; } + + // If the state wasn't passed, we quit if (state == null || state.isEmpty()) { logger.warn("This method needs a previous RADIUS state to respond to."); return null; } + + // If the response wasn't passed, we quit if (response == null || response.isEmpty()) { logger.warn("Response required for RADIUS authentication."); return null; } + /** + * Set up the authenticator based on the configured protocol. + * Unless that fails, add the attributes to the packet, set up the packet + * and send the packet. + */ RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); if (radAuth == null) throw new GuacamoleException("Unknown RADIUS authentication protocol."); @@ -221,8 +277,6 @@ public class RadiusConnectionService { * Disconnects the given RADIUS connection, logging any failure to do so * appropriately. * - * @param radiusConnection - * The RADIUS connection to disconnect. */ public void disconnect() { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java index 4721d6175..2c7bba613 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -31,11 +31,29 @@ public class RadiusChallengeResponseField extends Field { */ private final Logger logger = LoggerFactory.getLogger(RadiusChallengeResponseField.class); + /** + * The field returned by the RADIUS challenge/response. + */ private static final String RADIUS_FIELD_NAME = "guac-radius-challenge-response"; + + /** + * The type of field to initialize for the challenge/response. + */ private static final String RADIUS_FIELD_TYPE = "GUAC_RADIUS_CHALLENGE_RESPONSE"; + + /** + * The state of the connection passed by the previous RADIUS attempt. + */ private final String radiusState; + + /** + * The message the RADIUS server sent back in the challenge. + */ private final String replyMsg; + /** + * Initialize the field with the reply message and the state. + */ public RadiusChallengeResponseField(String replyMsg, String radiusState) { super(RADIUS_FIELD_NAME, RADIUS_FIELD_TYPE); logger.debug("Initializing the RADIUS challenge/response field: {}", replyMsg); From 2175c21ff5fe96129ca7faaca1440620158301a9 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 5 Feb 2017 20:55:44 -0500 Subject: [PATCH 04/76] GUACAMOLE-197: Add comments to the AngularJS files. --- .../src/main/resources/config/radiusConfig.js | 6 ++--- .../controllers/guacRadiusController.js | 23 ++++++++++++------- .../src/main/resources/radiusModule.js | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js index 4f5036234..bc14e63c3 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js +++ b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js @@ -21,10 +21,10 @@ * Config block which registers Radius-specific field types. */ angular.module('guacRadius').config(['formServiceProvider', - function guacRadiusConfig(formServiceProvider) { - console.log("In guacRadiusConfig() method."); + function guacRadiusConfig(formServiceProvider) { + console.log("In guacRadiusConfig() method."); - // Define field for the signed response from the RADIUS service + // Define field for the challenge from the RADIUS service formServiceProvider.registerFieldType('GUAC_RADIUS_CHALLENGE_RESPONSE', { module : 'guacRadius', controller : 'guacRadiusController', diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js index 6a5f7e263..beb544d88 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js @@ -23,14 +23,21 @@ * signed response from the Duo service. */ angular.module('guacRadius').controller('guacRadiusController', ['$scope', '$element', - function guacRadiusController($scope, $element) { - console.log("In guacRadiusController() method."); + function guacRadiusController($scope, $element) { + console.log("In guacRadiusController() method."); - var radiusChallenge = $element.find(document.querySelector('#radius-challenge-text')); - var radiusState = $element.find(document.querySelector('#radius-state')); - console.log("RADIUS Reply Message: " + $scope.field.replyMsg); - radiusChellenge.html($scope.field.replyMsg); - console.log("RADIUS State: " + scope.field.radiusState); - radiusState.value = $scope.field.radiusState; + // Find the area to display the challenge message + var radiusChallenge = $element.find(document.querySelector('#radius-challenge-text')); + + // Find the hidden input to put the state in + var radiusState = $element.find(document.querySelector('#radius-state')); + + // Populate the reply message field + console.log("RADIUS Reply Message: " + $scope.field.replyMsg); + radiusChellenge.html($scope.field.replyMsg); + + // Populate the input area for the connection state + console.log("RADIUS State: " + scope.field.radiusState); + radiusState.value = $scope.field.radiusState; }]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js b/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js index 6806a9242..7868b1277 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js +++ b/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js @@ -27,5 +27,5 @@ angular.module('guacRadius', [ 'form' ]); -// Ensure the guacDuo module is loaded along with the rest of the app +// Ensure the guacRadius module is loaded along with the rest of the app angular.module('index').requires.push('guacRadius'); From d8f6422e28c78ad40b1688d8ccf245d70ef53c23 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 6 Feb 2017 09:03:56 -0500 Subject: [PATCH 05/76] GUACAMOLE-197: Change credentials variable to expectedCredentials for consistency; add username to the response field. --- .../auth/radius/AuthenticationProviderService.java | 6 +++--- .../radius/form/RadiusChallengeResponseField.java | 11 ++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index e4965b2a1..ac937168f 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -124,9 +124,9 @@ public class AuthenticationProviderService { String radState = radPack.getAttributeValue("State").toString(); logger.debug("RADIUS sent challenge response: {}", replyMsg); logger.debug("RADIUS sent state: {}", radState); - Field radiusResponseField = new RadiusChallengeResponseField(replyMsg, radState); - CredentialsInfo responseCredentials = new CredentialsInfo(Collections.singletonList(radiusResponseField)); - throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", responseCredentials); + Field radiusResponseField = new RadiusChallengeResponseField(credentials.getUsername(), replyMsg, radState); + CredentialsInfo expectedCredentials = new CredentialsInfo(Collections.singletonList(radiusResponseField)); + throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); } catch(UnknownAttributeException e) { logger.error("Error in talks with RADIUS server."); diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java index 2c7bba613..9c27ecc9f 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -41,6 +41,10 @@ public class RadiusChallengeResponseField extends Field { */ private static final String RADIUS_FIELD_TYPE = "GUAC_RADIUS_CHALLENGE_RESPONSE"; + /** + * The username used for the RADIUS authentication attempt. + */ + /** * The state of the connection passed by the previous RADIUS attempt. */ @@ -54,15 +58,20 @@ public class RadiusChallengeResponseField extends Field { /** * Initialize the field with the reply message and the state. */ - public RadiusChallengeResponseField(String replyMsg, String radiusState) { + public RadiusChallengeResponseField(String username, String replyMsg, String radiusState) { super(RADIUS_FIELD_NAME, RADIUS_FIELD_TYPE); logger.debug("Initializing the RADIUS challenge/response field: {}", replyMsg); + this.username = username; this.replyMsg = replyMsg; this.radiusState = radiusState; } + public String getUsername() { + return username; + } + public String getRadiusState() { return radiusState; } From f7dda23b05122d9a949bacab92aacb793bf12abb Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 6 Feb 2017 11:57:25 -0500 Subject: [PATCH 06/76] GUACAMOLE-197: Fix a couple of style issues and add the username variable to the RadiusChallengeResponseField class. Fixes build error. --- .../auth/radius/AuthenticationProviderService.java | 11 ++++++----- .../radius/form/RadiusChallengeResponseField.java | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index ac937168f..d70d5eab5 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -122,17 +122,18 @@ public class AuthenticationProviderService { try { String replyMsg = radPack.getAttributeValue("Reply-Message").toString(); String radState = radPack.getAttributeValue("State").toString(); - logger.debug("RADIUS sent challenge response: {}", replyMsg); + logger.debug("RADIUS sent challenge: {}", replyMsg); logger.debug("RADIUS sent state: {}", radState); Field radiusResponseField = new RadiusChallengeResponseField(credentials.getUsername(), replyMsg, radState); CredentialsInfo expectedCredentials = new CredentialsInfo(Collections.singletonList(radiusResponseField)); throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); - } - catch(UnknownAttributeException e) { + } + catch(UnknownAttributeException e) { logger.error("Error in talks with RADIUS server."); logger.debug("RADIUS challenged by didn't provide right attributes."); - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - } + return null; + // throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } } // If we receive AccessAccept, authentication has succeeded diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java index 9c27ecc9f..111c07dee 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -44,6 +44,7 @@ public class RadiusChallengeResponseField extends Field { /** * The username used for the RADIUS authentication attempt. */ + private final String username; /** * The state of the connection passed by the previous RADIUS attempt. From fb0cdb39a5b9aaca02e79ca44ab44e331c8c595a Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 6 Feb 2017 11:59:39 -0500 Subject: [PATCH 07/76] GUACAMOLE-197: Re-enable an exception throw in AuthenticationProviderService that should not have been commented out. --- .../guacamole/auth/radius/AuthenticationProviderService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index d70d5eab5..f77f432e3 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -132,7 +132,7 @@ public class AuthenticationProviderService { logger.error("Error in talks with RADIUS server."); logger.debug("RADIUS challenged by didn't provide right attributes."); return null; - // throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } } From dbb62ded7784459a903197db6ff8becd5b426e69 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 6 Feb 2017 12:01:14 -0500 Subject: [PATCH 08/76] GUACAMOLE-197: You can't throw something after you return out of the function, so lets remove the return statement. --- .../guacamole/auth/radius/AuthenticationProviderService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index f77f432e3..c6650bc8b 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -131,7 +131,6 @@ public class AuthenticationProviderService { catch(UnknownAttributeException e) { logger.error("Error in talks with RADIUS server."); logger.debug("RADIUS challenged by didn't provide right attributes."); - return null; throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } } From 3e994021dacbbb1d214ecd16d208fcdf9e24e4d1 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 7 Feb 2017 15:37:49 -0500 Subject: [PATCH 09/76] GUACAMOLE-197: Working RADIUS Authentication, including dealing with Challenge/Response (e.g. 2/Multi-Factor) --- extensions/guacamole-auth-radius/pom.xml | 12 ++ .../radius/AuthenticationProviderService.java | 162 ++++++++++++------ .../auth/radius/RadiusConnectionService.java | 2 - .../form/RadiusChallengeResponseField.java | 26 +-- .../auth/radius/form/RadiusStateField.java | 64 +++++++ .../src/main/resources/config/radiusConfig.js | 9 +- ...troller.js => radiusResponseController.js} | 15 +- .../controllers/radiusStateController.js | 33 ++++ .../radiusChallengeResponseField.html | 9 - .../templates/radiusResponseField.html | 5 + 10 files changed, 238 insertions(+), 99 deletions(-) create mode 100644 extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java rename extensions/guacamole-auth-radius/src/main/resources/controllers/{guacRadiusController.js => radiusResponseController.js} (70%) create mode 100644 extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js delete mode 100644 extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html create mode 100644 extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index e9d5b5ca7..9aaa515f5 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -258,6 +258,18 @@ 1.1.5 + + commons-lang + commons-lang + 2.6 + + + commons-codec + commons-codec + 1.10 + + + diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index c6650bc8b..91bb0985b 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -21,9 +21,11 @@ package org.apache.guacamole.auth.radius; import com.google.inject.Inject; import com.google.inject.Provider; -import java.util.Collections; +import java.util.Arrays; +import javax.servlet.http.HttpServletRequest; import org.apache.guacamole.auth.radius.user.AuthenticatedUser; import org.apache.guacamole.auth.radius.form.RadiusChallengeResponseField; +import org.apache.guacamole.auth.radius.form.RadiusStateField; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.form.Field; import org.apache.guacamole.net.auth.Credentials; @@ -32,6 +34,7 @@ import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsExce import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.jradius.dictionary.Attr_State; import net.jradius.exception.UnknownAttributeException; import net.jradius.packet.RadiusPacket; import net.jradius.packet.AccessAccept; @@ -90,69 +93,124 @@ public class AuthenticationProviderService { public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { - // Initialize Radius Packet and try to authenticate + // Grab the HTTP Request from the credentials object + HttpServletRequest request = credentials.getRequest(); + + // Set up RadiusPacket object RadiusPacket radPack; - try { - radPack = radiusService.authenticate(credentials.getUsername(), + + // Ignore anonymous users + if (credentials.getUsername() == null || credentials.getUsername().isEmpty()) + return null; + + // Password is required + if (credentials.getPassword() == null || credentials.getPassword().isEmpty()) + return null; + + String challengeResponse = request.getParameter(RadiusChallengeResponseField.PARAMETER_NAME); + String radiusState = request.getParameter(RadiusStateField.PARAMETER_NAME); + + // We do not have a challenge response, so we proceed normally + if (challengeResponse == null || challengeResponse.isEmpty()) { + + // Initialize Radius Packet and try to authenticate + try { + radPack = radiusService.authenticate(credentials.getUsername(), credentials.getPassword()); - } - catch (GuacamoleException e) { - logger.error("Cannot configure RADIUS server: {}", e.getMessage()); - logger.debug("Error configuring RADIUS server.", e); - radPack = null; - } - - // If configure fails, permission to login is denied - if (radPack == null) { - logger.debug("Nothing in the RADIUS packet."); - throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); - } - - // If we get back an AccessReject packet, login is denied. - else if (radPack instanceof AccessReject) { - logger.debug("Login has been rejected by RADIUS server."); - throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); - } - - /** - * If we receive an AccessChallenge package, the server needs more information - - * We create a new form/field with the challenge message. - */ - else if (radPack instanceof AccessChallenge) { - try { - String replyMsg = radPack.getAttributeValue("Reply-Message").toString(); - String radState = radPack.getAttributeValue("State").toString(); - logger.debug("RADIUS sent challenge: {}", replyMsg); - logger.debug("RADIUS sent state: {}", radState); - Field radiusResponseField = new RadiusChallengeResponseField(credentials.getUsername(), replyMsg, radState); - CredentialsInfo expectedCredentials = new CredentialsInfo(Collections.singletonList(radiusResponseField)); - throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); } - catch(UnknownAttributeException e) { - logger.error("Error in talks with RADIUS server."); - logger.debug("RADIUS challenged by didn't provide right attributes."); - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + catch (GuacamoleException e) { + logger.error("Cannot configure RADIUS server: {}", e.getMessage()); + logger.debug("Error configuring RADIUS server.", e); + radPack = null; } + + // If configure fails, permission to login is denied + if (radPack == null) { + logger.debug("Nothing in the RADIUS packet."); + throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); + } + + // If we get back an AccessReject packet, login is denied. + else if (radPack instanceof AccessReject) { + logger.debug("Login has been rejected by RADIUS server."); + throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); + } + + /** + * If we receive an AccessChallenge package, the server needs more information - + * We create a new form/field with the challenge message. + */ + else if (radPack instanceof AccessChallenge) { + try { + RadiusAttribute stateAttr = radPack.findAttribute(Attr_State.TYPE); + // We should have a state attribute at this point, if not, we need to quit. + if (stateAttr == null) { + logger.error("Something went wrong, state attribute not present."); + logger.debug("State Attribute turned up null, which shouldn't happen in AccessChallenge."); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } + String replyMsg = radPack.getAttributeValue("Reply-Message").toString(); + radiusState = new String(stateAttr.getValue().getBytes()); + Field radiusResponseField = new RadiusChallengeResponseField(replyMsg); + Field radiusStateField = new RadiusStateField(radiusState); + CredentialsInfo expectedCredentials = new CredentialsInfo(Arrays.asList(radiusResponseField,radiusStateField)); + throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); + } + catch (UnknownAttributeException e) { + logger.error("Error in talks with RADIUS server."); + logger.debug("RADIUS challenged by didn't provide right attributes."); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } + } + + // If we receive AccessAccept, authentication has succeeded + else if (radPack instanceof AccessAccept) { + try { + + // Return AuthenticatedUser if bind succeeds + AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); + authenticatedUser.init(credentials); + return authenticatedUser; + } + finally { + radiusService.disconnect(); + } + } + + // Something unanticipated happened, so we panic + else + throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); } - // If we receive AccessAccept, authentication has succeeded - else if (radPack instanceof AccessAccept) { + // We did receive a challenge response, so we're going to send that back to the server + else { + // Initialize Radius Packet and try to authenticate try { - - // Return AuthenticatedUser if bind succeeds - AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); - authenticatedUser.init(credentials); - return authenticatedUser; + radPack = radiusService.authenticate(credentials.getUsername(), + radiusState, + challengeResponse); + } + catch (GuacamoleException e) { + logger.error("Cannot configure RADIUS server: {}", e.getMessage()); + logger.debug("Error configuring RADIUS server.", e); + radPack = null; } finally { radiusService.disconnect(); } + + if (radPack instanceof AccessAccept) { + AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); + authenticatedUser.init(credentials); + return authenticatedUser; + } + + else { + logger.warn("RADIUS Challenge/Response authentication failed."); + logger.debug("Did not receive a RADIUS AccessAccept packet back from server."); + throw new GuacamoleInvalidCredentialsException("Failed to authenticate to RADIUS.", CredentialsInfo.USERNAME_PASSWORD); + } } - - // Something else we haven't thought of has happened, so we throw an error - else - throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); - } } diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 02ad9869c..51eef07a7 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -178,7 +178,6 @@ public class RadiusConnectionService { radAttrs.add(new Attr_UserName(username)); radAttrs.add(new Attr_UserPassword(password)); AccessRequest radAcc = new AccessRequest(radiusClient, radAttrs); - logger.debug("Sending authentication request to radius server for user {}.", username); radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); @@ -256,7 +255,6 @@ public class RadiusConnectionService { radAttrs.add(new Attr_State(state)); radAttrs.add(new Attr_UserPassword(response)); AccessRequest radAcc = new AccessRequest(radiusClient, radAttrs); - logger.debug("Sending authentication response to radius server for user {}.", username); radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java index 111c07dee..f76c7bd7a 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -34,23 +34,13 @@ public class RadiusChallengeResponseField extends Field { /** * The field returned by the RADIUS challenge/response. */ - private static final String RADIUS_FIELD_NAME = "guac-radius-challenge-response"; + public static final String PARAMETER_NAME = "guac-radius-challenge-response"; /** * The type of field to initialize for the challenge/response. */ private static final String RADIUS_FIELD_TYPE = "GUAC_RADIUS_CHALLENGE_RESPONSE"; - /** - * The username used for the RADIUS authentication attempt. - */ - private final String username; - - /** - * The state of the connection passed by the previous RADIUS attempt. - */ - private final String radiusState; - /** * The message the RADIUS server sent back in the challenge. */ @@ -59,24 +49,14 @@ public class RadiusChallengeResponseField extends Field { /** * Initialize the field with the reply message and the state. */ - public RadiusChallengeResponseField(String username, String replyMsg, String radiusState) { - super(RADIUS_FIELD_NAME, RADIUS_FIELD_TYPE); + public RadiusChallengeResponseField(String replyMsg) { + super(PARAMETER_NAME, RADIUS_FIELD_TYPE); logger.debug("Initializing the RADIUS challenge/response field: {}", replyMsg); - this.username = username; this.replyMsg = replyMsg; - this.radiusState = radiusState; } - public String getUsername() { - return username; - } - - public String getRadiusState() { - return radiusState; - } - public String getReplyMsg() { return replyMsg; } diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java new file mode 100644 index 000000000..97a0e447a --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.guacamole.auth.radius.form; + +import org.apache.guacamole.form.Field; +import org.codehaus.jackson.annotate.JsonProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RadiusStateField extends Field { + + /** + * Logger for this class. + */ + private final Logger logger = LoggerFactory.getLogger(RadiusStateField.class); + + /** + * The parameter returned by the RADIUS state. + */ + public static final String PARAMETER_NAME = "guac-radius-state"; + + /** + * The type of field to initialize for the state. + */ + private static final String RADIUS_FIELD_TYPE = "GUAC_RADIUS_STATE"; + + /** + * The state of the connection passed by the previous RADIUS attempt. + */ + private final String radiusState; + + /** + * Initialize the field with the reply message and the state. + */ + public RadiusStateField(String radiusState) { + super(PARAMETER_NAME, RADIUS_FIELD_TYPE); + logger.debug("Initializing the RADIUS state field: {}", radiusState); + + this.radiusState = radiusState; + + } + + public String getRadiusState() { + return radiusState; + } + +} diff --git a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js index bc14e63c3..cff025c57 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js +++ b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js @@ -27,8 +27,13 @@ angular.module('guacRadius').config(['formServiceProvider', // Define field for the challenge from the RADIUS service formServiceProvider.registerFieldType('GUAC_RADIUS_CHALLENGE_RESPONSE', { module : 'guacRadius', - controller : 'guacRadiusController', - templateUrl : 'app/ext/radius/templates/radiusChallengeResponseField.html' + controller : 'radiusResponseController', + templateUrl : 'app/ext/radius/templates/radiusResponseField.html' + }); + formServiceProvider.registerFieldType('GUAC_RADIUS_STATE', { + module : 'guacRadius', + controller : 'radiusStateController', + template : '' }); }]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js similarity index 70% rename from extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js rename to extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js index beb544d88..16d7ce56a 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/guacRadiusController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js @@ -22,22 +22,15 @@ * API to prompt the user for additional credentials, ultimately receiving a * signed response from the Duo service. */ -angular.module('guacRadius').controller('guacRadiusController', ['$scope', '$element', - function guacRadiusController($scope, $element) { - console.log("In guacRadiusController() method."); +angular.module('guacRadius').controller('radiusResponseController', ['$scope', '$element', + function radiusResponseController($scope, $element) { + console.log("In radiusResponseController() method."); // Find the area to display the challenge message var radiusChallenge = $element.find(document.querySelector('#radius-challenge-text')); - // Find the hidden input to put the state in - var radiusState = $element.find(document.querySelector('#radius-state')); - // Populate the reply message field console.log("RADIUS Reply Message: " + $scope.field.replyMsg); - radiusChellenge.html($scope.field.replyMsg); - - // Populate the input area for the connection state - console.log("RADIUS State: " + scope.field.radiusState); - radiusState.value = $scope.field.radiusState; + radiusChallenge.html($scope.field.replyMsg); }]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js new file mode 100644 index 000000000..8b51933f8 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * Controller for the "GUAC_RADIUS_CHALLENGE_RESPONSE" field which uses the DuoWeb + * API to prompt the user for additional credentials, ultimately receiving a + * signed response from the Duo service. + */ +angular.module('guacRadius').controller('radiusStateController', ['$scope', '$element', + function radiusStateController($scope, $element) { + console.log("In radiusStateController() method."); + + // Populate the input area for the connection state + console.log("RADIUS State: " + $scope.field.radiusState); + $scope.model = $scope.field.radiusState; + +}]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html deleted file mode 100644 index 6dedcda7b..000000000 --- a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusChallengeResponseField.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
-
- -
-
- - -
diff --git a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html new file mode 100644 index 000000000..a75f66dae --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html @@ -0,0 +1,5 @@ +
+
+ +
+
From 9c13cb94987c076330076b885a5cac5bc64c7983 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 7 Feb 2017 15:43:31 -0500 Subject: [PATCH 10/76] GUACAMOLE-197: Remove debug code from AngularJS files. --- .../src/main/resources/config/radiusConfig.js | 3 ++- .../main/resources/controllers/radiusResponseController.js | 1 - .../src/main/resources/controllers/radiusStateController.js | 4 +--- .../guacamole-auth-radius/src/main/resources/radiusModule.js | 2 -- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js index cff025c57..c0154ac32 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js +++ b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js @@ -22,7 +22,6 @@ */ angular.module('guacRadius').config(['formServiceProvider', function guacRadiusConfig(formServiceProvider) { - console.log("In guacRadiusConfig() method."); // Define field for the challenge from the RADIUS service formServiceProvider.registerFieldType('GUAC_RADIUS_CHALLENGE_RESPONSE', { @@ -30,6 +29,8 @@ angular.module('guacRadius').config(['formServiceProvider', controller : 'radiusResponseController', templateUrl : 'app/ext/radius/templates/radiusResponseField.html' }); + + // Define the hidden field for the RADIUS state formServiceProvider.registerFieldType('GUAC_RADIUS_STATE', { module : 'guacRadius', controller : 'radiusStateController', diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js index 16d7ce56a..0c04d99b7 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js @@ -24,7 +24,6 @@ */ angular.module('guacRadius').controller('radiusResponseController', ['$scope', '$element', function radiusResponseController($scope, $element) { - console.log("In radiusResponseController() method."); // Find the area to display the challenge message var radiusChallenge = $element.find(document.querySelector('#radius-challenge-text')); diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js index 8b51933f8..908aa3b20 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js @@ -24,10 +24,8 @@ */ angular.module('guacRadius').controller('radiusStateController', ['$scope', '$element', function radiusStateController($scope, $element) { - console.log("In radiusStateController() method."); - // Populate the input area for the connection state - console.log("RADIUS State: " + $scope.field.radiusState); + // Populate the hidden field for the connection state $scope.model = $scope.field.radiusState; }]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js b/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js index 7868b1277..7d6c0f363 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js +++ b/extensions/guacamole-auth-radius/src/main/resources/radiusModule.js @@ -17,8 +17,6 @@ * under the License. */ -console.log("Loading guac-radius Angular module."); - /** * Module which provides handling for RADIUS challenge-response * authentication. From 4dd61403c83e19caaf0335d33afe1edc1961d801 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 7 Feb 2017 15:49:44 -0500 Subject: [PATCH 11/76] GUACAMOLE-197: Remove remaining JavaScript debug code. --- .../src/main/resources/controllers/radiusResponseController.js | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js index 0c04d99b7..17acc5797 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js @@ -29,7 +29,6 @@ angular.module('guacRadius').controller('radiusResponseController', ['$scope', ' var radiusChallenge = $element.find(document.querySelector('#radius-challenge-text')); // Populate the reply message field - console.log("RADIUS Reply Message: " + $scope.field.replyMsg); radiusChallenge.html($scope.field.replyMsg); }]); From 86d9a8fb884efd5d1f7d39bcc7233654b5e4db92 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 7 Feb 2017 21:51:04 -0500 Subject: [PATCH 12/76] GUACAMOLE-197: Fix display issues and add translation strings for the RADIUS response field. --- .../src/main/resources/config/radiusConfig.js | 2 +- .../resources/controllers/radiusResponseController.js | 5 +---- .../main/resources/templates/radiusResponseField.html | 6 +----- .../src/main/resources/translations/en.json | 9 +++++---- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js index c0154ac32..20ba86cd3 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js +++ b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js @@ -34,7 +34,7 @@ angular.module('guacRadius').config(['formServiceProvider', formServiceProvider.registerFieldType('GUAC_RADIUS_STATE', { module : 'guacRadius', controller : 'radiusStateController', - template : '' + template : '' }); }]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js index 17acc5797..fb16e6a63 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js @@ -25,10 +25,7 @@ angular.module('guacRadius').controller('radiusResponseController', ['$scope', '$element', function radiusResponseController($scope, $element) { - // Find the area to display the challenge message - var radiusChallenge = $element.find(document.querySelector('#radius-challenge-text')); - // Populate the reply message field - radiusChallenge.html($scope.field.replyMsg); + $scope.radiusPlaceholder = $scope.field.replyMsg; }]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html index a75f66dae..eec760ff4 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html +++ b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusResponseField.html @@ -1,5 +1 @@ -
-
- -
-
+ diff --git a/extensions/guacamole-auth-radius/src/main/resources/translations/en.json b/extensions/guacamole-auth-radius/src/main/resources/translations/en.json index 4e61f2ced..2459b8b37 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/translations/en.json +++ b/extensions/guacamole-auth-radius/src/main/resources/translations/en.json @@ -5,10 +5,11 @@ }, "LOGIN" : { - "FIELD_HEADER_RADIUS_RESPONSE" : "", - "INFO_RADIUS_RESPONSE_INCORRECT" : "RADIUS response incorrect.", - "INFO_RADIUS_AUTH_REQUIRED" : "Please authenticate with RADIUS to continue.", - "INFO_RADIUS_ADDL_REQUIRED" : "Additional credentials required." + "FIELD_HEADER_GUAC_RADIUS_CHALLENGE_RESPONSE" : "", + "FIELD_HEADER_GUAC_RADIUS_STATE" : "", + "INFO_RADIUS_RESPONSE_INCORRECT" : "RADIUS response incorrect.", + "INFO_RADIUS_AUTH_REQUIRED" : "Please authenticate with RADIUS to continue.", + "INFO_RADIUS_ADDL_REQUIRED" : "Please supply additional credentials" } } From 5d83a5f24bd59919704e5c458420458d87671b2d Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 7 Feb 2017 22:35:59 -0500 Subject: [PATCH 13/76] GUACAMOLE-197: Add configuration properties for EAP-related authentication protocols. --- .../auth/radius/ConfigurationService.java | 56 ++++++++++++++++++ .../radius/RadiusGuacamoleProperties.java | 57 +++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 461243b0f..37117e2cc 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -164,4 +164,60 @@ public class ConfigurationService { ); } + public String getRadiusCAFile() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_CA_FILE, + "radius-ca.pem" + ); + } + + public String getRadiusKeyFile() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_KEY_FILE, + "radius-key.pem" + ); + } + + public String getRadiusCAPassword() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_CA_PASSWORD, + null + ); + } + + public String getRadiusCAType() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_CA_TYPE, + null + ); + } + + public String getRadiusKeyPassword() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_KEY_PASSWORD, + null + ); + } + + public String getRadiusKeyType() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_KEY_PASSWORD, + null + ); + } + + public Boolean getRadiusTrustAll() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_TRUST_ALL, + false + ); + } + + public String getRadiusEAPTTLSInnerProtocol() throws GuacamoleException { + return environment.getProperty( + RadiusGuacamoleProperties.RADIUS_EAP_TTLS_INNER_PROTOCOL, + null + ); + } + } diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index 02b9df72b..46c267daf 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -19,6 +19,7 @@ package org.apache.guacamole.auth.radius; +import org.apache.guacamole.properties.BooleanGuacamoleProperty; import org.apache.guacamole.properties.IntegerGuacamoleProperty; import org.apache.guacamole.properties.StringGuacamoleProperty; @@ -108,5 +109,61 @@ public class RadiusGuacamoleProperties { }; + public static final StringGuacamoleProperty RADIUS_CA_FILE = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-ca-file"; } + + }; + + public static final StringGuacamoleProperty RADIUS_CA_TYPE = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-ca-type"; } + + }; + + public static final StringGuacamoleProperty RADIUS_CA_PASSWORD = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-ca-password"; } + + }; + + public static final StringGuacamoleProperty RADIUS_KEY_FILE = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-key-file"; } + + }; + + public static final StringGuacamoleProperty RADIUS_KEY_TYPE = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-key-type"; } + + }; + + public static final StringGuacamoleProperty RADIUS_KEY_PASSWORD = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-key-password"; } + + }; + + public static final BooleanGuacamoleProperty RADIUS_TRUST_ALL = new BooleanGuacamoleProperty() { + + @Override + public String getName() { return "radius-trust-all"; } + + }; + + public static final StringGuacamoleProperty RADIUS_EAP_TTLS_INNER_PROTOCOL = new StringGuacamoleProperty() { + + @Override + public String getName() { return "radius-eap-ttls-inner-protocol"; } + + }; + } From 2e8c3ae284c05a962039a205e3e0cc716fad0c0a Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Thu, 9 Feb 2017 09:28:06 -0500 Subject: [PATCH 14/76] GUACAMOLE-197: Organize RADIUS connection and configuration code a little more cleanly. --- extensions/guacamole-auth-radius/pom.xml | 55 ++++-- .../auth/radius/RadiusConnectionService.java | 162 +++++++++++++----- 2 files changed, 165 insertions(+), 52 deletions(-) diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index 9aaa515f5..3ee38d537 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -175,6 +175,41 @@ + + org.apache.rat @@ -245,11 +280,11 @@ - + @@ -259,18 +294,18 @@ - commons-lang - commons-lang - 2.6 + org.bouncycastle + bcprov-jdk15 + 1.44 + + - commons-codec - commons-codec - 1.10 + net.jradius + jradius-extended + 1.1.5 - - diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 51eef07a7..900e6e54e 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -35,13 +35,16 @@ import net.jradius.packet.RadiusPacket; import net.jradius.packet.AccessRequest; import net.jradius.dictionary.*; import net.jradius.packet.attribute.AttributeList; +import net.jradius.client.auth.EAPTLSAuthenticator; +import net.jradius.client.auth.EAPTTLSAuthenticator; import net.jradius.client.auth.RadiusAuthenticator; +import net.jradius.client.auth.PEAPAuthenticator; import net.jradius.packet.attribute.AttributeFactory; /** * Service for creating and managing connections to RADIUS servers. * - * @author Michael Jumper + * @author Nick Couchman */ public class RadiusConnectionService { @@ -63,12 +66,12 @@ public class RadiusConnectionService { private RadiusClient radiusClient; /** - * Creates a new instance of RadiusConnection, configured as required to use - * whichever encryption method is requested within guacamole.properties. + * Creates a new instance of RadiusConnection, configured with parameters + * from guacamole.properties. * * @return - * A new RadiusConnection instance which has already been configured to - * use the encryption method requested within guacamole.properties. + * A new RadiusConnection instance which has already been configured + * with parameters from guacamole.properties. * * @throws GuacamoleException * If an error occurs while parsing guacamole.properties, or if the @@ -76,33 +79,6 @@ public class RadiusConnectionService { */ private void createRadiusConnection() { - /* - * This is commented out right now because it isn't implemented, yet. - // Map encryption method to proper connection and socket factory - EncryptionMethod encryptionMethod = confService.getEncryptionMethod(); - switch (encryptionMethod) { - - // Unencrypted RADIUS connection - case NONE: - logger.debug("Connection to RADIUS server without encryption."); - radiusClient = new RadiusClient(); - return radiusClient; - - // Radius over TTLS (EAP-TTLS) - case TTLS: - logger.debug("Connecting to RADIUS server using TTLS."); - radiusClient = new RadiusClient(); - return radiusClient; - - // We default to unencrypted connections. - default: - logger.debug("Defaulting an unencrypted RADIUS connection."); - radiusClient = new RadiusClient(); - return radiusClient; - - } - */ - // Create the RADIUS client with the configuration parameters try { radiusClient = new RadiusClient(InetAddress.getByName(confService.getRadiusServer()), @@ -129,6 +105,98 @@ public class RadiusConnectionService { } + /** + * Creates a new instance of RadiusAuthentictor, configured with + * parameters specified within guacamole.properties. + * + * @return + * A new RadiusAuthenticator instance which has been configured + * with parameters from guacamole.properties, or null if + * configuration fails. + * + */ + private RadiusAuthenticator setupRadiusAuthenticator() { + + if(radiusClient == null) { + logger.error("RADIUS client hasn't been set up, yet."); + logger.debug("We can't run this method until the RADIUS client has been set up."); + return null; + } + + String radAuthName; + String caFile; + String caPassword; + String caType; + String keyFile; + String keyPassword; + String keyType; + Boolean trustAll; + String innerProtocol; + + // Pull configuration parameters from guacamole.properties + try { + radAuthName = confService.getRadiusAuthProtocol(); + caFile = confService.getRadiusCAFile(); + caPassword = confService.getRadiusCAPassword(); + caType = confService.getRadiusCAType(); + keyFile = confService.getRadiusKeyFile(); + keyPassword = confService.getRadiusKeyPassword(); + keyType = confService.getRadiusKeyType(); + trustAll = confService.getRadiusTrustAll(); + innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); + + } + catch (GuacamoleException e) { + logger.error("Error retrieving configuration."); + logger.debug("Error getting config parameters from file."); + return null; + } + + RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(radAuthName); + if(radAuth == null) + return null; + + // If we're using any of the TLS protocols, we need to configure them + if (radAuth instanceof PEAPAuthenticator || + radAuth instanceof EAPTLSAuthenticator || + radAuth instanceof EAPTTLSAuthenticator) { + + if (caFile != null && !caFile.isEmpty()) + ((EAPTLSAuthenticator)radAuth).setCaFile(caFile); + + if (caType != null && !caType.isEmpty()) + ((EAPTLSAuthenticator)radAuth).setCaFileType(caType); + + if (caPassword != null && !caPassword.isEmpty()) + ((EAPTLSAuthenticator)radAuth).setCaPassword(caPassword); + + if (keyFile != null && !keyFile.isEmpty()) + ((EAPTLSAuthenticator)radAuth).setKeyFile(keyFile); + + if (keyType != null && !keyType.isEmpty()) + ((EAPTLSAuthenticator)radAuth).setKeyFileType(keyType); + + if (keyPassword != null && !keyPassword.isEmpty()) + ((EAPTLSAuthenticator)radAuth).setKeyPassword(keyPassword); + + ((EAPTLSAuthenticator)radAuth).setTrustAll(trustAll); + + } + + // If we're using EAP-TTLS, we need to define tunneled protocol + if (radAuth instanceof EAPTTLSAuthenticator) { + + if (innerProtocol == null || innerProtocol.isEmpty()) + return null; + + ((EAPTTLSAuthenticator)radAuth).setInnerProtocol(innerProtocol); + + } + + return radAuth; + + } + /** * Authenticate to the RADIUS server and return the response from the * server. @@ -167,8 +235,8 @@ public class RadiusConnectionService { return null; } - // Set up the authentication protocol as configured - RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); + RadiusAuthenticator radAuth = setupRadiusAuthenticator(); + if (radAuth == null) throw new GuacamoleException("Unknown RADIUS authentication protocol."); @@ -177,7 +245,13 @@ public class RadiusConnectionService { AttributeList radAttrs = new AttributeList(); radAttrs.add(new Attr_UserName(username)); radAttrs.add(new Attr_UserPassword(password)); - AccessRequest radAcc = new AccessRequest(radiusClient, radAttrs); + AccessRequest radAcc = new AccessRequest(radiusClient); + + if (radAuth instanceof EAPTTLSAuthenticator) + ((EAPTTLSAuthenticator)radAuth).setTunneledAttributes(radAttrs); + else + radAcc.addAttributes(radAttrs); + radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); @@ -241,20 +315,24 @@ public class RadiusConnectionService { return null; } - /** - * Set up the authenticator based on the configured protocol. - * Unless that fails, add the attributes to the packet, set up the packet - * and send the packet. - */ - RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); + // Set up the RadiusAuthenticator + RadiusAuthenticator radAuth = setupRadiusAuthenticator(); if (radAuth == null) throw new GuacamoleException("Unknown RADIUS authentication protocol."); + + // Add attributes to the connection and send the packet try { AttributeList radAttrs = new AttributeList(); radAttrs.add(new Attr_UserName(username)); radAttrs.add(new Attr_State(state)); radAttrs.add(new Attr_UserPassword(response)); - AccessRequest radAcc = new AccessRequest(radiusClient, radAttrs); + AccessRequest radAcc = new AccessRequest(radiusClient); + + if (radAuth instanceof EAPTTLSAuthenticator) + ((EAPTTLSAuthenticator)radAuth).setTunneledAttributes(radAttrs); + else + radAcc.addAttributes(radAttrs); + radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); From ead5480ca94307b684de1870c81de92645f9ed90 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Thu, 9 Feb 2017 09:30:02 -0500 Subject: [PATCH 15/76] GUACAMOLE-197: Fix style issues...if is not a function... --- .../guacamole/auth/radius/RadiusConnectionService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 900e6e54e..93f338db8 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -117,7 +117,8 @@ public class RadiusConnectionService { */ private RadiusAuthenticator setupRadiusAuthenticator() { - if(radiusClient == null) { + // If we don't have a radiusClient object, yet, don't go any further. + if (radiusClient == null) { logger.error("RADIUS client hasn't been set up, yet."); logger.debug("We can't run this method until the RADIUS client has been set up."); return null; @@ -153,7 +154,7 @@ public class RadiusConnectionService { } RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(radAuthName); - if(radAuth == null) + if (radAuth == null) return null; // If we're using any of the TLS protocols, we need to configure them From aa4517738732c39e88dce4d5dda479c52f478781 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Thu, 9 Feb 2017 15:13:47 -0500 Subject: [PATCH 16/76] GUACAMOLE-197: Deal correctly with EAP Challenge/Response, which is different from 2/Multi-factor Challenge/Response --- .../guacamole/auth/radius/RadiusConnectionService.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 93f338db8..a0077b477 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -40,6 +40,8 @@ import net.jradius.client.auth.EAPTTLSAuthenticator; import net.jradius.client.auth.RadiusAuthenticator; import net.jradius.client.auth.PEAPAuthenticator; import net.jradius.packet.attribute.AttributeFactory; +import net.jradius.packet.AccessChallenge; +import net.jradius.packet.RadiusResponse; /** * Service for creating and managing connections to RADIUS servers. @@ -255,7 +257,13 @@ public class RadiusConnectionService { radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); - return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + RadiusResponse reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + if ((reply instanceof AccessChallenge) && (reply.findAttribute(Attr_EAPMessage.TYPE) != null)) { + logger.debug("We got an AccessChallenge message, and it appears to be an EAP mechanism, trying to process."); + radAuth.processChallenge(radAcc, reply); + reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + } + return reply; } catch (RadiusException e) { From 5cb9b7972d5240ca9307fe5fc94ff818b6d6ab7b Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 10 Feb 2017 16:33:19 -0500 Subject: [PATCH 17/76] GUACAMOLE-197: Correct issues with TLS modules, including EAP-TLS and EAP-TTLS --- .../radius/AuthenticationProviderService.java | 7 ++++ .../auth/radius/ConfigurationService.java | 10 ++--- .../auth/radius/RadiusConnectionService.java | 38 +++++++++++++++---- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index 91bb0985b..0e0629024 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -42,6 +42,7 @@ import net.jradius.packet.AccessChallenge; import net.jradius.packet.AccessReject; import net.jradius.packet.AccessRequest; import net.jradius.packet.AccessResponse; +import net.jradius.packet.attribute.AttributeList; import net.jradius.packet.attribute.RadiusAttribute; /** @@ -141,6 +142,12 @@ public class AuthenticationProviderService { * We create a new form/field with the challenge message. */ else if (radPack instanceof AccessChallenge) { + AttributeList radAttrs = radPack.getAttributes(); + logger.debug("===BEGIN ATTRIBUTE DEBUG==="); + for(RadiusAttribute attr : radAttrs.getAttributeList()) { + logger.debug("Attribute: {}; Value: {}", attr.getAttributeName(), attr.getValue()); + } + logger.debug("==END ATTRIBUTE DEBUG==="); try { RadiusAttribute stateAttr = radPack.findAttribute(Attr_State.TYPE); // We should have a state attribute at this point, if not, we need to quit. diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 37117e2cc..3136587ca 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -167,14 +167,14 @@ public class ConfigurationService { public String getRadiusCAFile() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_CA_FILE, - "radius-ca.pem" + null ); } public String getRadiusKeyFile() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_KEY_FILE, - "radius-key.pem" + "radius.pem" ); } @@ -188,7 +188,7 @@ public class ConfigurationService { public String getRadiusCAType() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_CA_TYPE, - null + "pkcs12" ); } @@ -201,8 +201,8 @@ public class ConfigurationService { public String getRadiusKeyType() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_KEY_PASSWORD, - null + RadiusGuacamoleProperties.RADIUS_KEY_TYPE, + "pkcs12" ); } diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index a0077b477..6cca67789 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -27,6 +27,7 @@ import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleUnsupportedException; +import org.apache.guacamole.environment.LocalEnvironment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.jradius.client.RadiusClient; @@ -35,6 +36,7 @@ import net.jradius.packet.RadiusPacket; import net.jradius.packet.AccessRequest; import net.jradius.dictionary.*; import net.jradius.packet.attribute.AttributeList; +import net.jradius.packet.attribute.RadiusAttribute; import net.jradius.client.auth.EAPTLSAuthenticator; import net.jradius.client.auth.EAPTTLSAuthenticator; import net.jradius.client.auth.RadiusAuthenticator; @@ -135,9 +137,13 @@ public class RadiusConnectionService { String keyType; Boolean trustAll; String innerProtocol; + LocalEnvironment guacEnv; + String basePath; // Pull configuration parameters from guacamole.properties try { + guacEnv = new LocalEnvironment(); + basePath = guacEnv.getGuacamoleHome().getAbsolutePath() + '/'; radAuthName = confService.getRadiusAuthProtocol(); caFile = confService.getRadiusCAFile(); caPassword = confService.getRadiusCAPassword(); @@ -165,7 +171,7 @@ public class RadiusConnectionService { radAuth instanceof EAPTTLSAuthenticator) { if (caFile != null && !caFile.isEmpty()) - ((EAPTLSAuthenticator)radAuth).setCaFile(caFile); + ((EAPTLSAuthenticator)radAuth).setCaFile(basePath + caFile); if (caType != null && !caType.isEmpty()) ((EAPTLSAuthenticator)radAuth).setCaFileType(caType); @@ -174,7 +180,7 @@ public class RadiusConnectionService { ((EAPTLSAuthenticator)radAuth).setCaPassword(caPassword); if (keyFile != null && !keyFile.isEmpty()) - ((EAPTLSAuthenticator)radAuth).setKeyFile(keyFile); + ((EAPTLSAuthenticator)radAuth).setKeyFile(basePath + keyFile); if (keyType != null && !keyType.isEmpty()) ((EAPTLSAuthenticator)radAuth).setKeyFileType(keyType); @@ -248,18 +254,24 @@ public class RadiusConnectionService { AttributeList radAttrs = new AttributeList(); radAttrs.add(new Attr_UserName(username)); radAttrs.add(new Attr_UserPassword(password)); + radAttrs.add(new Attr_CleartextPassword(password)); + AccessRequest radAcc = new AccessRequest(radiusClient); - if (radAuth instanceof EAPTTLSAuthenticator) + // EAP-TTLS tunnels protected attributes inside the TLS layer + if (radAuth instanceof EAPTTLSAuthenticator) { + radAuth.setUsername(new Attr_UserName(username)); ((EAPTTLSAuthenticator)radAuth).setTunneledAttributes(radAttrs); + } else radAcc.addAttributes(radAttrs); radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); RadiusResponse reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); - if ((reply instanceof AccessChallenge) && (reply.findAttribute(Attr_EAPMessage.TYPE) != null)) { - logger.debug("We got an AccessChallenge message, and it appears to be an EAP mechanism, trying to process."); + + // We receive a Challenge not asking for user input, so silently process the challenge + while((reply instanceof AccessChallenge) && (reply.findAttribute(Attr_ReplyMessage.TYPE) == null)) { radAuth.processChallenge(radAcc, reply); reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); } @@ -335,16 +347,28 @@ public class RadiusConnectionService { radAttrs.add(new Attr_UserName(username)); radAttrs.add(new Attr_State(state)); radAttrs.add(new Attr_UserPassword(response)); + radAttrs.add(new Attr_CleartextPassword(response)); + AccessRequest radAcc = new AccessRequest(radiusClient); - if (radAuth instanceof EAPTTLSAuthenticator) + // EAP-TTLS tunnels protected attributes inside the TLS layer + if (radAuth instanceof EAPTTLSAuthenticator) { + radAuth.setUsername(new Attr_UserName(username)); ((EAPTTLSAuthenticator)radAuth).setTunneledAttributes(radAttrs); + } else radAcc.addAttributes(radAttrs); radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); - return radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + RadiusResponse reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + + // We receive a Challenge not asking for user input, so silently process the challenge + while((reply instanceof AccessChallenge) && (reply.findAttribute(Attr_ReplyMessage.TYPE) == null)) { + radAuth.processChallenge(radAcc, reply); + reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + } + return reply; } catch (RadiusException e) { logger.error("Unable to complete authentication.", e.getMessage()); From acbefd4924dcae729ba4f7a77d89ea47abaa8716 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 13 Feb 2017 12:09:34 -0500 Subject: [PATCH 18/76] GUACAMOLE-197: Doesn't make sense to default the key file to radius.pem and have it trying to use pkcs12 as the default keystore type. Set it all to PEM for consistency. --- .../apache/guacamole/auth/radius/ConfigurationService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 3136587ca..5749b7104 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -188,7 +188,7 @@ public class ConfigurationService { public String getRadiusCAType() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_CA_TYPE, - "pkcs12" + "pem" ); } @@ -202,7 +202,7 @@ public class ConfigurationService { public String getRadiusKeyType() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_KEY_TYPE, - "pkcs12" + "pem" ); } From 1747d364d1daae7dea11605aa86c65d9c60c5d46 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 07:30:01 -0500 Subject: [PATCH 19/76] GUACAMOLE-197: Remove section that commments out JRadius Core inclusion --- extensions/guacamole-auth-radius/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index 3ee38d537..66a500e34 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -280,11 +280,11 @@ - + From fe511d97b24646ce16d27582247f7d726068a433 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 07:31:11 -0500 Subject: [PATCH 20/76] GUACAMOLE-197: Remove explicit declaration of bouncycastle dependency - JRadius pulls it in automatically. --- extensions/guacamole-auth-radius/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index 66a500e34..0a77c84bc 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -293,12 +293,6 @@ 1.1.5 - - org.bouncycastle - bcprov-jdk15 - 1.44 - - net.jradius From 9451fd63bf1f0170e5243638bea4a137483c8deb Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 07:33:11 -0500 Subject: [PATCH 21/76] GUACAMOLE-197: Remove Maven links in pom.xml and replace with comments --- extensions/guacamole-auth-radius/pom.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index 0a77c84bc..b45b921d5 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -278,22 +278,21 @@ provided - - + net.jradius jradius-core 1.1.5 - + net.jradius jradius-dictionary 1.1.5 - + net.jradius jradius-extended From 40b27b2cdff371d0a71a278769f6896b0ce071d2 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 08:19:27 -0500 Subject: [PATCH 22/76] GUACAMOLE-197: Remove duo-related licenses; add jradius license. --- .../src/licenses/LICENSE | 38 +- .../licenses/bundled/duo-java-56570d1/LICENSE | 25 - .../licenses/bundled/jradius-1.1.5/LICENSE | 545 ++++++++++++++++++ 3 files changed, 550 insertions(+), 58 deletions(-) delete mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE create mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/jradius-1.1.5/LICENSE diff --git a/extensions/guacamole-auth-radius/src/licenses/LICENSE b/extensions/guacamole-auth-radius/src/licenses/LICENSE index 4ae92c4fe..124e9665c 100644 --- a/extensions/guacamole-auth-radius/src/licenses/LICENSE +++ b/extensions/guacamole-auth-radius/src/licenses/LICENSE @@ -220,40 +220,12 @@ AOP Alliance (http://aopalliance.sourceforge.net/) Public Domain (bundled/aopalliance-1.0/LICENSE) -DuoWeb Java SDK (https://github.com/duosecurity/duo_java) ---------------------------------------------------------- - - Verson: commit 56570d18a1f98642500e6c1158a3f41e448963ff - From: `Duo Security, Inc.' (https://duo.com/) +JRadius (https://github.com/coova/jradius) +------------------------------------------ + Version: 1.1.5 + From: 'Coova Technologies, LLC' (https://coova.github.io) License(s): - BSD 3-clause (bundled/duo-java-56570d1/LICENSE) - -Copyright (c) 2011, Duo Security, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - + LGPL-2.1 (bundled/jradius-1.1.5/LICENSE) Google Guice (https://github.com/google/guice) ---------------------------------------------- diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE b/extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE deleted file mode 100644 index 66e1f74d5..000000000 --- a/extensions/guacamole-auth-radius/src/licenses/bundled/duo-java-56570d1/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2011, Duo Security, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/jradius-1.1.5/LICENSE b/extensions/guacamole-auth-radius/src/licenses/bundled/jradius-1.1.5/LICENSE new file mode 100644 index 000000000..ff1be90e2 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/bundled/jradius-1.1.5/LICENSE @@ -0,0 +1,545 @@ +========================================================================== + +Coova JRadius License: + +The Coova JRadius core libraries are licensed under the The GNU +Library or "Lesser" General Public License (LGPL), while stand-alone +applications within in the JRadius project, listed below, are released +under the standard The GNU General Public License (GPL). For details, +visit http://www.coova.org/JRadius. See source files for details +regarding stand-alone applications contained herein which are +released under the GPL. + +Copyright 2006-2010 Coova Technologies, LLC. All rights reserved. + +See doc/GPL-LICENSE, doc/LGPL-LICENSE, and source files for details. + +========================================================================== + +Original JRadius License: + +The JRadius core library is licensed under the The GNU Library or "Lesser" +General Public License (LGPL), while stand-alone applications within in the +JRadius project, listed below, are released under the standard The GNU +General Public License (GPL). For details, visit http://jradius.net/ + +This software is OSI Certified Open Source Software. OSI Certified is a +certification mark of the Open Source Initiative. + +Stand-alone JRadius Applications: + + * JRadiusSimulator + * JRadiusWiFiClient + * RadClient + * RadBench + * RadiusDictionary + +Copyright 2004-2006 PicoPoint, B.V. +Copyright 2006-2008 David Bird + +See doc/GPL-LICENSE, doc/LGPL-LICENSE, and source files for details. + +========================================================================== + +GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +(This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.) + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + {signature of Ty Coon}, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! From 5590b3eaf354a139eb830e5b1f0dc712c0b3d6b3 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 08:59:00 -0500 Subject: [PATCH 23/76] GUACAMOLE-197: Add Bouncy Castle licenses. --- extensions/guacamole-auth-radius/src/licenses/LICENSE | 9 +++++++++ .../src/licenses/bundled/bouncycastle-1.44/LICENSE | 7 +++++++ 2 files changed, 16 insertions(+) create mode 100644 extensions/guacamole-auth-radius/src/licenses/bundled/bouncycastle-1.44/LICENSE diff --git a/extensions/guacamole-auth-radius/src/licenses/LICENSE b/extensions/guacamole-auth-radius/src/licenses/LICENSE index 124e9665c..fb195e1cb 100644 --- a/extensions/guacamole-auth-radius/src/licenses/LICENSE +++ b/extensions/guacamole-auth-radius/src/licenses/LICENSE @@ -222,11 +222,20 @@ AOP Alliance (http://aopalliance.sourceforge.net/) JRadius (https://github.com/coova/jradius) ------------------------------------------ + Version: 1.1.5 From: 'Coova Technologies, LLC' (https://coova.github.io) License(s): LGPL-2.1 (bundled/jradius-1.1.5/LICENSE) +BouncyCastle Crypto (https://www.bouncycastle.org/java.html) +------------------------------------------------------------ + + Version: 1.44 + From: 'The Legion of Bouncy Caslte' (https://www.bouncycastle.org) + License(s): + The Bouncy Castle License (bundled/bouncycastle-1.44/LICENSE + Google Guice (https://github.com/google/guice) ---------------------------------------------- diff --git a/extensions/guacamole-auth-radius/src/licenses/bundled/bouncycastle-1.44/LICENSE b/extensions/guacamole-auth-radius/src/licenses/bundled/bouncycastle-1.44/LICENSE new file mode 100644 index 000000000..15c29d98a --- /dev/null +++ b/extensions/guacamole-auth-radius/src/licenses/bundled/bouncycastle-1.44/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2000 - 2016 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From b4d46db86218eb00eeb02f6b298df707f12cc7f0 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 09:21:13 -0500 Subject: [PATCH 24/76] GUACAMOLE-197: Clean up code comments and make code more readable. --- .../radius/AuthenticationProviderService.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index 0e0629024..d1a9e2559 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -108,6 +108,7 @@ public class AuthenticationProviderService { if (credentials.getPassword() == null || credentials.getPassword().isEmpty()) return null; + // Try to get parameters to see if this is a post-challenge attempt String challengeResponse = request.getParameter(RadiusChallengeResponseField.PARAMETER_NAME); String radiusState = request.getParameter(RadiusStateField.PARAMETER_NAME); @@ -128,7 +129,7 @@ public class AuthenticationProviderService { // If configure fails, permission to login is denied if (radPack == null) { logger.debug("Nothing in the RADIUS packet."); - throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } // If we get back an AccessReject packet, login is denied. @@ -137,26 +138,29 @@ public class AuthenticationProviderService { throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); } - /** - * If we receive an AccessChallenge package, the server needs more information - - * We create a new form/field with the challenge message. - */ + // If we receive an AccessChallenge package, the server needs more information - + // We create a new form/field with the challenge message. else if (radPack instanceof AccessChallenge) { - AttributeList radAttrs = radPack.getAttributes(); - logger.debug("===BEGIN ATTRIBUTE DEBUG==="); - for(RadiusAttribute attr : radAttrs.getAttributeList()) { - logger.debug("Attribute: {}; Value: {}", attr.getAttributeName(), attr.getValue()); - } - logger.debug("==END ATTRIBUTE DEBUG==="); + try { + // Try to get the state attribute - if it's not there, we have a problem RadiusAttribute stateAttr = radPack.findAttribute(Attr_State.TYPE); - // We should have a state attribute at this point, if not, we need to quit. if (stateAttr == null) { logger.error("Something went wrong, state attribute not present."); logger.debug("State Attribute turned up null, which shouldn't happen in AccessChallenge."); throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } - String replyMsg = radPack.getAttributeValue("Reply-Message").toString(); + + // We need to get the reply message so we know what to ask the user + RadiusAttribute replyAttr = radPack.findAttribute(Attr_ReplyMessage.TYPE); + if (replyAttr == null) { + logger.error("No reply message received from the server."); + logger.debug("Expecting a Attr_ReplyMessage attribute on this packet, and did not get one."); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } + + // We have the required attributes - convert to strings and then generate the additional login box/field + String replyMsg = replyAttr.toString(); radiusState = new String(stateAttr.getValue().getBytes()); Field radiusResponseField = new RadiusChallengeResponseField(replyMsg); Field radiusStateField = new RadiusStateField(radiusState); @@ -172,6 +176,7 @@ public class AuthenticationProviderService { // If we receive AccessAccept, authentication has succeeded else if (radPack instanceof AccessAccept) { + try { // Return AuthenticatedUser if bind succeeds @@ -189,8 +194,9 @@ public class AuthenticationProviderService { throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); } - // We did receive a challenge response, so we're going to send that back to the server + // The user responded to the challenge, send that back to the server else { + // Initialize Radius Packet and try to authenticate try { radPack = radiusService.authenticate(credentials.getUsername(), @@ -206,12 +212,14 @@ public class AuthenticationProviderService { radiusService.disconnect(); } + // Check the server response, see if we get accepted or not if (radPack instanceof AccessAccept) { AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); authenticatedUser.init(credentials); return authenticatedUser; } + // Authentication failed else { logger.warn("RADIUS Challenge/Response authentication failed."); logger.debug("Did not receive a RADIUS AccessAccept packet back from server."); From e6d05406c12a8ca2a39fb77e07505228f6105eb0 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 09:34:17 -0500 Subject: [PATCH 25/76] GUACAMOLE-197: Add JavaDoc comments to functions missing them in the ConfigurationService class. --- .../auth/radius/ConfigurationService.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 5749b7104..753a10a96 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -164,6 +164,17 @@ public class ConfigurationService { ); } + /** + * Returns the CA file for validating certificates for + * encrypted connections as specified in guacamole.properties + * + * @return + * The file name for the CA file for validating + * RADIUS server certificates + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public String getRadiusCAFile() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_CA_FILE, @@ -171,6 +182,18 @@ public class ConfigurationService { ); } + /** + * Returns the key file for the client for creating encrypted + * connections to RADIUS servers as specified in + * guacamole.properties. + * + * @return + * The file name for the client certificate/key pair + * for making encrypted RADIUS connections. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public String getRadiusKeyFile() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_KEY_FILE, @@ -178,6 +201,16 @@ public class ConfigurationService { ); } + /** + * Returns the password for the CA file, if it is + * password-protected, as configured in guacamole.properties. + * + * @return + * The password for the CA file + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public String getRadiusCAPassword() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_CA_PASSWORD, @@ -185,6 +218,18 @@ public class ConfigurationService { ); } + /** + * Returns the type of store that the CA file represents + * so that it can be correctly processed by the RADIUS + * library, as configured in guacamole.properties. + * + * @return + * The type of store that the CA file is encoded + * as, as configured in guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public String getRadiusCAType() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_CA_TYPE, @@ -192,6 +237,16 @@ public class ConfigurationService { ); } + /** + * Returns the password for the key file, if it is + * password-protected, as configured in guacamole.properties. + * + * @return + * The password for the key file + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public String getRadiusKeyPassword() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_KEY_PASSWORD, @@ -199,6 +254,18 @@ public class ConfigurationService { ); } + /** + * Returns the type of store that the key file represents + * so that it can be correctly processed by the RADIUS + * library, as configured in guacamole.properties. + * + * @return + * The type of store that the key file is encoded + * as, as configured in guacamole.properties. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public String getRadiusKeyType() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_KEY_TYPE, @@ -206,6 +273,20 @@ public class ConfigurationService { ); } + /** + * Returns the boolean value of whether or not the + * RADIUS library should trust all server certificates + * or should validate them against known CA certificates, + * as configured in guacamole.properties. + * + * @return + * True if the RADIUS client should trust all + * server certificates; false if it should + * validate against known good CA certificates. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public Boolean getRadiusTrustAll() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_TRUST_ALL, @@ -213,6 +294,18 @@ public class ConfigurationService { ); } + /** + * Returns the tunneled protocol that RADIUS should use + * when the authentication protocol is set to EAP-TTLS, as + * configured in the guacamole.properties file. + * + * @return + * The tunneled protocol that should be used inside + * an EAP-TTLS RADIUS connection. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ public String getRadiusEAPTTLSInnerProtocol() throws GuacamoleException { return environment.getProperty( RadiusGuacamoleProperties.RADIUS_EAP_TTLS_INNER_PROTOCOL, From 0d505bdcf7932a123640275d255ed4df87ad42a3 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 09:39:10 -0500 Subject: [PATCH 26/76] GUACAMOLE-197: Add JavaDoc comments to functions in RadiusGuacamoleProperties. --- .../radius/RadiusGuacamoleProperties.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index 46c267daf..713a08320 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -109,6 +109,9 @@ public class RadiusGuacamoleProperties { }; + /** + * The CA file to use to validate RADIUS server certificates. + */ public static final StringGuacamoleProperty RADIUS_CA_FILE = new StringGuacamoleProperty() { @Override @@ -116,6 +119,9 @@ public class RadiusGuacamoleProperties { }; + /** + * The type of file the RADIUS CA file is (PEM, PKCS12, DER). + */ public static final StringGuacamoleProperty RADIUS_CA_TYPE = new StringGuacamoleProperty() { @Override @@ -123,6 +129,9 @@ public class RadiusGuacamoleProperties { }; + /** + * The password for the CA file. + */ public static final StringGuacamoleProperty RADIUS_CA_PASSWORD = new StringGuacamoleProperty() { @Override @@ -130,6 +139,9 @@ public class RadiusGuacamoleProperties { }; + /** + * The file that stores the key/certificate pair to use for the RADIUS client connection. + */ public static final StringGuacamoleProperty RADIUS_KEY_FILE = new StringGuacamoleProperty() { @Override @@ -137,6 +149,9 @@ public class RadiusGuacamoleProperties { }; + /** + * The type of file the RADIUS key file is (PEM, PKCS12, DER). + */ public static final StringGuacamoleProperty RADIUS_KEY_TYPE = new StringGuacamoleProperty() { @Override @@ -144,6 +159,9 @@ public class RadiusGuacamoleProperties { }; + /** + * The password for the key file. + */ public static final StringGuacamoleProperty RADIUS_KEY_PASSWORD = new StringGuacamoleProperty() { @Override @@ -151,6 +169,9 @@ public class RadiusGuacamoleProperties { }; + /** + * Whether or not to trust all RADIUS server certificates. + */ public static final BooleanGuacamoleProperty RADIUS_TRUST_ALL = new BooleanGuacamoleProperty() { @Override @@ -158,6 +179,9 @@ public class RadiusGuacamoleProperties { }; + /** + * The tunneled protocol to use inside a RADIUS EAP-TTLS connection. + */ public static final StringGuacamoleProperty RADIUS_EAP_TTLS_INNER_PROTOCOL = new StringGuacamoleProperty() { @Override From 59e8b8a66747b6f57e5c3e0a89707649e95cb52d Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 12:37:15 -0500 Subject: [PATCH 27/76] GUACAMOLE-197: Add JavaDoc comments for the response field class; remove some debug code. --- .../radius/form/RadiusChallengeResponseField.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java index f76c7bd7a..0b8944b31 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -24,13 +24,13 @@ import org.codehaus.jackson.annotate.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * A form used to prompt the user for additional information when + * the RADIUS server sends a challenge back to the user with a reply + * message. + */ public class RadiusChallengeResponseField extends Field { - /** - * Logger for this class. - */ - private final Logger logger = LoggerFactory.getLogger(RadiusChallengeResponseField.class); - /** * The field returned by the RADIUS challenge/response. */ @@ -51,12 +51,13 @@ public class RadiusChallengeResponseField extends Field { */ public RadiusChallengeResponseField(String replyMsg) { super(PARAMETER_NAME, RADIUS_FIELD_TYPE); - logger.debug("Initializing the RADIUS challenge/response field: {}", replyMsg); - this.replyMsg = replyMsg; } + /** + * Get the value of the replyMsg field. + */ public String getReplyMsg() { return replyMsg; } From c02e46e70db796c020f6163dc68909567ec50572 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 12:39:06 -0500 Subject: [PATCH 28/76] GUACAMOLE-197: Add JavaDoc comments for the state field class; remove debug code. --- .../auth/radius/form/RadiusStateField.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java index 97a0e447a..51d57fece 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java @@ -24,13 +24,14 @@ import org.codehaus.jackson.annotate.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * The invisible field that stores the state of the RADIUS + * connection. The state is simply a placeholder that helps + * the client and server pick back up the conversation + * at the correct spot during challenge/response. + */ public class RadiusStateField extends Field { - - /** - * Logger for this class. - */ - private final Logger logger = LoggerFactory.getLogger(RadiusStateField.class); - + /** * The parameter returned by the RADIUS state. */ @@ -51,8 +52,6 @@ public class RadiusStateField extends Field { */ public RadiusStateField(String radiusState) { super(PARAMETER_NAME, RADIUS_FIELD_TYPE); - logger.debug("Initializing the RADIUS state field: {}", radiusState); - this.radiusState = radiusState; } From df91b8828a3292a2b7636f67cd9ccc5a02b39e71 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 15 Feb 2017 12:44:59 -0500 Subject: [PATCH 29/76] GUACAMOLE-197: Update Authorship for RADIUS-specific files --- .../org/apache/guacamole/auth/radius/ConfigurationService.java | 2 +- .../apache/guacamole/auth/radius/RadiusGuacamoleProperties.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 753a10a96..a77acaec3 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -28,7 +28,7 @@ import org.apache.guacamole.environment.Environment; /** * Service for retrieving configuration information regarding the RADIUS server. * - * @author Michael Jumper + * @author Nick Couchman */ public class ConfigurationService { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index 713a08320..187686b11 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -29,7 +29,7 @@ import org.apache.guacamole.properties.StringGuacamoleProperty; * These properties will be read from guacamole.properties when the RADIUS * authentication provider is used. * - * @author Michael Jumper + * @author Nick Couchman */ public class RadiusGuacamoleProperties { From 9de1b73ac86553f9b65585244ae47a5e5d7dd2f4 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 28 Feb 2017 08:03:45 -0500 Subject: [PATCH 30/76] GUACAMOLE-197: Remove @author tags from Java source files. --- .../guacamole/auth/radius/AuthenticationProviderService.java | 2 -- .../org/apache/guacamole/auth/radius/ConfigurationService.java | 2 -- .../guacamole/auth/radius/RadiusAuthenticationProvider.java | 2 -- .../auth/radius/RadiusAuthenticationProviderModule.java | 2 -- .../apache/guacamole/auth/radius/RadiusConnectionService.java | 2 -- .../apache/guacamole/auth/radius/RadiusGuacamoleProperties.java | 2 -- .../apache/guacamole/auth/radius/user/AuthenticatedUser.java | 2 -- 7 files changed, 14 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index d1a9e2559..f1741e167 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -48,8 +48,6 @@ import net.jradius.packet.attribute.RadiusAttribute; /** * Service providing convenience functions for the RADIUS AuthenticationProvider * implementation. - * - * @author Michael Jumper */ public class AuthenticationProviderService { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index a77acaec3..58ee3c6ef 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -27,8 +27,6 @@ import org.apache.guacamole.environment.Environment; /** * Service for retrieving configuration information regarding the RADIUS server. - * - * @author Nick Couchman */ public class ConfigurationService { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java index 461eb0a1a..c4af1c361 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java @@ -32,8 +32,6 @@ import org.apache.guacamole.net.auth.UserContext; * Allows users to be authenticated against an RADIUS server. Each user may have * any number of authorized configurations. Authorized configurations may be * shared. - * - * @author Michael Jumper */ public class RadiusAuthenticationProvider implements AuthenticationProvider { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java index af6d02de6..37ecb79fd 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProviderModule.java @@ -27,8 +27,6 @@ import org.apache.guacamole.net.auth.AuthenticationProvider; /** * Guice module which configures RADIUS-specific injections. - * - * @author Michael Jumper */ public class RadiusAuthenticationProviderModule extends AbstractModule { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 6cca67789..d9a7c2d84 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -47,8 +47,6 @@ import net.jradius.packet.RadiusResponse; /** * Service for creating and managing connections to RADIUS servers. - * - * @author Nick Couchman */ public class RadiusConnectionService { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index 187686b11..15f4da207 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -28,8 +28,6 @@ import org.apache.guacamole.properties.StringGuacamoleProperty; * Provides properties required for use of the RADIUS authentication provider. * These properties will be read from guacamole.properties when the RADIUS * authentication provider is used. - * - * @author Nick Couchman */ public class RadiusGuacamoleProperties { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java index d4d55b98e..a42925357 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/user/AuthenticatedUser.java @@ -27,8 +27,6 @@ import org.apache.guacamole.net.auth.Credentials; /** * An RADIUS-specific implementation of AuthenticatedUser, associating a * particular set of credentials with the RADIUS authentication provider. - * - * @author Michael Jumper */ public class AuthenticatedUser extends AbstractAuthenticatedUser { From dd48486f12a00454cb6b08f045d345aae7835456 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 21 Mar 2017 17:12:54 -0400 Subject: [PATCH 31/76] GUACAMOLE-197: Fix imports and remove unnecessary try/catch statement. --- .../auth/radius/AuthenticationProviderService.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index f1741e167..e64d11df2 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -35,6 +35,7 @@ import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredential import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.jradius.dictionary.Attr_State; +import net.jradius.dictionary.Attr_ReplyMessage; import net.jradius.exception.UnknownAttributeException; import net.jradius.packet.RadiusPacket; import net.jradius.packet.AccessAccept; @@ -140,7 +141,6 @@ public class AuthenticationProviderService { // We create a new form/field with the challenge message. else if (radPack instanceof AccessChallenge) { - try { // Try to get the state attribute - if it's not there, we have a problem RadiusAttribute stateAttr = radPack.findAttribute(Attr_State.TYPE); if (stateAttr == null) { @@ -164,12 +164,6 @@ public class AuthenticationProviderService { Field radiusStateField = new RadiusStateField(radiusState); CredentialsInfo expectedCredentials = new CredentialsInfo(Arrays.asList(radiusResponseField,radiusStateField)); throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); - } - catch (UnknownAttributeException e) { - logger.error("Error in talks with RADIUS server."); - logger.debug("RADIUS challenged by didn't provide right attributes."); - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - } } // If we receive AccessAccept, authentication has succeeded From 3a5c43b94e95e4a66e33c3e2435f714ee3c112c6 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 21 Mar 2017 17:14:15 -0400 Subject: [PATCH 32/76] GUACAMOLE-197: Fix indentation after removing try/catch block. --- .../radius/AuthenticationProviderService.java | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index e64d11df2..d9de261b3 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -141,29 +141,30 @@ public class AuthenticationProviderService { // We create a new form/field with the challenge message. else if (radPack instanceof AccessChallenge) { - // Try to get the state attribute - if it's not there, we have a problem - RadiusAttribute stateAttr = radPack.findAttribute(Attr_State.TYPE); - if (stateAttr == null) { - logger.error("Something went wrong, state attribute not present."); - logger.debug("State Attribute turned up null, which shouldn't happen in AccessChallenge."); - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - } + // Try to get the state attribute - if it's not there, we have a problem + RadiusAttribute stateAttr = radPack.findAttribute(Attr_State.TYPE); + if (stateAttr == null) { + logger.error("Something went wrong, state attribute not present."); + logger.debug("State Attribute turned up null, which shouldn't happen in AccessChallenge."); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } - // We need to get the reply message so we know what to ask the user - RadiusAttribute replyAttr = radPack.findAttribute(Attr_ReplyMessage.TYPE); - if (replyAttr == null) { - logger.error("No reply message received from the server."); - logger.debug("Expecting a Attr_ReplyMessage attribute on this packet, and did not get one."); - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - } + // We need to get the reply message so we know what to ask the user + RadiusAttribute replyAttr = radPack.findAttribute(Attr_ReplyMessage.TYPE); + if (replyAttr == null) { + logger.error("No reply message received from the server."); + logger.debug("Expecting a Attr_ReplyMessage attribute on this packet, and did not get one."); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } + + // We have the required attributes - convert to strings and then generate the additional login box/field + String replyMsg = replyAttr.toString(); + radiusState = new String(stateAttr.getValue().getBytes()); + Field radiusResponseField = new RadiusChallengeResponseField(replyMsg); + Field radiusStateField = new RadiusStateField(radiusState); + CredentialsInfo expectedCredentials = new CredentialsInfo(Arrays.asList(radiusResponseField,radiusStateField)); + throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); - // We have the required attributes - convert to strings and then generate the additional login box/field - String replyMsg = replyAttr.toString(); - radiusState = new String(stateAttr.getValue().getBytes()); - Field radiusResponseField = new RadiusChallengeResponseField(replyMsg); - Field radiusStateField = new RadiusStateField(radiusState); - CredentialsInfo expectedCredentials = new CredentialsInfo(Arrays.asList(radiusResponseField,radiusStateField)); - throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); } // If we receive AccessAccept, authentication has succeeded From 773f2da9cecb64711f99f4134d5048fde6db34b5 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 21 Mar 2017 22:17:55 -0400 Subject: [PATCH 33/76] GUACAMOLE-197: Correct comments on controller js files. --- .../main/resources/controllers/radiusResponseController.js | 5 ++--- .../src/main/resources/controllers/radiusStateController.js | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js index fb16e6a63..9e363debc 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js @@ -18,9 +18,8 @@ */ /** - * Controller for the "GUAC_RADIUS_CHALLENGE_RESPONSE" field which uses the DuoWeb - * API to prompt the user for additional credentials, ultimately receiving a - * signed response from the Duo service. + * Controller for the "GUAC_RADIUS_CHALLENGE_RESPONSE" field which + * passes the RADIUS server challenge to the user and takes the response. */ angular.module('guacRadius').controller('radiusResponseController', ['$scope', '$element', function radiusResponseController($scope, $element) { diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js index 908aa3b20..726f2f543 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js @@ -18,9 +18,9 @@ */ /** - * Controller for the "GUAC_RADIUS_CHALLENGE_RESPONSE" field which uses the DuoWeb - * API to prompt the user for additional credentials, ultimately receiving a - * signed response from the Duo service. + * Controller for the "GUAC_RADIUS_STATE" field which is used to pass + * the RADIUS server state to maintain the session with the RADIUS + * server. */ angular.module('guacRadius').controller('radiusStateController', ['$scope', '$element', function radiusStateController($scope, $element) { From 6402cecd539f3f15c055feb1907f9a4065d4702b Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 10 Apr 2017 14:05:08 -0400 Subject: [PATCH 34/76] GUACAMOLE-197: Fix pom.xml build to exclude signatures for BouncyCastle. --- extensions/guacamole-auth-radius/pom.xml | 36 +----------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index b45b921d5..bc373db5a 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -170,46 +170,12 @@ runtime ${project.build.directory}/classes + META-INF/*.SF,META-INF/*.DSA - - org.apache.rat From 564b9687a21ec61f5527078713538c83d63fe9b8 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:15:39 -0400 Subject: [PATCH 35/76] GUACAMOLE-197: Clean up logic for retrieving radius state. --- .../guacamole/auth/radius/AuthenticationProviderService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index d9de261b3..bb2e203b7 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -109,7 +109,6 @@ public class AuthenticationProviderService { // Try to get parameters to see if this is a post-challenge attempt String challengeResponse = request.getParameter(RadiusChallengeResponseField.PARAMETER_NAME); - String radiusState = request.getParameter(RadiusStateField.PARAMETER_NAME); // We do not have a challenge response, so we proceed normally if (challengeResponse == null || challengeResponse.isEmpty()) { @@ -159,7 +158,7 @@ public class AuthenticationProviderService { // We have the required attributes - convert to strings and then generate the additional login box/field String replyMsg = replyAttr.toString(); - radiusState = new String(stateAttr.getValue().getBytes()); + String radiusState = new String(stateAttr.getValue().getBytes()); Field radiusResponseField = new RadiusChallengeResponseField(replyMsg); Field radiusStateField = new RadiusStateField(radiusState); CredentialsInfo expectedCredentials = new CredentialsInfo(Arrays.asList(radiusResponseField,radiusStateField)); @@ -193,7 +192,7 @@ public class AuthenticationProviderService { // Initialize Radius Packet and try to authenticate try { radPack = radiusService.authenticate(credentials.getUsername(), - radiusState, + request.getParameter(RadiusStateField.PARAMETER_NAME), challengeResponse); } catch (GuacamoleException e) { From 8be8626578862eccd9fac53f0a1b7e4e20c1d6e2 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:18:17 -0400 Subject: [PATCH 36/76] GUACAMOLE-197: Consider challengeResponse empty value an acceptable response. --- .../guacamole/auth/radius/AuthenticationProviderService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index bb2e203b7..2b4f98192 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -111,7 +111,7 @@ public class AuthenticationProviderService { String challengeResponse = request.getParameter(RadiusChallengeResponseField.PARAMETER_NAME); // We do not have a challenge response, so we proceed normally - if (challengeResponse == null || challengeResponse.isEmpty()) { + if (challengeResponse == null) { // Initialize Radius Packet and try to authenticate try { From ecfa9183b500f40d9f074e9de56f8a53bae1d701 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:23:19 -0400 Subject: [PATCH 37/76] GUACAMOLE-197: Fix issue where wrong error message is logged. --- .../guacamole/auth/radius/AuthenticationProviderService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index 2b4f98192..da0ae4e98 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -121,7 +121,7 @@ public class AuthenticationProviderService { catch (GuacamoleException e) { logger.error("Cannot configure RADIUS server: {}", e.getMessage()); logger.debug("Error configuring RADIUS server.", e); - radPack = null; + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } // If configure fails, permission to login is denied From 8d83ba2d8b4003b419e90df1bc39a5d8399da9f5 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:25:31 -0400 Subject: [PATCH 38/76] GUACAMOLE-197: Fix comments to remove return value for void function. --- .../guacamole/auth/radius/RadiusConnectionService.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index d9a7c2d84..e8a30ff4b 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -71,13 +71,9 @@ public class RadiusConnectionService { * Creates a new instance of RadiusConnection, configured with parameters * from guacamole.properties. * - * @return - * A new RadiusConnection instance which has already been configured - * with parameters from guacamole.properties. - * * @throws GuacamoleException * If an error occurs while parsing guacamole.properties, or if the - * requested encryption method is actually not implemented (a bug). + * configuration of RadiusClient fails. */ private void createRadiusConnection() { From 12ae1223148351608d1b503a3cc7021da8daef94 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:26:51 -0400 Subject: [PATCH 39/76] GUACAMOLE-197: Fix comments for function that sets up RadiusClient. --- .../apache/guacamole/auth/radius/RadiusConnectionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index e8a30ff4b..a2f984b99 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -68,7 +68,7 @@ public class RadiusConnectionService { private RadiusClient radiusClient; /** - * Creates a new instance of RadiusConnection, configured with parameters + * Creates a new instance of RadiusClient, configured with parameters * from guacamole.properties. * * @throws GuacamoleException From 3976af7b11fa81e04fb7bade11a73814ef54e87f Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:27:57 -0400 Subject: [PATCH 40/76] GUACAMOLE-197: Remove unnecessary return statements. --- .../apache/guacamole/auth/radius/RadiusConnectionService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index a2f984b99..e36b8bd4a 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -88,17 +88,14 @@ public class RadiusConnectionService { catch (GuacamoleException e) { logger.error("Unable to initialize RADIUS client: {}", e.getMessage()); logger.debug("Failed to init RADIUS client.", e); - return; } catch (UnknownHostException e) { logger.error("Unable to resolve host: {}", e.getMessage()); logger.debug("Failed to resolve host.", e); - return; } catch (IOException e) { logger.error("Unable to communicate with host: {}", e.getMessage()); logger.debug("Failed to communicate with host.", e); - return; } } From a49dfeeeeb8acd950d2c7b3fe056453652259d75 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:41:18 -0400 Subject: [PATCH 41/76] GUACAMOLE-197: Allow setupRadiusAuthenticator to throw GuacamoleException rather than hiding it. --- .../auth/radius/RadiusConnectionService.java | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index e36b8bd4a..64a0257ef 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -110,7 +110,7 @@ public class RadiusConnectionService { * configuration fails. * */ - private RadiusAuthenticator setupRadiusAuthenticator() { + private RadiusAuthenticator setupRadiusAuthenticator() throws GuacamoleException { // If we don't have a radiusClient object, yet, don't go any further. if (radiusClient == null) { @@ -132,26 +132,18 @@ public class RadiusConnectionService { String basePath; // Pull configuration parameters from guacamole.properties - try { - guacEnv = new LocalEnvironment(); - basePath = guacEnv.getGuacamoleHome().getAbsolutePath() + '/'; - radAuthName = confService.getRadiusAuthProtocol(); - caFile = confService.getRadiusCAFile(); - caPassword = confService.getRadiusCAPassword(); - caType = confService.getRadiusCAType(); - keyFile = confService.getRadiusKeyFile(); - keyPassword = confService.getRadiusKeyPassword(); - keyType = confService.getRadiusKeyType(); - trustAll = confService.getRadiusTrustAll(); - innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); + guacEnv = new LocalEnvironment(); + basePath = guacEnv.getGuacamoleHome().getAbsolutePath() + '/'; + radAuthName = confService.getRadiusAuthProtocol(); + caFile = confService.getRadiusCAFile(); + caPassword = confService.getRadiusCAPassword(); + caType = confService.getRadiusCAType(); + keyFile = confService.getRadiusKeyFile(); + keyPassword = confService.getRadiusKeyPassword(); + keyType = confService.getRadiusKeyType(); + trustAll = confService.getRadiusTrustAll(); + innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); - } - catch (GuacamoleException e) { - logger.error("Error retrieving configuration."); - logger.debug("Error getting config parameters from file."); - return null; - } - RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(radAuthName); if (radAuth == null) return null; From 99869592aef98d2fa423fde9db3abd2c74e75f21 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:44:54 -0400 Subject: [PATCH 42/76] GUACAMOLE-197: FIx style issues. --- .../apache/guacamole/auth/radius/RadiusConnectionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 64a0257ef..3b37199de 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -208,7 +208,7 @@ public class RadiusConnectionService { throws GuacamoleException { // Create the connection and load the attribute dictionary - createRadiusConnection(); + createRadiusConnection(); AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); // If the client is null, we return null - something has gone wrong From d773614a79dd64027fe50aca94d9fd9083163bc2 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 09:46:14 -0400 Subject: [PATCH 43/76] GUACAMOLE-197: Remove unnecessary null default values, as that is already the default. --- .../auth/radius/ConfigurationService.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 58ee3c6ef..0cfe26b0e 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -103,8 +103,7 @@ public class ConfigurationService { */ public String getRadiusSharedSecret() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_SHARED_SECRET, - null + RadiusGuacamoleProperties.RADIUS_SHARED_SECRET ); } @@ -121,8 +120,7 @@ public class ConfigurationService { */ public String getRadiusAuthProtocol() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_AUTH_PROTOCOL, - null + RadiusGuacamoleProperties.RADIUS_AUTH_PROTOCOL ); } @@ -175,8 +173,7 @@ public class ConfigurationService { */ public String getRadiusCAFile() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_CA_FILE, - null + RadiusGuacamoleProperties.RADIUS_CA_FILE ); } @@ -211,8 +208,7 @@ public class ConfigurationService { */ public String getRadiusCAPassword() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_CA_PASSWORD, - null + RadiusGuacamoleProperties.RADIUS_CA_PASSWORD ); } @@ -247,8 +243,7 @@ public class ConfigurationService { */ public String getRadiusKeyPassword() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_KEY_PASSWORD, - null + RadiusGuacamoleProperties.RADIUS_KEY_PASSWORD ); } @@ -306,8 +301,7 @@ public class ConfigurationService { */ public String getRadiusEAPTTLSInnerProtocol() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_EAP_TTLS_INNER_PROTOCOL, - null + RadiusGuacamoleProperties.RADIUS_EAP_TTLS_INNER_PROTOCOL ); } From ba837cb31bf84331389e500bdf468d39112b76d7 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 10:19:00 -0400 Subject: [PATCH 44/76] GUACAMOLE-197: Remove unnecessary null/empty checks in setupRadiusAuthenticator, and throw exceptions instead of returning null. --- .../auth/radius/RadiusConnectionService.java | 39 +++++++------------ 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 3b37199de..68d7823f2 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -119,14 +119,11 @@ public class RadiusConnectionService { return null; } - String radAuthName; String caFile; String caPassword; String caType; String keyFile; String keyPassword; - String keyType; - Boolean trustAll; String innerProtocol; LocalEnvironment guacEnv; String basePath; @@ -134,52 +131,42 @@ public class RadiusConnectionService { // Pull configuration parameters from guacamole.properties guacEnv = new LocalEnvironment(); basePath = guacEnv.getGuacamoleHome().getAbsolutePath() + '/'; - radAuthName = confService.getRadiusAuthProtocol(); caFile = confService.getRadiusCAFile(); caPassword = confService.getRadiusCAPassword(); - caType = confService.getRadiusCAType(); keyFile = confService.getRadiusKeyFile(); keyPassword = confService.getRadiusKeyPassword(); - keyType = confService.getRadiusKeyType(); - trustAll = confService.getRadiusTrustAll(); innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); - RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(radAuthName); + RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); if (radAuth == null) - return null; + throw new GuacamoleException("Could not get a valid RadiusAuthenticator for specified protocol: " + confService.getRadiusAuthProtocol()); // If we're using any of the TLS protocols, we need to configure them if (radAuth instanceof PEAPAuthenticator || radAuth instanceof EAPTLSAuthenticator || radAuth instanceof EAPTTLSAuthenticator) { - if (caFile != null && !caFile.isEmpty()) + if (caFile != null) { ((EAPTLSAuthenticator)radAuth).setCaFile(basePath + caFile); + ((EAPTLSAuthenticator)radAuth).setCaFileType(confService.getRadiusCAType()); + if (caPassword != null) + ((EAPTLSAuthenticator)radAuth).setCaPassword(caPassword); + } - if (caType != null && !caType.isEmpty()) - ((EAPTLSAuthenticator)radAuth).setCaFileType(caType); - - if (caPassword != null && !caPassword.isEmpty()) - ((EAPTLSAuthenticator)radAuth).setCaPassword(caPassword); - - if (keyFile != null && !keyFile.isEmpty()) - ((EAPTLSAuthenticator)radAuth).setKeyFile(basePath + keyFile); - - if (keyType != null && !keyType.isEmpty()) - ((EAPTLSAuthenticator)radAuth).setKeyFileType(keyType); - - if (keyPassword != null && !keyPassword.isEmpty()) + if (keyPassword != null) ((EAPTLSAuthenticator)radAuth).setKeyPassword(keyPassword); - ((EAPTLSAuthenticator)radAuth).setTrustAll(trustAll); + ((EAPTLSAuthenticator)radAuth).setKeyFile(basePath + keyFile); + ((EAPTLSAuthenticator)radAuth).setKeyFileType(confService.getRadiusKeyType()); + ((EAPTLSAuthenticator)radAuth).setTrustAll(confService.getRadiusTrustAll()); } // If we're using EAP-TTLS, we need to define tunneled protocol if (radAuth instanceof EAPTTLSAuthenticator) { - if (innerProtocol == null || innerProtocol.isEmpty()) - return null; + if (innerProtocol == null) + throw new GuacamoleException("Trying to use EAP-TTLS, but no inner protocol specified."); ((EAPTTLSAuthenticator)radAuth).setInnerProtocol(innerProtocol); From fd84e761b104040ed4f8eb7b3a6afff67050c5ca Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 10:30:38 -0400 Subject: [PATCH 45/76] GUACAMOLE-197: Remove the .tar.gz bundling bits from the source tree, since we won't be distributing binaries. --- extensions/guacamole-auth-radius/pom.xml | 22 -------- .../src/main/assembly/dist.xml | 53 ------------------- 2 files changed, 75 deletions(-) delete mode 100644 extensions/guacamole-auth-radius/src/main/assembly/dist.xml diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index bc373db5a..921087d56 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -133,28 +133,6 @@ - - - maven-assembly-plugin - 2.5.3 - - ${project.artifactId}-${project.version} - false - - src/main/assembly/dist.xml - - - - - make-dist-archive - package - - single - - - - - org.apache.maven.plugins diff --git a/extensions/guacamole-auth-radius/src/main/assembly/dist.xml b/extensions/guacamole-auth-radius/src/main/assembly/dist.xml deleted file mode 100644 index b89fd534c..000000000 --- a/extensions/guacamole-auth-radius/src/main/assembly/dist.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - dist - ${project.artifactId}-${project.version} - - - - tar.gz - - - - - - - - - src/licenses - - - - - target - - - *.jar - - - - - - From 60b5802cc70f2513243fc624c39e3870a9481c8f Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 10:57:45 -0400 Subject: [PATCH 46/76] GUACAMOLE-197: Move state field to template file for consistency. --- .../src/main/resources/config/radiusConfig.js | 2 +- .../src/main/resources/templates/radiusStateField.html | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html diff --git a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js index 20ba86cd3..dab0ffc24 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js +++ b/extensions/guacamole-auth-radius/src/main/resources/config/radiusConfig.js @@ -34,7 +34,7 @@ angular.module('guacRadius').config(['formServiceProvider', formServiceProvider.registerFieldType('GUAC_RADIUS_STATE', { module : 'guacRadius', controller : 'radiusStateController', - template : '' + templateUrl : 'app/ext/radius/templates/radiusStateField.html' }); }]); diff --git a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html new file mode 100644 index 000000000..be8067c06 --- /dev/null +++ b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html @@ -0,0 +1 @@ + From cf884f33f93c27ee861d7f00156de4732581f942 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 11 Apr 2017 13:29:49 -0400 Subject: [PATCH 47/76] GUACAMOLE-197: Use java.io.File for filename operations, rather than relying on platform-specific assumptions. --- .../auth/radius/RadiusConnectionService.java | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 68d7823f2..677647a8d 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -20,6 +20,7 @@ package org.apache.guacamole.auth.radius; import com.google.inject.Inject; +import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.InetAddress; @@ -119,23 +120,14 @@ public class RadiusConnectionService { return null; } - String caFile; - String caPassword; - String caType; - String keyFile; - String keyPassword; - String innerProtocol; - LocalEnvironment guacEnv; - String basePath; - // Pull configuration parameters from guacamole.properties - guacEnv = new LocalEnvironment(); - basePath = guacEnv.getGuacamoleHome().getAbsolutePath() + '/'; - caFile = confService.getRadiusCAFile(); - caPassword = confService.getRadiusCAPassword(); - keyFile = confService.getRadiusKeyFile(); - keyPassword = confService.getRadiusKeyPassword(); - innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); + LocalEnvironment guacEnv = new LocalEnvironment(); + String guacHome = guacEnv.getGuacamoleHome().getAbsolutePath(); + String caFile = confService.getRadiusCAFile(); + String caPassword = confService.getRadiusCAPassword(); + String keyFile = confService.getRadiusKeyFile(); + String keyPassword = confService.getRadiusKeyPassword(); + String innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); if (radAuth == null) @@ -147,7 +139,7 @@ public class RadiusConnectionService { radAuth instanceof EAPTTLSAuthenticator) { if (caFile != null) { - ((EAPTLSAuthenticator)radAuth).setCaFile(basePath + caFile); + ((EAPTLSAuthenticator)radAuth).setCaFile((new File(guacHome, caFile)).toString()); ((EAPTLSAuthenticator)radAuth).setCaFileType(confService.getRadiusCAType()); if (caPassword != null) ((EAPTLSAuthenticator)radAuth).setCaPassword(caPassword); @@ -156,7 +148,7 @@ public class RadiusConnectionService { if (keyPassword != null) ((EAPTLSAuthenticator)radAuth).setKeyPassword(keyPassword); - ((EAPTLSAuthenticator)radAuth).setKeyFile(basePath + keyFile); + ((EAPTLSAuthenticator)radAuth).setKeyFile((new File(guacHome, keyFile)).toString()); ((EAPTLSAuthenticator)radAuth).setKeyFileType(confService.getRadiusKeyType()); ((EAPTLSAuthenticator)radAuth).setTrustAll(confService.getRadiusTrustAll()); From f4a6cf85ed84d9305397447dfde4cfab1815b8b5 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 21 Apr 2017 22:25:48 -0400 Subject: [PATCH 48/76] GUACAMOLE-197: Make a seprate build profile for LGPL dependencies and add this extension to that list; also exclude all extensions from top-level RAT check. --- pom.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b2203a9e3..0144d5ac0 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,6 @@ extensions/guacamole-auth-ldap extensions/guacamole-auth-noauth extensions/guacamole-auth-openid - extensions/guacamole-auth-radius doc/guacamole-example @@ -64,6 +63,15 @@ + + + lgpl-extensions + + extensions/guacamole-auth-radius + + + + @@ -106,6 +114,7 @@ .dockerignore CONTRIBUTING **/README.md + extensions/**/* From 77cb98c30f4181537b9b06a42ff2b65f3f4f4531 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 14 Jul 2017 16:44:20 -0400 Subject: [PATCH 49/76] GUACAMOLE-197: Bump version to 0.9.13-incubating and fix issues after rebase. --- extensions/guacamole-auth-radius/pom.xml | 4 ++-- .../guacamole/auth/radius/RadiusAuthenticationProvider.java | 5 +++++ .../src/main/resources/guac-manifest.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index 921087d56..69d171d40 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -26,7 +26,7 @@ org.apache.guacamole guacamole-auth-radius jar - 0.9.11-incubating + 0.9.13-incubating guacamole-auth-radius http://guacamole.incubator.apache.org/ @@ -198,7 +198,7 @@ org.apache.guacamole guacamole-ext - 0.9.11-incubating + 0.9.13-incubating provided diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java index c4af1c361..499f3c1e4 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java @@ -63,6 +63,11 @@ public class RadiusAuthenticationProvider implements AuthenticationProvider { return "radius"; } + @Override + public Object getResource() throws GuacamoleException { + return null; + } + @Override public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { diff --git a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json index a82956434..f8c011104 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json +++ b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json @@ -1,6 +1,6 @@ { - "guacamoleVersion" : "0.9.11-incubating", + "guacamoleVersion" : "0.9.13-incubating", "name" : "RADIUS Authentication Backend", "namespace" : "radius", From 41557566b9b87b7f2acaad00fc54781e83210658 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 14 Jul 2017 16:53:39 -0400 Subject: [PATCH 50/76] GUACAMOLE-197: Log error if we reach an unexpected place in the RADIUS conversation. --- .../guacamole/auth/radius/AuthenticationProviderService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index da0ae4e98..d4f3ed1f6 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -182,8 +182,10 @@ public class AuthenticationProviderService { } // Something unanticipated happened, so we panic - else + else { + logger.error("Unexpected authentication failure talking to RADIUS server."); throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); + } } // The user responded to the challenge, send that back to the server From e341e48c2a8d81eb73abb84ac23619027a61c303 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 14 Jul 2017 21:24:45 -0400 Subject: [PATCH 51/76] GUACAMOLE-197: Move some RADIUS code into specific functions; tighten up code, improve efficiency, address some style issues. --- .../radius/AuthenticationProviderService.java | 98 +++++++++++-------- .../auth/radius/RadiusConnectionService.java | 40 ++++---- 2 files changed, 75 insertions(+), 63 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index d4f3ed1f6..fc4a6bf1d 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -75,6 +75,46 @@ public class AuthenticationProviderService { @Inject private Provider authenticatedUserProvider; + /** + * Returns the expected credentials from a RADIUS challenge. + * + * @param challengePacket + * The AccessChallenge RadiusPacket received from the RADIUS + * server. + * + * @return + * A CredentialsInfo object that represents fields that need to + * be presented to the user in order to complete authentication. + * One of these must be the RADIUS state. + */ + private CredentialsInfo getRadiusChallenge(RadiusPacket challengePacket) { + + // Try to get the state attribute - if it's not there, we have a problem + RadiusAttribute stateAttr = challengePacket.findAttribute(Attr_State.TYPE); + if (stateAttr == null) { + logger.error("Something went wrong, state attribute not present."); + logger.debug("State Attribute turned up null, which shouldn't happen in AccessChallenge."); + return null; + } + + // We need to get the reply message so we know what to ask the user + RadiusAttribute replyAttr = challengePacket.findAttribute(Attr_ReplyMessage.TYPE); + if (replyAttr == null) { + logger.error("No reply message received from the server."); + logger.debug("Expecting a Attr_ReplyMessage attribute on this packet, and did not get one."); + return null; + } + + // We have the required attributes - convert to strings and then generate the additional login box/field + String replyMsg = replyAttr.toString(); + String radiusState = new String(stateAttr.getValue().getBytes()); + Field radiusResponseField = new RadiusChallengeResponseField(replyMsg); + Field radiusStateField = new RadiusStateField(radiusState); + + // Return the CredentialsInfo object that has the state and the expected response. + return new CredentialsInfo(Arrays.asList(radiusResponseField,radiusStateField)); + } + /** * Returns an AuthenticatedUser representing the user authenticated by the * given credentials. @@ -93,12 +133,6 @@ public class AuthenticationProviderService { public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { - // Grab the HTTP Request from the credentials object - HttpServletRequest request = credentials.getRequest(); - - // Set up RadiusPacket object - RadiusPacket radPack; - // Ignore anonymous users if (credentials.getUsername() == null || credentials.getUsername().isEmpty()) return null; @@ -107,13 +141,19 @@ public class AuthenticationProviderService { if (credentials.getPassword() == null || credentials.getPassword().isEmpty()) return null; + // Grab the HTTP Request from the credentials object + HttpServletRequest request = credentials.getRequest(); + // Try to get parameters to see if this is a post-challenge attempt String challengeResponse = request.getParameter(RadiusChallengeResponseField.PARAMETER_NAME); - // We do not have a challenge response, so we proceed normally + // RadiusPacket object to store response from server. + RadiusPacket radPack; + + // We do not have a challenge response, proceed with username/password authentication. if (challengeResponse == null) { - // Initialize Radius Packet and try to authenticate + // Attempt RADIUS authentication with username/password. try { radPack = radiusService.authenticate(credentials.getUsername(), credentials.getPassword()); @@ -124,7 +164,7 @@ public class AuthenticationProviderService { throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } - // If configure fails, permission to login is denied + // If no RadiusPacket is returned, we've encountered an error. if (radPack == null) { logger.debug("Nothing in the RADIUS packet."); throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); @@ -133,45 +173,23 @@ public class AuthenticationProviderService { // If we get back an AccessReject packet, login is denied. else if (radPack instanceof AccessReject) { logger.debug("Login has been rejected by RADIUS server."); - throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD); + throw new GuacamoleInvalidCredentialsException("Authentication failed.", CredentialsInfo.USERNAME_PASSWORD); } // If we receive an AccessChallenge package, the server needs more information - // We create a new form/field with the challenge message. else if (radPack instanceof AccessChallenge) { + CredentialsInfo expectedCredentials = getRadiusChallenge(radPack); - // Try to get the state attribute - if it's not there, we have a problem - RadiusAttribute stateAttr = radPack.findAttribute(Attr_State.TYPE); - if (stateAttr == null) { - logger.error("Something went wrong, state attribute not present."); - logger.debug("State Attribute turned up null, which shouldn't happen in AccessChallenge."); + if (expectedCredentials == null) throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - } - // We need to get the reply message so we know what to ask the user - RadiusAttribute replyAttr = radPack.findAttribute(Attr_ReplyMessage.TYPE); - if (replyAttr == null) { - logger.error("No reply message received from the server."); - logger.debug("Expecting a Attr_ReplyMessage attribute on this packet, and did not get one."); - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - } - - // We have the required attributes - convert to strings and then generate the additional login box/field - String replyMsg = replyAttr.toString(); - String radiusState = new String(stateAttr.getValue().getBytes()); - Field radiusResponseField = new RadiusChallengeResponseField(replyMsg); - Field radiusStateField = new RadiusStateField(radiusState); - CredentialsInfo expectedCredentials = new CredentialsInfo(Arrays.asList(radiusResponseField,radiusStateField)); throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); - } // If we receive AccessAccept, authentication has succeeded else if (radPack instanceof AccessAccept) { - try { - - // Return AuthenticatedUser if bind succeeds AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); authenticatedUser.init(credentials); return authenticatedUser; @@ -181,9 +199,9 @@ public class AuthenticationProviderService { } } - // Something unanticipated happened, so we panic + // Something unanticipated happened, so we panic and go back to login. else { - logger.error("Unexpected authentication failure talking to RADIUS server."); + logger.error("Unexpected failure authenticating with RADIUS server."); throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); } } @@ -191,7 +209,7 @@ public class AuthenticationProviderService { // The user responded to the challenge, send that back to the server else { - // Initialize Radius Packet and try to authenticate + // Attempt to authenticate with response to challenge. try { radPack = radiusService.authenticate(credentials.getUsername(), request.getParameter(RadiusStateField.PARAMETER_NAME), @@ -200,7 +218,7 @@ public class AuthenticationProviderService { catch (GuacamoleException e) { logger.error("Cannot configure RADIUS server: {}", e.getMessage()); logger.debug("Error configuring RADIUS server.", e); - radPack = null; + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } finally { radiusService.disconnect(); @@ -216,8 +234,8 @@ public class AuthenticationProviderService { // Authentication failed else { logger.warn("RADIUS Challenge/Response authentication failed."); - logger.debug("Did not receive a RADIUS AccessAccept packet back from server."); - throw new GuacamoleInvalidCredentialsException("Failed to authenticate to RADIUS.", CredentialsInfo.USERNAME_PASSWORD); + logger.debug("Received something other than AccessAccept packet from the RADIUS server."); + throw new GuacamoleInvalidCredentialsException("Authentication failed.", CredentialsInfo.USERNAME_PASSWORD); } } } diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 677647a8d..c3524cd9c 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -109,7 +109,6 @@ public class RadiusConnectionService { * A new RadiusAuthenticator instance which has been configured * with parameters from guacamole.properties, or null if * configuration fails. - * */ private RadiusAuthenticator setupRadiusAuthenticator() throws GuacamoleException { @@ -151,17 +150,14 @@ public class RadiusConnectionService { ((EAPTLSAuthenticator)radAuth).setKeyFile((new File(guacHome, keyFile)).toString()); ((EAPTLSAuthenticator)radAuth).setKeyFileType(confService.getRadiusKeyType()); ((EAPTLSAuthenticator)radAuth).setTrustAll(confService.getRadiusTrustAll()); - } // If we're using EAP-TTLS, we need to define tunneled protocol if (radAuth instanceof EAPTTLSAuthenticator) { - if (innerProtocol == null) throw new GuacamoleException("Trying to use EAP-TTLS, but no inner protocol specified."); ((EAPTTLSAuthenticator)radAuth).setInnerProtocol(innerProtocol); - } return radAuth; @@ -186,14 +182,6 @@ public class RadiusConnectionService { public RadiusPacket authenticate(String username, String password) throws GuacamoleException { - // Create the connection and load the attribute dictionary - createRadiusConnection(); - AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); - - // If the client is null, we return null - something has gone wrong - if (radiusClient == null) - return null; - // If a username hasn't been provided, stop if (username == null || username.isEmpty()) { logger.warn("Anonymous access not allowed with RADIUS client."); @@ -206,6 +194,14 @@ public class RadiusConnectionService { return null; } + // Create the connection and load the attribute dictionary + createRadiusConnection(); + AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); + + // If the client is null, we return null - something has gone wrong + if (radiusClient == null) + return null; + RadiusAuthenticator radAuth = setupRadiusAuthenticator(); if (radAuth == null) @@ -272,14 +268,6 @@ public class RadiusConnectionService { public RadiusPacket authenticate(String username, String state, String response) throws GuacamoleException { - // Create the RADIUS connection and set up the dictionary - createRadiusConnection(); - AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); - - // Client failed to set up, so we return null - if (radiusClient == null) - return null; - // If a username wasn't passed, we quit if (username == null || username.isEmpty()) { logger.warn("Anonymous access not allowed with RADIUS client."); @@ -298,6 +286,14 @@ public class RadiusConnectionService { return null; } + // Create the RADIUS connection and set up the dictionary + createRadiusConnection(); + AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); + + // Client failed to set up, so we return null + if (radiusClient == null) + return null; + // Set up the RadiusAuthenticator RadiusAuthenticator radAuth = setupRadiusAuthenticator(); if (radAuth == null) @@ -345,9 +341,7 @@ public class RadiusConnectionService { } /** - * Disconnects the given RADIUS connection, logging any failure to do so - * appropriately. - * + * Disconnects the current RADIUS connection. */ public void disconnect() { From f0b36ca5b104d7d65cd36f95ac4d2640fba9f07a Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 14 Jul 2017 21:52:29 -0400 Subject: [PATCH 52/76] GUACAMOLE-197: More style tweaks, update comments, fix typos --- .../radius/AuthenticationProviderService.java | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index fc4a6bf1d..2c3ace9eb 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -141,19 +141,16 @@ public class AuthenticationProviderService { if (credentials.getPassword() == null || credentials.getPassword().isEmpty()) return null; - // Grab the HTTP Request from the credentials object + // Grab HTTP request object and a response to a challenge. HttpServletRequest request = credentials.getRequest(); - - // Try to get parameters to see if this is a post-challenge attempt String challengeResponse = request.getParameter(RadiusChallengeResponseField.PARAMETER_NAME); // RadiusPacket object to store response from server. RadiusPacket radPack; - // We do not have a challenge response, proceed with username/password authentication. + // No challenge response, proceed with username/password authentication. if (challengeResponse == null) { - // Attempt RADIUS authentication with username/password. try { radPack = radiusService.authenticate(credentials.getUsername(), credentials.getPassword()); @@ -164,20 +161,19 @@ public class AuthenticationProviderService { throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } - // If no RadiusPacket is returned, we've encountered an error. + // No RadiusPacket is returned, we've encountered an error. if (radPack == null) { logger.debug("Nothing in the RADIUS packet."); throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } - // If we get back an AccessReject packet, login is denied. + // Received AccessReject packet, login is denied. else if (radPack instanceof AccessReject) { logger.debug("Login has been rejected by RADIUS server."); throw new GuacamoleInvalidCredentialsException("Authentication failed.", CredentialsInfo.USERNAME_PASSWORD); } - // If we receive an AccessChallenge package, the server needs more information - - // We create a new form/field with the challenge message. + // Received AccessChallenge packet, more credentials required to complete authentication else if (radPack instanceof AccessChallenge) { CredentialsInfo expectedCredentials = getRadiusChallenge(radPack); @@ -187,7 +183,7 @@ public class AuthenticationProviderService { throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); } - // If we receive AccessAccept, authentication has succeeded + // Received AccessAccept, authentication has succeeded else if (radPack instanceof AccessAccept) { try { AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); @@ -206,10 +202,9 @@ public class AuthenticationProviderService { } } - // The user responded to the challenge, send that back to the server + // This is a response to a challenge, so authenticate with that response else { - // Attempt to authenticate with response to challenge. try { radPack = radiusService.authenticate(credentials.getUsername(), request.getParameter(RadiusStateField.PARAMETER_NAME), @@ -224,14 +219,14 @@ public class AuthenticationProviderService { radiusService.disconnect(); } - // Check the server response, see if we get accepted or not + // Received AccessAccept, authentication succeeded. if (radPack instanceof AccessAccept) { AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); authenticatedUser.init(credentials); return authenticatedUser; } - // Authentication failed + // Authentication failed. else { logger.warn("RADIUS Challenge/Response authentication failed."); logger.debug("Received something other than AccessAccept packet from the RADIUS server."); From aa556763b201a2327b50ec977a7fb9f30da12d15 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 14 Jul 2017 21:55:39 -0400 Subject: [PATCH 53/76] GUACAMOLE-197: Fix LICENSE order and style. --- .../guacamole-auth-radius/src/licenses/LICENSE | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/licenses/LICENSE b/extensions/guacamole-auth-radius/src/licenses/LICENSE index fb195e1cb..7ad231d59 100644 --- a/extensions/guacamole-auth-radius/src/licenses/LICENSE +++ b/extensions/guacamole-auth-radius/src/licenses/LICENSE @@ -220,14 +220,6 @@ AOP Alliance (http://aopalliance.sourceforge.net/) Public Domain (bundled/aopalliance-1.0/LICENSE) -JRadius (https://github.com/coova/jradius) ------------------------------------------- - - Version: 1.1.5 - From: 'Coova Technologies, LLC' (https://coova.github.io) - License(s): - LGPL-2.1 (bundled/jradius-1.1.5/LICENSE) - BouncyCastle Crypto (https://www.bouncycastle.org/java.html) ------------------------------------------------------------ @@ -236,6 +228,7 @@ BouncyCastle Crypto (https://www.bouncycastle.org/java.html) License(s): The Bouncy Castle License (bundled/bouncycastle-1.44/LICENSE + Google Guice (https://github.com/google/guice) ---------------------------------------------- @@ -245,6 +238,15 @@ Google Guice (https://github.com/google/guice) Apache v2.0 (bundled/guice-3.0/COPYING) +JRadius (https://github.com/coova/jradius) +------------------------------------------ + + Version: 1.1.5 + From: 'Coova Technologies, LLC' (https://coova.github.io) + License(s): + LGPL-2.1 (bundled/jradius-1.1.5/LICENSE) + + JSR-330 / Dependency Injection for Java (http://code.google.com/p/atinject/) ---------------------------------------------------------------------------- From 015cb4aecdbb385f86bf8c9d9d0d0b315b460473 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 14 Jul 2017 22:24:11 -0400 Subject: [PATCH 54/76] GUACAMOLE-197: Tweak to comment --- .../guacamole/auth/radius/AuthenticationProviderService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index 2c3ace9eb..ad1ac060f 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -195,7 +195,7 @@ public class AuthenticationProviderService { } } - // Something unanticipated happened, so we panic and go back to login. + // Something unanticipated happened, so panic and go back to login. else { logger.error("Unexpected failure authenticating with RADIUS server."); throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); From 6acf032247dc9b5c5ba54fd02fbf34d550e98554 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Fri, 14 Jul 2017 22:35:31 -0400 Subject: [PATCH 55/76] GUACAMOLE-197: Reorganize authenticateUser to remove some duplicate code and make it easier to follow. --- .../radius/AuthenticationProviderService.java | 94 ++++++++----------- 1 file changed, 39 insertions(+), 55 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index ad1ac060f..fdb773715 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -160,51 +160,13 @@ public class AuthenticationProviderService { logger.debug("Error configuring RADIUS server.", e); throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } - - // No RadiusPacket is returned, we've encountered an error. - if (radPack == null) { - logger.debug("Nothing in the RADIUS packet."); - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - } - - // Received AccessReject packet, login is denied. - else if (radPack instanceof AccessReject) { - logger.debug("Login has been rejected by RADIUS server."); - throw new GuacamoleInvalidCredentialsException("Authentication failed.", CredentialsInfo.USERNAME_PASSWORD); - } - - // Received AccessChallenge packet, more credentials required to complete authentication - else if (radPack instanceof AccessChallenge) { - CredentialsInfo expectedCredentials = getRadiusChallenge(radPack); - - if (expectedCredentials == null) - throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); - - throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); - } - - // Received AccessAccept, authentication has succeeded - else if (radPack instanceof AccessAccept) { - try { - AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); - authenticatedUser.init(credentials); - return authenticatedUser; - } - finally { - radiusService.disconnect(); - } - } - - // Something unanticipated happened, so panic and go back to login. - else { - logger.error("Unexpected failure authenticating with RADIUS server."); - throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); + finally { + radiusService.disconnect(); } } - // This is a response to a challenge, so authenticate with that response + // This is a response to a previous challenge, authenticate with that. else { - try { radPack = radiusService.authenticate(credentials.getUsername(), request.getParameter(RadiusStateField.PARAMETER_NAME), @@ -218,21 +180,43 @@ public class AuthenticationProviderService { finally { radiusService.disconnect(); } - - // Received AccessAccept, authentication succeeded. - if (radPack instanceof AccessAccept) { - AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); - authenticatedUser.init(credentials); - return authenticatedUser; - } - - // Authentication failed. - else { - logger.warn("RADIUS Challenge/Response authentication failed."); - logger.debug("Received something other than AccessAccept packet from the RADIUS server."); - throw new GuacamoleInvalidCredentialsException("Authentication failed.", CredentialsInfo.USERNAME_PASSWORD); - } } + + // No RadiusPacket is returned, we've encountered an error. + if (radPack == null) { + logger.debug("Nothing in the RADIUS packet."); + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + } + + // Received AccessReject packet, login is denied. + else if (radPack instanceof AccessReject) { + logger.debug("Login has been rejected by RADIUS server."); + throw new GuacamoleInvalidCredentialsException("Authentication failed.", CredentialsInfo.USERNAME_PASSWORD); + } + + // Received AccessAccept, authentication has succeeded + else if (radPack instanceof AccessAccept) { + AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); + authenticatedUser.init(credentials); + return authenticatedUser; + } + + // Received AccessChallenge packet, more credentials required to complete authentication + else if (radPack instanceof AccessChallenge) { + CredentialsInfo expectedCredentials = getRadiusChallenge(radPack); + + if (expectedCredentials == null) + throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); + + throw new GuacamoleInsufficientCredentialsException("LOGIN.INFO_RADIUS_ADDL_REQUIRED", expectedCredentials); + } + + // Something unanticipated happened, so panic and go back to login. + else { + logger.error("Unexpected failure authenticating with RADIUS server."); + throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD); + } + } } From 52e9b6605d87a554d36918d151768971bb6ef57f Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sat, 15 Jul 2017 17:24:09 -0400 Subject: [PATCH 56/76] GUACAMOLE-197: Consistency for RADIUS vs. radius vs. Radius. --- .../guacamole/auth/radius/RadiusGuacamoleProperties.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index 15f4da207..5df6a467e 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -88,7 +88,7 @@ public class RadiusGuacamoleProperties { }; /** - * The number of retries when attempting a radius packet transaction. + * The number of retries when attempting a RADIUS packet transaction. */ public static final IntegerGuacamoleProperty RADIUS_RETRIES = new IntegerGuacamoleProperty() { @@ -98,7 +98,7 @@ public class RadiusGuacamoleProperties { }; /** - * The network timeout when attempting a radius packet transaction. + * The network timeout when attempting a RADIUS packet transaction. */ public static final IntegerGuacamoleProperty RADIUS_TIMEOUT = new IntegerGuacamoleProperty() { From 9a98400ce235917be371bff1eb8cacdbfb4a2010 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sat, 15 Jul 2017 17:26:10 -0400 Subject: [PATCH 57/76] GUACAMOLE-197: Remove unneeded iframe reference. --- .../src/main/resources/styles/radius.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css b/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css index 00d7988fa..92cb48ae9 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css +++ b/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css @@ -37,7 +37,3 @@ .radius-challenge-response-field input[type="submit"] { display: none !important; } - -.radius-challenge-response-field.loading iframe { - opacity: 0; -} From 84276af007d138ec2e108a084ab179119c0ba3f3 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sat, 15 Jul 2017 17:28:58 -0400 Subject: [PATCH 58/76] GUACAMOLE-197: Clean up property comments. --- .../guacamole/auth/radius/RadiusGuacamoleProperties.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index 5df6a467e..cee7e0e22 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -47,7 +47,7 @@ public class RadiusGuacamoleProperties { }; /** - * The port on the RADIUS server to connect to when accounting users. + * The port on the server to connect to when performing RADIUS accounting. */ public static final IntegerGuacamoleProperty RADIUS_ACCT_PORT = new IntegerGuacamoleProperty() { @@ -68,7 +68,7 @@ public class RadiusGuacamoleProperties { }; /** - * The shared secret of the RADIUS server to connect to when authenticating users. + * The shared secret to use when connecting to the RADIUS server. */ public static final StringGuacamoleProperty RADIUS_SHARED_SECRET = new StringGuacamoleProperty() { From fa820cb46f5abffd57b73a558db4cbedd7e6b065 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 16 Jul 2017 14:25:55 -0400 Subject: [PATCH 59/76] GUACAMOLE-197: Collapse authenticate methods together into single method, add minimal method for challenge/response. --- .../radius/AuthenticationProviderService.java | 8 +- .../auth/radius/RadiusConnectionService.java | 128 ++++-------------- 2 files changed, 34 insertions(+), 102 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index fdb773715..530de158f 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -153,7 +153,7 @@ public class AuthenticationProviderService { try { radPack = radiusService.authenticate(credentials.getUsername(), - credentials.getPassword()); + credentials.getPassword(), null); } catch (GuacamoleException e) { logger.error("Cannot configure RADIUS server: {}", e.getMessage()); @@ -168,9 +168,9 @@ public class AuthenticationProviderService { // This is a response to a previous challenge, authenticate with that. else { try { - radPack = radiusService.authenticate(credentials.getUsername(), - request.getParameter(RadiusStateField.PARAMETER_NAME), - challengeResponse); + radPack = radiusService.sendChallengeResponse(credentials.getUsername(), + challengeResponse, + request.getParameter(RadiusStateField.PARAMETER_NAME)); } catch (GuacamoleException e) { logger.error("Cannot configure RADIUS server: {}", e.getMessage()); diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index c3524cd9c..22c8d825e 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -164,91 +164,6 @@ public class RadiusConnectionService { } - /** - * Authenticate to the RADIUS server and return the response from the - * server. - * - * @param username - * The username for authentication. - * @param password - * The password for authentication. - * - * @return - * A RadiusPacket with the response of the server. - * - * @throws GuacamoleException - * If an error occurs while talking to the server. - */ - public RadiusPacket authenticate(String username, String password) - throws GuacamoleException { - - // If a username hasn't been provided, stop - if (username == null || username.isEmpty()) { - logger.warn("Anonymous access not allowed with RADIUS client."); - return null; - } - - // If a password hasn't been provided, stop - if (password == null || password.isEmpty()) { - logger.warn("Password required for RADIUS authentication."); - return null; - } - - // Create the connection and load the attribute dictionary - createRadiusConnection(); - AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); - - // If the client is null, we return null - something has gone wrong - if (radiusClient == null) - return null; - - RadiusAuthenticator radAuth = setupRadiusAuthenticator(); - - if (radAuth == null) - throw new GuacamoleException("Unknown RADIUS authentication protocol."); - - // Set up attributes, create the access request, and send the packet - try { - AttributeList radAttrs = new AttributeList(); - radAttrs.add(new Attr_UserName(username)); - radAttrs.add(new Attr_UserPassword(password)); - radAttrs.add(new Attr_CleartextPassword(password)); - - AccessRequest radAcc = new AccessRequest(radiusClient); - - // EAP-TTLS tunnels protected attributes inside the TLS layer - if (radAuth instanceof EAPTTLSAuthenticator) { - radAuth.setUsername(new Attr_UserName(username)); - ((EAPTTLSAuthenticator)radAuth).setTunneledAttributes(radAttrs); - } - else - radAcc.addAttributes(radAttrs); - - radAuth.setupRequest(radiusClient, radAcc); - radAuth.processRequest(radAcc); - RadiusResponse reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); - - // We receive a Challenge not asking for user input, so silently process the challenge - while((reply instanceof AccessChallenge) && (reply.findAttribute(Attr_ReplyMessage.TYPE) == null)) { - radAuth.processChallenge(radAcc, reply); - reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); - } - return reply; - } - - catch (RadiusException e) { - logger.error("Unable to complete authentication.", e.getMessage()); - logger.debug("Authentication with RADIUS failed.", e); - return null; - } - - catch (NoSuchAlgorithmException e) { - logger.error("No such RADIUS algorithm: {}", e.getMessage()); - logger.debug("Unknown RADIUS algorithm.", e); - return null; - } - } - /** * Authenticate to the RADIUS server using existing state and a response * @@ -265,7 +180,7 @@ public class RadiusConnectionService { * @throws GuacamoleException * If an error occurs while talking to the server. */ - public RadiusPacket authenticate(String username, String state, String response) + public RadiusPacket authenticate(String username, String secret, String state) throws GuacamoleException { // If a username wasn't passed, we quit @@ -274,15 +189,9 @@ public class RadiusConnectionService { return null; } - // If the state wasn't passed, we quit - if (state == null || state.isEmpty()) { - logger.warn("This method needs a previous RADIUS state to respond to."); - return null; - } - - // If the response wasn't passed, we quit - if (response == null || response.isEmpty()) { - logger.warn("Response required for RADIUS authentication."); + // If secret wasn't passed, we quit + if (secret == null || secret.isEmpty()) { + logger.warn("Password/secret required for RADIUS authentication."); return null; } @@ -303,9 +212,10 @@ public class RadiusConnectionService { try { AttributeList radAttrs = new AttributeList(); radAttrs.add(new Attr_UserName(username)); - radAttrs.add(new Attr_State(state)); - radAttrs.add(new Attr_UserPassword(response)); - radAttrs.add(new Attr_CleartextPassword(response)); + if (state != null && !state.isEmpty()) + radAttrs.add(new Attr_State(state)); + radAttrs.add(new Attr_UserPassword(secret)); + radAttrs.add(new Attr_CleartextPassword(secret)); AccessRequest radAcc = new AccessRequest(radiusClient); @@ -340,6 +250,28 @@ public class RadiusConnectionService { } } + public RadiusPacket sendChallengeResponse(String username, String response, String state) + throws GuacamoleException { + + if (username == null || username.isEmpty()) { + logger.error("Challenge/response to RADIUS requires a username."); + return null; + } + + if (state == null || state.isEmpty()) { + logger.error("Challenge/response to RADIUS requires a prior state."); + return null; + } + + if (response == null || response.isEmpty()) { + logger.error("Challenge/response to RADIUS requires a response."); + return null; + } + + return authenticate(username,response,state); + + } + /** * Disconnects the current RADIUS connection. */ From 249ea0776b4ac2fe178a03976252c283f9d05334 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 16 Jul 2017 14:40:49 -0400 Subject: [PATCH 60/76] GUACAMOLE-197: Move RadiusClient object to a return value instead of class-level object; properly clean up RADIUS connections. --- .../radius/AuthenticationProviderService.java | 6 ---- .../auth/radius/RadiusConnectionService.java | 30 +++++++------------ 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index 530de158f..eafdf830d 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -160,9 +160,6 @@ public class AuthenticationProviderService { logger.debug("Error configuring RADIUS server.", e); throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } - finally { - radiusService.disconnect(); - } } // This is a response to a previous challenge, authenticate with that. @@ -177,9 +174,6 @@ public class AuthenticationProviderService { logger.debug("Error configuring RADIUS server.", e); throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD); } - finally { - radiusService.disconnect(); - } } // No RadiusPacket is returned, we've encountered an error. diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 22c8d825e..9dd39a38d 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -63,11 +63,6 @@ public class RadiusConnectionService { private ConfigurationService confService; - /** - * The RADIUS client; - */ - private RadiusClient radiusClient; - /** * Creates a new instance of RadiusClient, configured with parameters * from guacamole.properties. @@ -76,11 +71,11 @@ public class RadiusConnectionService { * If an error occurs while parsing guacamole.properties, or if the * configuration of RadiusClient fails. */ - private void createRadiusConnection() { + private RadiusClient createRadiusConnection() { // Create the RADIUS client with the configuration parameters try { - radiusClient = new RadiusClient(InetAddress.getByName(confService.getRadiusServer()), + return new RadiusClient(InetAddress.getByName(confService.getRadiusServer()), confService.getRadiusSharedSecret(), confService.getRadiusAuthPort(), confService.getRadiusAcctPort(), @@ -99,6 +94,8 @@ public class RadiusConnectionService { logger.debug("Failed to communicate with host.", e); } + return null; + } /** @@ -110,7 +107,8 @@ public class RadiusConnectionService { * with parameters from guacamole.properties, or null if * configuration fails. */ - private RadiusAuthenticator setupRadiusAuthenticator() throws GuacamoleException { + private RadiusAuthenticator setupRadiusAuthenticator(RadiusClient radiusClient) + throws GuacamoleException { // If we don't have a radiusClient object, yet, don't go any further. if (radiusClient == null) { @@ -196,7 +194,7 @@ public class RadiusConnectionService { } // Create the RADIUS connection and set up the dictionary - createRadiusConnection(); + RadiusClient radiusClient = createRadiusConnection(); AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); // Client failed to set up, so we return null @@ -204,7 +202,7 @@ public class RadiusConnectionService { return null; // Set up the RadiusAuthenticator - RadiusAuthenticator radAuth = setupRadiusAuthenticator(); + RadiusAuthenticator radAuth = setupRadiusAuthenticator(radiusClient); if (radAuth == null) throw new GuacamoleException("Unknown RADIUS authentication protocol."); @@ -248,6 +246,9 @@ public class RadiusConnectionService { logger.debug("Unknown RADIUS algorithm.", e); return null; } + finally { + radiusClient.close(); + } } public RadiusPacket sendChallengeResponse(String username, String response, String state) @@ -272,13 +273,4 @@ public class RadiusConnectionService { } - /** - * Disconnects the current RADIUS connection. - */ - public void disconnect() { - - radiusClient.close(); - - } - } From 60ddc82aff7d6447dc4708d76dd83860aa1951f0 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 16 Jul 2017 15:32:11 -0400 Subject: [PATCH 61/76] GUACAMOLE-197: Move variable declarations for TLS into correct context. --- .../auth/radius/RadiusConnectionService.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 9dd39a38d..fa9a0b61a 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -117,15 +117,6 @@ public class RadiusConnectionService { return null; } - // Pull configuration parameters from guacamole.properties - LocalEnvironment guacEnv = new LocalEnvironment(); - String guacHome = guacEnv.getGuacamoleHome().getAbsolutePath(); - String caFile = confService.getRadiusCAFile(); - String caPassword = confService.getRadiusCAPassword(); - String keyFile = confService.getRadiusKeyFile(); - String keyPassword = confService.getRadiusKeyPassword(); - String innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); - RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol()); if (radAuth == null) throw new GuacamoleException("Could not get a valid RadiusAuthenticator for specified protocol: " + confService.getRadiusAuthProtocol()); @@ -135,6 +126,15 @@ public class RadiusConnectionService { radAuth instanceof EAPTLSAuthenticator || radAuth instanceof EAPTTLSAuthenticator) { + // Pull TLS configuration parameters from guacamole.properties + LocalEnvironment guacEnv = new LocalEnvironment(); + String guacHome = guacEnv.getGuacamoleHome(); + String caFile = confService.getRadiusCAFile(); + String caPassword = confService.getRadiusCAPassword(); + String keyFile = confService.getRadiusKeyFile(); + String keyPassword = confService.getRadiusKeyPassword(); + String innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); + if (caFile != null) { ((EAPTLSAuthenticator)radAuth).setCaFile((new File(guacHome, caFile)).toString()); ((EAPTLSAuthenticator)radAuth).setCaFileType(confService.getRadiusCAType()); From 67df52ab0b08afc0b182f3505a5d41a5cfdb65d5 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 17 Jul 2017 13:33:42 -0400 Subject: [PATCH 62/76] GUACAMOLE-197: Fix build issue introduced by moving variable context. --- .../apache/guacamole/auth/radius/RadiusConnectionService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index fa9a0b61a..345a03d11 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -128,12 +128,11 @@ public class RadiusConnectionService { // Pull TLS configuration parameters from guacamole.properties LocalEnvironment guacEnv = new LocalEnvironment(); - String guacHome = guacEnv.getGuacamoleHome(); + File guacHome = guacEnv.getGuacamoleHome(); String caFile = confService.getRadiusCAFile(); String caPassword = confService.getRadiusCAPassword(); String keyFile = confService.getRadiusKeyFile(); String keyPassword = confService.getRadiusKeyPassword(); - String innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); if (caFile != null) { ((EAPTLSAuthenticator)radAuth).setCaFile((new File(guacHome, caFile)).toString()); @@ -152,6 +151,7 @@ public class RadiusConnectionService { // If we're using EAP-TTLS, we need to define tunneled protocol if (radAuth instanceof EAPTTLSAuthenticator) { + String innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); if (innerProtocol == null) throw new GuacamoleException("Trying to use EAP-TTLS, but no inner protocol specified."); From f84e3b88c6e6e91b9142f86352eec865c139747e Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 10 Oct 2017 20:35:51 -0400 Subject: [PATCH 63/76] GUACAMOLE-197: Add override for module shutdown() method. --- .../guacamole/auth/radius/RadiusAuthenticationProvider.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java index 499f3c1e4..f2227406d 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusAuthenticationProvider.java @@ -68,6 +68,11 @@ public class RadiusAuthenticationProvider implements AuthenticationProvider { return null; } + @Override + public void shutdown() { + // Do nothing + } + @Override public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { From 45f9815eed43896061f9ed35e6fca80718142806 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sun, 19 Nov 2017 17:39:28 -0500 Subject: [PATCH 64/76] GUACAMOLE-197: Add $injector to AngularJS controllers. --- .../main/resources/controllers/radiusResponseController.js | 4 ++-- .../src/main/resources/controllers/radiusStateController.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js index 9e363debc..ddc7e3495 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js @@ -21,8 +21,8 @@ * Controller for the "GUAC_RADIUS_CHALLENGE_RESPONSE" field which * passes the RADIUS server challenge to the user and takes the response. */ -angular.module('guacRadius').controller('radiusResponseController', ['$scope', '$element', - function radiusResponseController($scope, $element) { +angular.module('guacRadius').controller('radiusResponseController', ['$scope', '$injector', + function radiusResponseController($scope, $injector) { // Populate the reply message field $scope.radiusPlaceholder = $scope.field.replyMsg; diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js index 726f2f543..fb956abb3 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusStateController.js @@ -22,8 +22,8 @@ * the RADIUS server state to maintain the session with the RADIUS * server. */ -angular.module('guacRadius').controller('radiusStateController', ['$scope', '$element', - function radiusStateController($scope, $element) { +angular.module('guacRadius').controller('radiusStateController', ['$scope', '$injector', + function radiusStateController($scope, $injector) { // Populate the hidden field for the connection state $scope.model = $scope.field.radiusState; From adc574f890f736bede0ced125ce8a627d7d55a54 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 1 Jan 2018 17:29:55 -0500 Subject: [PATCH 65/76] GUACAMOLE-197: Bump version to 0.9.14 and remove incubating stuff. --- extensions/guacamole-auth-radius/pom.xml | 6 +++--- extensions/guacamole-auth-radius/src/licenses/DISCLAIMER | 7 ------- .../src/main/resources/guac-manifest.json | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 extensions/guacamole-auth-radius/src/licenses/DISCLAIMER diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index 69d171d40..f1c26f1e2 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -26,7 +26,7 @@ org.apache.guacamole guacamole-auth-radius jar - 0.9.13-incubating + 0.9.14 guacamole-auth-radius http://guacamole.incubator.apache.org/ @@ -190,7 +190,7 @@ org.apache.guacamole guacamole-common - 0.9.10-incubating + 0.9.14 provided @@ -198,7 +198,7 @@ org.apache.guacamole guacamole-ext - 0.9.13-incubating + 0.9.14 provided diff --git a/extensions/guacamole-auth-radius/src/licenses/DISCLAIMER b/extensions/guacamole-auth-radius/src/licenses/DISCLAIMER deleted file mode 100644 index 1a9c3be8d..000000000 --- a/extensions/guacamole-auth-radius/src/licenses/DISCLAIMER +++ /dev/null @@ -1,7 +0,0 @@ -Apache Guacamole is an effort undergoing incubation at The Apache Software -Foundation (ASF). Incubation is required of all newly accepted projects until a -further review indicates that the infrastructure, communications, and decision -making process have stabilized in a manner consistent with other successful ASF -projects. While incubation status is not necessarily a reflection of the -completeness or stability of the code, it does indicate that the project has -yet to be fully endorsed by the ASF. diff --git a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json index f8c011104..4f4bca058 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json +++ b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json @@ -1,6 +1,6 @@ { - "guacamoleVersion" : "0.9.13-incubating", + "guacamoleVersion" : "0.9.14", "name" : "RADIUS Authentication Backend", "namespace" : "radius", From aba9d839565f78f55d419a68ea1fc57992bac443 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 15 Jan 2018 10:27:16 -0500 Subject: [PATCH 66/76] GUACAMOLE-197: Remove last traces of incubating. --- extensions/guacamole-auth-radius/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index f1c26f1e2..9d27a104f 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -28,7 +28,7 @@ jar 0.9.14 guacamole-auth-radius - http://guacamole.incubator.apache.org/ + http://guacamole.apache.org/ UTF-8 From 440a74e71a272adfe615a3eee87f5c41fd50b277 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 15 Jan 2018 10:42:46 -0500 Subject: [PATCH 67/76] GUACAMOLE-197: Clean up imports in various classes. --- .../auth/radius/AuthenticationProviderService.java | 10 ---------- .../guacamole/auth/radius/ConfigurationService.java | 2 -- .../guacamole/auth/radius/RadiusConnectionService.java | 9 +++++---- .../guacamole/auth/radius/form/RadiusStateField.java | 3 --- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java index eafdf830d..ae9f6bfd7 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java @@ -36,14 +36,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.jradius.dictionary.Attr_State; import net.jradius.dictionary.Attr_ReplyMessage; -import net.jradius.exception.UnknownAttributeException; import net.jradius.packet.RadiusPacket; import net.jradius.packet.AccessAccept; import net.jradius.packet.AccessChallenge; import net.jradius.packet.AccessReject; -import net.jradius.packet.AccessRequest; -import net.jradius.packet.AccessResponse; -import net.jradius.packet.attribute.AttributeList; import net.jradius.packet.attribute.RadiusAttribute; /** @@ -63,12 +59,6 @@ public class AuthenticationProviderService { @Inject private RadiusConnectionService radiusService; - /** - * Service for retrieving RADIUS server configuration information. - */ - @Inject - private ConfigurationService confService; - /** * Provider for AuthenticatedUser objects. */ diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 0cfe26b0e..73241ea28 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -20,8 +20,6 @@ package org.apache.guacamole.auth.radius; import com.google.inject.Inject; -import java.util.Collections; -import java.util.List; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.environment.Environment; diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 345a03d11..52e735ef6 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -22,22 +22,23 @@ package org.apache.guacamole.auth.radius; import com.google.inject.Inject; import java.io.File; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.GuacamoleUnsupportedException; import org.apache.guacamole.environment.LocalEnvironment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.jradius.client.RadiusClient; +import net.jradius.dictionary.Attr_CleartextPassword; +import net.jradius.dictionary.Attr_ReplyMessage; +import net.jradius.dictionary.Attr_State; +import net.jradius.dictionary.Attr_UserName; +import net.jradius.dictionary.Attr_UserPassword; import net.jradius.exception.RadiusException; import net.jradius.packet.RadiusPacket; import net.jradius.packet.AccessRequest; -import net.jradius.dictionary.*; import net.jradius.packet.attribute.AttributeList; -import net.jradius.packet.attribute.RadiusAttribute; import net.jradius.client.auth.EAPTLSAuthenticator; import net.jradius.client.auth.EAPTTLSAuthenticator; import net.jradius.client.auth.RadiusAuthenticator; diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java index 51d57fece..c7c06c492 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java @@ -20,9 +20,6 @@ package org.apache.guacamole.auth.radius.form; import org.apache.guacamole.form.Field; -import org.codehaus.jackson.annotate.JsonProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The invisible field that stores the state of the RADIUS From 8cf66bc3df52c82fba32dd91765dd6662746441a Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 15 Jan 2018 10:43:55 -0500 Subject: [PATCH 68/76] GUACAMOLE-197: Finish cleaning unused imports. --- .../auth/radius/form/RadiusChallengeResponseField.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java index 0b8944b31..7f407aaf0 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -20,9 +20,6 @@ package org.apache.guacamole.auth.radius.form; import org.apache.guacamole.form.Field; -import org.codehaus.jackson.annotate.JsonProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * A form used to prompt the user for additional information when From ab90606c8197407849f205dd0f688d8b6f747a89 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 15 Jan 2018 15:02:37 -0500 Subject: [PATCH 69/76] GUACAMOLE-197: Clean up comments and configured parameters. --- .../auth/radius/ConfigurationService.java | 54 ++++++++++------- .../auth/radius/RadiusConnectionService.java | 59 +++++++++++++++---- .../radius/RadiusGuacamoleProperties.java | 8 +-- .../form/RadiusChallengeResponseField.java | 21 ++++--- .../auth/radius/form/RadiusStateField.java | 11 +++- .../controllers/radiusResponseController.js | 2 +- 6 files changed, 108 insertions(+), 47 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index 73241ea28..c903a3880 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -53,8 +53,9 @@ public class ConfigurationService { } /** - * Returns the authentication port of the RADIUS server configured with - * guacamole.properties. + * Returns the UDP port that will be used to communicate authentication + * and authorization information to the RADIUS server, as configured in + * guacamole.properties. By default this will be 1812. * * @return * The authentication port of the RADIUS server, as configured with @@ -71,8 +72,9 @@ public class ConfigurationService { } /** - * Returns the accounting port of the RADIUS server configured with - * guacamole.properties. + * Returns the UDP port that will be used to communicate accounting + * information to the RADIUS server, as configured in + * guacamole.properties. The default is 1813. * * @return * The accouting port of the RADIUS server, as configured with @@ -89,8 +91,9 @@ public class ConfigurationService { } /** - * Returns the shared secret of the RADIUS server configured with - * guacamole.properties. + * Returns the shared secret used to communicate with the RADIUS server, + * as configured in guacamole.properties. This must match the value + * in the RADIUS server configuration. * * @return * The shared secret of the RADIUS server, as configured with @@ -106,8 +109,11 @@ public class ConfigurationService { } /** - * Returns the authentication protocol of the RADIUS server - * from guacamole.properties. + * Returns the authentication protocol Guacamole should use when + * communicating with the RADIUS server, as configured in + * guacamole.properties. This must match the configuration + * of the RADIUS server, so that the RADIUS server and Guacamole + * client are "speaking the same language." * * @return * The authentication protocol of the RADIUS server, @@ -123,8 +129,8 @@ public class ConfigurationService { } /** - * Returns the number of retries for connecting to the RADIUS server - * from guacamole.properties. + * Returns the maximum number of retries for connecting to the RADIUS server + * from guacamole.properties. The default number of retries is 5. * * @return * The number of retries for connection to the RADIUS server, @@ -133,19 +139,19 @@ public class ConfigurationService { * @throws GuacamoleException * If guacamole.properties cannot be parsed. */ - public int getRadiusRetries() throws GuacamoleException { + public int getRadiusMaxRetries() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_RETRIES, + RadiusGuacamoleProperties.RADIUS_MAX_RETRIES, 5 ); } /** - * Returns the timeout for connecting to the RADIUS server - * from guacamole.properties. + * Returns the timeout, in seconds, for connecting to the RADIUS server + * from guacamole.properties. The default timeout is 60 seconds. * * @return - * The timeout for connection to the RADIUS server, + * The timeout, in seconds, for connection to the RADIUS server, * from guacamole.properties. * * @throws GuacamoleException @@ -159,8 +165,9 @@ public class ConfigurationService { } /** - * Returns the CA file for validating certificates for - * encrypted connections as specified in guacamole.properties + * Returns the CA file for validating certificates for encrypted + * connections to the RADIUS server, as configured in + * guacamole.properties. * * @return * The file name for the CA file for validating @@ -178,7 +185,8 @@ public class ConfigurationService { /** * Returns the key file for the client for creating encrypted * connections to RADIUS servers as specified in - * guacamole.properties. + * guacamole.properties. By default a file called radius.pem + * is used. * * @return * The file name for the client certificate/key pair @@ -213,7 +221,8 @@ public class ConfigurationService { /** * Returns the type of store that the CA file represents * so that it can be correctly processed by the RADIUS - * library, as configured in guacamole.properties. + * library, as configured in guacamole.properties. By + * default the pem type is used. * * @return * The type of store that the CA file is encoded @@ -248,7 +257,8 @@ public class ConfigurationService { /** * Returns the type of store that the key file represents * so that it can be correctly processed by the RADIUS - * library, as configured in guacamole.properties. + * library, as configured in guacamole.properties. By + * default the pem type is used. * * @return * The type of store that the key file is encoded @@ -268,7 +278,9 @@ public class ConfigurationService { * Returns the boolean value of whether or not the * RADIUS library should trust all server certificates * or should validate them against known CA certificates, - * as configured in guacamole.properties. + * as configured in guacamole.properties. By default + * this is false, indicating that server certificates + * must be validated against a known good CA. * * @return * True if the RADIUS client should trust all diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index 52e735ef6..c73bf66ab 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -26,6 +26,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.environment.LocalEnvironment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,11 +69,15 @@ public class RadiusConnectionService { * Creates a new instance of RadiusClient, configured with parameters * from guacamole.properties. * + * @return + * A RadiusClient instance, configured with server, shared secret, + * ports, and timeout, as configured in guacamole.properties. + * * @throws GuacamoleException * If an error occurs while parsing guacamole.properties, or if the * configuration of RadiusClient fails. */ - private RadiusClient createRadiusConnection() { + private RadiusClient createRadiusConnection() throws GuacamoleException { // Create the RADIUS client with the configuration parameters try { @@ -82,31 +87,34 @@ public class RadiusConnectionService { confService.getRadiusAcctPort(), confService.getRadiusTimeout()); } - catch (GuacamoleException e) { - logger.error("Unable to initialize RADIUS client: {}", e.getMessage()); - logger.debug("Failed to init RADIUS client.", e); - } catch (UnknownHostException e) { - logger.error("Unable to resolve host: {}", e.getMessage()); logger.debug("Failed to resolve host.", e); + throw new GuacamoleServerException("Unable to resolve RADIUS server host.", e); } catch (IOException e) { - logger.error("Unable to communicate with host: {}", e.getMessage()); logger.debug("Failed to communicate with host.", e); + throw new GuacamoleServerException("Failed to communicate with RADIUS server.", e); } - return null; - } /** * Creates a new instance of RadiusAuthentictor, configured with * parameters specified within guacamole.properties. * + * @param radiusClient + * A RadiusClient instance that has been initialized to + * communicate with a RADIUS server. + * * @return * A new RadiusAuthenticator instance which has been configured * with parameters from guacamole.properties, or null if * configuration fails. + * + * @throws GuacamoleException + * If the configuration cannot be read or the inner protocol is + * not configured when the client is set up for a tunneled + * RADIUS connection. */ private RadiusAuthenticator setupRadiusAuthenticator(RadiusClient radiusClient) throws GuacamoleException { @@ -168,10 +176,13 @@ public class RadiusConnectionService { * * @param username * The username for the authentication + * + * @param secret + * The secret, usually a password or challenge response, to send + * to authenticate to the RADIUS server. + * * @param state * The previous state of the RADIUS connection - * @param response - * The response to the RADIUS challenge * * @return * A RadiusPacket with the response of the server. @@ -228,12 +239,12 @@ public class RadiusConnectionService { radAuth.setupRequest(radiusClient, radAcc); radAuth.processRequest(radAcc); - RadiusResponse reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + RadiusResponse reply = radiusClient.sendReceive(radAcc, confService.getRadiusMaxRetries()); // We receive a Challenge not asking for user input, so silently process the challenge while((reply instanceof AccessChallenge) && (reply.findAttribute(Attr_ReplyMessage.TYPE) == null)) { radAuth.processChallenge(radAcc, reply); - reply = radiusClient.sendReceive(radAcc, confService.getRadiusRetries()); + reply = radiusClient.sendReceive(radAcc, confService.getRadiusMaxRetries()); } return reply; } @@ -252,6 +263,28 @@ public class RadiusConnectionService { } } + /** + * Send a challenge response to the RADIUS server by validating the input and + * then sending it along to the authenticate method. + * + * @param username + * The username to send to the RADIUS server for authentication. + * + * @param response + * The response phrase to send to the RADIUS server in response to the + * challenge previously provided. + * + * @param state + * The state data provided by the RADIUS server in order to continue + * the RADIUS conversation. + * + * @return + * A RadiusPacket containing the server's response to the authentication + * attempt. + * + * @throws GuacamoleException + * If an error is encountered trying to talk to the RADIUS server. + */ public RadiusPacket sendChallengeResponse(String username, String response, String state) throws GuacamoleException { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index cee7e0e22..49fa1b687 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -88,17 +88,17 @@ public class RadiusGuacamoleProperties { }; /** - * The number of retries when attempting a RADIUS packet transaction. + * The maximum number of retries when attempting a RADIUS packet transaction. */ - public static final IntegerGuacamoleProperty RADIUS_RETRIES = new IntegerGuacamoleProperty() { + public static final IntegerGuacamoleProperty RADIUS_MAX_RETRIES = new IntegerGuacamoleProperty() { @Override - public String getName() { return "radius-retries"; } + public String getName() { return "radius-max-retries"; } }; /** - * The network timeout when attempting a RADIUS packet transaction. + * The network timeout, in seconds, when attempting a RADIUS packet transaction. */ public static final IntegerGuacamoleProperty RADIUS_TIMEOUT = new IntegerGuacamoleProperty() { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java index 7f407aaf0..32ceb90de 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusChallengeResponseField.java @@ -41,21 +41,28 @@ public class RadiusChallengeResponseField extends Field { /** * The message the RADIUS server sent back in the challenge. */ - private final String replyMsg; + private final String challenge; /** - * Initialize the field with the reply message and the state. + * Initialize the field with the challenge sent back by the RADIUS server. + * + * @param challenge + * The challenge message sent back by the RADIUS server. */ - public RadiusChallengeResponseField(String replyMsg) { + public RadiusChallengeResponseField(String challenge) { super(PARAMETER_NAME, RADIUS_FIELD_TYPE); - this.replyMsg = replyMsg; + this.challenge = challenge; } /** - * Get the value of the replyMsg field. + * Get the challenge sent by the RADIUS server. + * + * @return + * A String that indicates the challenge returned + * by the RADIUS server. */ - public String getReplyMsg() { - return replyMsg; + public String getChallenge() { + return challenge; } } diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java index c7c06c492..201df2cd0 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/form/RadiusStateField.java @@ -45,7 +45,10 @@ public class RadiusStateField extends Field { private final String radiusState; /** - * Initialize the field with the reply message and the state. + * Initialize the field with the state returned by the RADIUS server. + * + * @param radiusState + * The state returned by the RADIUS server. */ public RadiusStateField(String radiusState) { super(PARAMETER_NAME, RADIUS_FIELD_TYPE); @@ -53,6 +56,12 @@ public class RadiusStateField extends Field { } + /** + * Get the state provided by the RADIUS server. + * + * @return + * The state provided by the RADIUS server. + */ public String getRadiusState() { return radiusState; } diff --git a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js index ddc7e3495..4782b208f 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js +++ b/extensions/guacamole-auth-radius/src/main/resources/controllers/radiusResponseController.js @@ -25,6 +25,6 @@ angular.module('guacRadius').controller('radiusResponseController', ['$scope', ' function radiusResponseController($scope, $injector) { // Populate the reply message field - $scope.radiusPlaceholder = $scope.field.replyMsg; + $scope.radiusPlaceholder = $scope.field.challenge; }]); From b0284ec7104de603132230e8d642043e3fee6de0 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Mon, 15 Jan 2018 15:16:02 -0500 Subject: [PATCH 70/76] GUACAMOLE-197: Clean up HTML and translations, remove unnecessary CSS files. --- extensions/guacamole-auth-radius/pom.xml | 12 ------ .../src/main/resources/guac-manifest.json | 4 -- .../src/main/resources/styles/radius.css | 39 ------------------- .../resources/templates/radiusStateField.html | 2 +- .../src/main/resources/translations/en.json | 2 - 5 files changed, 1 insertion(+), 58 deletions(-) delete mode 100644 extensions/guacamole-auth-radius/src/main/resources/styles/radius.css diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml index 9d27a104f..d46e0b1be 100644 --- a/extensions/guacamole-auth-radius/pom.xml +++ b/extensions/guacamole-auth-radius/pom.xml @@ -88,18 +88,6 @@ ${basedir}/src/main/resources ${project.build.directory}/classes - / - / - radius.css - - - license.txt - - - - **/*.css - - / / radius.js diff --git a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json index 4f4bca058..be6e2a264 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json +++ b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json @@ -17,10 +17,6 @@ "radius.min.js" ], - "css" : [ - "radius.min.css" - ], - "resources" : { "templates/radiusChallengeResponseField.html" : "text/html" } diff --git a/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css b/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css deleted file mode 100644 index 92cb48ae9..000000000 --- a/extensions/guacamole-auth-radius/src/main/resources/styles/radius.css +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -.radius-challenge-response-field-container { - height: 100%; - width: 100%; - position: fixed; - left: 0; - top: 0; - display: table; - background: white; -} - -.radius-challenge-response-field { - width: 100%; - display: table-cell; - vertical-align: middle; -} - -.radius-challenge-response-field input[type="submit"] { - display: none !important; -} diff --git a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html index be8067c06..bfd9c4f31 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html +++ b/extensions/guacamole-auth-radius/src/main/resources/templates/radiusStateField.html @@ -1 +1 @@ - + diff --git a/extensions/guacamole-auth-radius/src/main/resources/translations/en.json b/extensions/guacamole-auth-radius/src/main/resources/translations/en.json index 2459b8b37..c068a70af 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/translations/en.json +++ b/extensions/guacamole-auth-radius/src/main/resources/translations/en.json @@ -7,8 +7,6 @@ "LOGIN" : { "FIELD_HEADER_GUAC_RADIUS_CHALLENGE_RESPONSE" : "", "FIELD_HEADER_GUAC_RADIUS_STATE" : "", - "INFO_RADIUS_RESPONSE_INCORRECT" : "RADIUS response incorrect.", - "INFO_RADIUS_AUTH_REQUIRED" : "Please authenticate with RADIUS to continue.", "INFO_RADIUS_ADDL_REQUIRED" : "Please supply additional credentials" } From b7db93c7296a9f79cfe264d63cc30d1c3adbc7aa Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 16 Jan 2018 14:22:52 -0500 Subject: [PATCH 71/76] GUACAMOLE-197: Handle extra login fields when dealing with failed authentication. --- guacamole/src/main/webapp/app/login/directives/login.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/guacamole/src/main/webapp/app/login/directives/login.js b/guacamole/src/main/webapp/app/login/directives/login.js index cc820b81e..97d10684a 100644 --- a/guacamole/src/main/webapp/app/login/directives/login.js +++ b/guacamole/src/main/webapp/app/login/directives/login.js @@ -66,6 +66,7 @@ angular.module('login').directive('guacLogin', [function guacLogin() { var Field = $injector.get('Field'); // Required services + var $log = $injector.get('$log'); var $route = $injector.get('$route'); var authenticationService = $injector.get('authenticationService'); @@ -168,13 +169,17 @@ angular.module('login').directive('guacLogin', [function guacLogin() { else $scope.loginError = error.translatableMessage; - // Clear all visible password fields + // Clear all remaining fields that are not username fields angular.forEach($scope.remainingFields, function clearEnteredValueIfPassword(field) { // Remove entered value only if field is a password field - if (field.type === Field.Type.PASSWORD && field.name in $scope.enteredValues) + if (field.type === Field.Type.PASSWORD) $scope.enteredValues[field.name] = ''; + // If field is not username field and not password field, delete it. + else if (field.type !== Field.Type.USERNAME) + delete $scope.enteredValues[field.name]; + }); } From b204a4c708c0235db9a1825699e8724a8a9853a8 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 16 Jan 2018 14:26:14 -0500 Subject: [PATCH 72/76] GUACAMOLE-197: Remove debugging code. --- guacamole/src/main/webapp/app/login/directives/login.js | 1 - 1 file changed, 1 deletion(-) diff --git a/guacamole/src/main/webapp/app/login/directives/login.js b/guacamole/src/main/webapp/app/login/directives/login.js index 97d10684a..f918a555e 100644 --- a/guacamole/src/main/webapp/app/login/directives/login.js +++ b/guacamole/src/main/webapp/app/login/directives/login.js @@ -66,7 +66,6 @@ angular.module('login').directive('guacLogin', [function guacLogin() { var Field = $injector.get('Field'); // Required services - var $log = $injector.get('$log'); var $route = $injector.get('$route'); var authenticationService = $injector.get('authenticationService'); From 4a57012f9da8631c15a64ebc93a35e569e0995db Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 16 Jan 2018 14:27:34 -0500 Subject: [PATCH 73/76] GUACAMOLE-197: Revert some unnecessary code changes. --- guacamole/src/main/webapp/app/login/directives/login.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guacamole/src/main/webapp/app/login/directives/login.js b/guacamole/src/main/webapp/app/login/directives/login.js index f918a555e..02aa1ac37 100644 --- a/guacamole/src/main/webapp/app/login/directives/login.js +++ b/guacamole/src/main/webapp/app/login/directives/login.js @@ -172,11 +172,11 @@ angular.module('login').directive('guacLogin', [function guacLogin() { angular.forEach($scope.remainingFields, function clearEnteredValueIfPassword(field) { // Remove entered value only if field is a password field - if (field.type === Field.Type.PASSWORD) + if (field.type === Field.Type.PASSWORD && field.name in $scope.enteredValues) $scope.enteredValues[field.name] = ''; // If field is not username field and not password field, delete it. - else if (field.type !== Field.Type.USERNAME) + else if (field.type !== Field.Type.USERNAME && field.name in $scope.enteredValues) delete $scope.enteredValues[field.name]; }); From 037913ac739097ec82d0a950ee9935883595de36 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 30 Jan 2018 09:50:21 -0500 Subject: [PATCH 74/76] GUACAMOLE-197: Handle all non-username fields identically. --- guacamole/src/main/webapp/app/login/directives/login.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/guacamole/src/main/webapp/app/login/directives/login.js b/guacamole/src/main/webapp/app/login/directives/login.js index 02aa1ac37..51c366f95 100644 --- a/guacamole/src/main/webapp/app/login/directives/login.js +++ b/guacamole/src/main/webapp/app/login/directives/login.js @@ -171,12 +171,8 @@ angular.module('login').directive('guacLogin', [function guacLogin() { // Clear all remaining fields that are not username fields angular.forEach($scope.remainingFields, function clearEnteredValueIfPassword(field) { - // Remove entered value only if field is a password field - if (field.type === Field.Type.PASSWORD && field.name in $scope.enteredValues) - $scope.enteredValues[field.name] = ''; - - // If field is not username field and not password field, delete it. - else if (field.type !== Field.Type.USERNAME && field.name in $scope.enteredValues) + // If field is not username field, delete it. + if (field.type !== Field.Type.USERNAME && field.name in $scope.enteredValues) delete $scope.enteredValues[field.name]; }); From 789da685745ebaf2c54096b17b5d6ddbf06bd7ac Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 30 Jan 2018 18:33:13 -0500 Subject: [PATCH 75/76] GUACAMOLE-197: Change RADIUS server to RADIUS hostname. --- .../apache/guacamole/auth/radius/ConfigurationService.java | 2 +- .../guacamole/auth/radius/RadiusGuacamoleProperties.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java index c903a3880..97cc39ca0 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/ConfigurationService.java @@ -47,7 +47,7 @@ public class ConfigurationService { */ public String getRadiusServer() throws GuacamoleException { return environment.getProperty( - RadiusGuacamoleProperties.RADIUS_SERVER, + RadiusGuacamoleProperties.RADIUS_HOSTNAME, "localhost" ); } diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java index 49fa1b687..144d824a5 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusGuacamoleProperties.java @@ -58,12 +58,12 @@ public class RadiusGuacamoleProperties { /** - * The hostname or ip of the RADIUS server to connect to when authenticating users. + * The hostname or IP address of the RADIUS server to connect to when authenticating users. */ - public static final StringGuacamoleProperty RADIUS_SERVER = new StringGuacamoleProperty() { + public static final StringGuacamoleProperty RADIUS_HOSTNAME = new StringGuacamoleProperty() { @Override - public String getName() { return "radius-server"; } + public String getName() { return "radius-hostname"; } }; From dcb9e46e4382395ea37638a7dcd23b73639117f0 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 30 Jan 2018 18:33:59 -0500 Subject: [PATCH 76/76] GUACAMOLE-197: Add/fix fields in guac manifest. --- .../src/main/resources/guac-manifest.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json index be6e2a264..f85ab1f4a 100644 --- a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json +++ b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json @@ -18,7 +18,8 @@ ], "resources" : { - "templates/radiusChallengeResponseField.html" : "text/html" + "templates/radiusResponseField.html" : "text/html", + "templates/radiusStateField.html" : "text/html" } }