mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-1289: Merge upgrade to Duo API v4.
This commit is contained in:
17
doc/licenses/apache-commons-codec-1.11/NOTICE
Normal file
17
doc/licenses/apache-commons-codec-1.11/NOTICE
Normal file
@@ -0,0 +1,17 @@
|
||||
Apache Commons Codec
|
||||
Copyright 2002-2020 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (https://www.apache.org/).
|
||||
|
||||
src/test/org/apache/commons/codec/language/DoubleMetaphoneTest.java
|
||||
contains test data from http://aspell.net/test/orig/batch0.tab.
|
||||
Copyright (C) 2002 Kevin Atkinson (kevina@gnu.org)
|
||||
|
||||
===============================================================================
|
||||
|
||||
The content of package org.apache.commons.codec.language.bm has been translated
|
||||
from the original php source code available at http://stevemorse.org/phoneticinfo.htm
|
||||
with permission from the original authors.
|
||||
Original source copyright:
|
||||
Copyright (c) 2008 Alexander Beider & Stephen P. Morse.
|
8
doc/licenses/apache-commons-codec-1.11/README
Normal file
8
doc/licenses/apache-commons-codec-1.11/README
Normal file
@@ -0,0 +1,8 @@
|
||||
Apache Commons Codec (http://commons.apache.org/proper/commons-codec/)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Version: 1.11
|
||||
From: 'Apache Software Foundation' (https://www.apache.org/)
|
||||
License(s):
|
||||
Apache v2.0
|
||||
|
@@ -0,0 +1 @@
|
||||
commons-codec:commons-codec:jar:1.11
|
25
doc/licenses/duo-universal-sdk-1.1.3/LICENSE
Normal file
25
doc/licenses/duo-universal-sdk-1.1.3/LICENSE
Normal file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2022 Cisco Systems, Inc. and/or its affiliates
|
||||
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.
|
8
doc/licenses/duo-universal-sdk-1.1.3/README
Normal file
8
doc/licenses/duo-universal-sdk-1.1.3/README
Normal file
@@ -0,0 +1,8 @@
|
||||
Duo Universal SDK for Java (https://duo.com/docs/duoweb)
|
||||
--------------------------------------------------------
|
||||
|
||||
Version: 1.1.3
|
||||
From: 'Cisco Systems'
|
||||
License(s):
|
||||
Duo License (bundled/duo-universal-sdk-1.1.3/LICENSE)
|
||||
|
1
doc/licenses/duo-universal-sdk-1.1.3/dep-coordinates.txt
Normal file
1
doc/licenses/duo-universal-sdk-1.1.3/dep-coordinates.txt
Normal file
@@ -0,0 +1 @@
|
||||
com.duosecurity:duo-universal-sdk:jar:1.1.3
|
21
doc/licenses/java-jwt-3.3.0/LICENSE
Normal file
21
doc/licenses/java-jwt-3.3.0/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Auth0, Inc. <support@auth0.com> (http://auth0.com)
|
||||
|
||||
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.
|
8
doc/licenses/java-jwt-3.3.0/README
Normal file
8
doc/licenses/java-jwt-3.3.0/README
Normal file
@@ -0,0 +1,8 @@
|
||||
Java JWT (https://github.com/auth0/java-jwt)
|
||||
--------------------------------------------
|
||||
|
||||
Version: 3.3.0
|
||||
From: 'Auth0 by Okta' (https://www.auth0.com)
|
||||
License(s):
|
||||
MIT (bundled/java-jwt-3.3.0/LICENSE)
|
||||
|
1
doc/licenses/java-jwt-3.3.0/dep-coordinates.txt
Normal file
1
doc/licenses/java-jwt-3.3.0/dep-coordinates.txt
Normal file
@@ -0,0 +1 @@
|
||||
com.auth0:java-jwt:jar:3.3.0
|
2
doc/licenses/kotlin-1.4.10/NOTICE.txt
Normal file
2
doc/licenses/kotlin-1.4.10/NOTICE.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Kotlin Compiler
|
||||
Copyright 2010-2023 JetBrains s.r.o and respective authors and developers
|
8
doc/licenses/kotlin-1.4.10/README
Normal file
8
doc/licenses/kotlin-1.4.10/README
Normal file
@@ -0,0 +1,8 @@
|
||||
Kotlin (https://kotlinlang.org/)
|
||||
--------------------------------
|
||||
|
||||
Version: 1.4.10
|
||||
From: 'JetBrains s.r.o and respective authors and developers'
|
||||
License(s):
|
||||
Apache v2.0
|
||||
|
5
doc/licenses/kotlin-1.4.10/dep-coordinates.txt
Normal file
5
doc/licenses/kotlin-1.4.10/dep-coordinates.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
org.jetbrains.kotlin:kotlin-reflect:jar:1.4.10
|
||||
org.jetbrains.kotlin:kotlin-stdlib:jar:1.4.10
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.4.10
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:jar:1.4.10
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:jar:1.4.10
|
201
doc/licenses/logging-interceptor-4.9.1/LICENSE.txt
Normal file
201
doc/licenses/logging-interceptor-4.9.1/LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
13
doc/licenses/logging-interceptor-4.9.1/NOTICE
Normal file
13
doc/licenses/logging-interceptor-4.9.1/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2019 Square, Inc.
|
||||
|
||||
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.
|
8
doc/licenses/logging-interceptor-4.9.1/README
Normal file
8
doc/licenses/logging-interceptor-4.9.1/README
Normal file
@@ -0,0 +1,8 @@
|
||||
okhttp logging-interceptor (https://square.github.io/okhttp/)
|
||||
-------------------------------------------------------------
|
||||
|
||||
Version: 4.9.1
|
||||
From: 'Square Inc'
|
||||
License(s):
|
||||
Apache v2.0
|
||||
|
@@ -0,0 +1 @@
|
||||
com.squareup.okhttp3:logging-interceptor:jar:4.9.1
|
201
doc/licenses/okhttp-3.14.9/LICENSE.txt
Normal file
201
doc/licenses/okhttp-3.14.9/LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
13
doc/licenses/okhttp-3.14.9/NOTICE
Normal file
13
doc/licenses/okhttp-3.14.9/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2019 Square, Inc.
|
||||
|
||||
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.
|
7
doc/licenses/okhttp-3.14.9/README
Normal file
7
doc/licenses/okhttp-3.14.9/README
Normal file
@@ -0,0 +1,7 @@
|
||||
okhttp (https://square.github.io/okhttp/)
|
||||
---------------------------------------------
|
||||
|
||||
Version: 3.14.9
|
||||
From: 'Square Inc'
|
||||
License(s):
|
||||
Apache 2.0
|
1
doc/licenses/okhttp-3.14.9/dep-coordinates.txt
Normal file
1
doc/licenses/okhttp-3.14.9/dep-coordinates.txt
Normal file
@@ -0,0 +1 @@
|
||||
com.squareup.okhttp3:okhttp:jar:3.14.9
|
201
doc/licenses/okhttp-4.9.1/LICENSE.txt
Normal file
201
doc/licenses/okhttp-4.9.1/LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
13
doc/licenses/okhttp-4.9.1/NOTICE
Normal file
13
doc/licenses/okhttp-4.9.1/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2021 Square, Inc.
|
||||
|
||||
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.
|
7
doc/licenses/okhttp-4.9.1/README
Normal file
7
doc/licenses/okhttp-4.9.1/README
Normal file
@@ -0,0 +1,7 @@
|
||||
okhttp (https://square.github.io/okhttp/)
|
||||
---------------------------------------------
|
||||
|
||||
Version: 4.9.1
|
||||
From: 'Square Inc'
|
||||
License(s):
|
||||
Apache 2.0
|
1
doc/licenses/okhttp-4.9.1/dep-coordinates.txt
Normal file
1
doc/licenses/okhttp-4.9.1/dep-coordinates.txt
Normal file
@@ -0,0 +1 @@
|
||||
com.squareup.okhttp3:okhttp:jar:4.9.1
|
201
doc/licenses/okio-1.17.2/LICENSE.txt
Normal file
201
doc/licenses/okio-1.17.2/LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
13
doc/licenses/okio-1.17.2/NOTICE
Normal file
13
doc/licenses/okio-1.17.2/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2013 Square, Inc.
|
||||
|
||||
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.
|
7
doc/licenses/okio-1.17.2/README
Normal file
7
doc/licenses/okio-1.17.2/README
Normal file
@@ -0,0 +1,7 @@
|
||||
okio (https://square.github.io/okio/)
|
||||
---------------------------------------------
|
||||
|
||||
Version: 1.17.2
|
||||
From: 'Square Inc'
|
||||
License(s):
|
||||
Apache 2.0 (bundled/retrofit-2.9.0/LICENSE.txt)
|
1
doc/licenses/okio-1.17.2/dep-coordinates.txt
Normal file
1
doc/licenses/okio-1.17.2/dep-coordinates.txt
Normal file
@@ -0,0 +1 @@
|
||||
com.squareup.okio:okio:jar:1.17.2
|
201
doc/licenses/okio-2.8.0/LICENSE.txt
Normal file
201
doc/licenses/okio-2.8.0/LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
13
doc/licenses/okio-2.8.0/NOTICE
Normal file
13
doc/licenses/okio-2.8.0/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2020 Square, Inc.
|
||||
|
||||
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.
|
7
doc/licenses/okio-2.8.0/README
Normal file
7
doc/licenses/okio-2.8.0/README
Normal file
@@ -0,0 +1,7 @@
|
||||
okio (https://square.github.io/okio/)
|
||||
---------------------------------------------
|
||||
|
||||
Version: 2.8.0
|
||||
From: 'Square Inc'
|
||||
License(s):
|
||||
Apache 2.0 (bundled/retrofit-2.9.0/LICENSE.txt)
|
1
doc/licenses/okio-2.8.0/dep-coordinates.txt
Normal file
1
doc/licenses/okio-2.8.0/dep-coordinates.txt
Normal file
@@ -0,0 +1 @@
|
||||
com.squareup.okio:okio:jar:2.8.0
|
201
doc/licenses/retrofit-2.9.0/LICENSE.txt
Normal file
201
doc/licenses/retrofit-2.9.0/LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
13
doc/licenses/retrofit-2.9.0/NOTICE
Normal file
13
doc/licenses/retrofit-2.9.0/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2013 Square, Inc.
|
||||
|
||||
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.
|
8
doc/licenses/retrofit-2.9.0/README
Normal file
8
doc/licenses/retrofit-2.9.0/README
Normal file
@@ -0,0 +1,8 @@
|
||||
retrofit (https://square.github.io/retrofit/)
|
||||
---------------------------------------------
|
||||
|
||||
Version: 2.9.0
|
||||
From: 'Square Inc'
|
||||
License(s):
|
||||
Apache 2.0 (bundled/retrofit-2.9.0/LICENSE.txt)
|
||||
|
2
doc/licenses/retrofit-2.9.0/dep-coordinates.txt
Normal file
2
doc/licenses/retrofit-2.9.0/dep-coordinates.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
com.squareup.retrofit2:retrofit:jar:2.9.0
|
||||
com.squareup.retrofit2:converter-jackson:jar:2.9.0
|
202
doc/licenses/spring-web-5.3.25/LICENSE
Normal file
202
doc/licenses/spring-web-5.3.25/LICENSE
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://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
|
||||
|
||||
https://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.
|
7
doc/licenses/spring-web-5.3.25/README
Normal file
7
doc/licenses/spring-web-5.3.25/README
Normal file
@@ -0,0 +1,7 @@
|
||||
Spring Framework (https://spring.io/projects/spring-framework)
|
||||
--------------------------------------------------------------
|
||||
|
||||
Version: 5.3.25
|
||||
From: 'Spring' (https://spring.io/)
|
||||
License(s):
|
||||
Apache v2.0
|
4
doc/licenses/spring-web-5.3.25/dep-coordinates.txt
Normal file
4
doc/licenses/spring-web-5.3.25/dep-coordinates.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
org.springframework:spring-web:jar:5.3.25
|
||||
org.springframework:spring-beans:jar:5.3.25
|
||||
org.springframework:spring-core:jar:5.3.25
|
||||
org.springframework:spring-jcl:jar:5.3.25
|
@@ -41,90 +41,30 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- Define okhttp version to use everywhere to resolve conflict -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.9.1</version> <!-- Specify the desired version -->
|
||||
</dependency>
|
||||
|
||||
<!-- Pre-cache Angular templates with maven-angular-plugin -->
|
||||
<plugin>
|
||||
<groupId>com.keithbranton.mojo</groupId>
|
||||
<artifactId>angular-maven-plugin</artifactId>
|
||||
<version>0.3.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>html2js</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<sourceDir>${basedir}/src/main/resources</sourceDir>
|
||||
<include>**/*.html</include>
|
||||
<target>${basedir}/src/main/resources/generated/templates-main/templates.js</target>
|
||||
<prefix>app/ext/duo</prefix>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Force the use of a consistent version of Kotlin standard library common -->
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib-common</artifactId>
|
||||
<version>1.4.10</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JS/CSS Minification Plugin -->
|
||||
<plugin>
|
||||
<groupId>com.github.buckelieg</groupId>
|
||||
<artifactId>minify-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-cli</id>
|
||||
<configuration>
|
||||
<charset>UTF-8</charset>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>1.4.10</version>
|
||||
</dependency>
|
||||
|
||||
<webappSourceDir>${basedir}/src/main/resources</webappSourceDir>
|
||||
<webappTargetDir>${project.build.directory}/classes</webappTargetDir>
|
||||
|
||||
<cssSourceDir>/</cssSourceDir>
|
||||
<cssTargetDir>/</cssTargetDir>
|
||||
<cssFinalFile>duo.css</cssFinalFile>
|
||||
|
||||
<cssSourceFiles>
|
||||
<cssSourceFile>license.txt</cssSourceFile>
|
||||
</cssSourceFiles>
|
||||
|
||||
<cssSourceIncludes>
|
||||
<cssSourceInclude>**/*.css</cssSourceInclude>
|
||||
</cssSourceIncludes>
|
||||
|
||||
<jsSourceDir>/</jsSourceDir>
|
||||
<jsTargetDir>/</jsTargetDir>
|
||||
<jsFinalFile>duo.js</jsFinalFile>
|
||||
|
||||
<jsSourceFiles>
|
||||
<jsSourceFile>license.txt</jsSourceFile>
|
||||
<jsSourceFile>lib/DuoWeb/LICENSE.js</jsSourceFile>
|
||||
</jsSourceFiles>
|
||||
|
||||
<jsSourceIncludes>
|
||||
<jsSourceInclude>**/*.js</jsSourceInclude>
|
||||
</jsSourceIncludes>
|
||||
|
||||
<!-- Do not minify and include tests -->
|
||||
<jsSourceExcludes>
|
||||
<jsSourceExclude>**/*.test.js</jsSourceExclude>
|
||||
</jsSourceExcludes>
|
||||
<jsEngine>CLOSURE</jsEngine>
|
||||
|
||||
<!-- Disable warnings for JSDoc annotations -->
|
||||
<closureWarningLevels>
|
||||
<misplacedTypeAnnotation>OFF</misplacedTypeAnnotation>
|
||||
<nonStandardJsDocs>OFF</nonStandardJsDocs>
|
||||
</closureWarningLevels>
|
||||
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>minify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -156,6 +96,20 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Duo SDK -->
|
||||
<dependency>
|
||||
<groupId>com.duosecurity</groupId>
|
||||
<artifactId>duo-universal-sdk</artifactId>
|
||||
<version>1.1.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>5.3.25</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@@ -33,6 +33,13 @@ import org.apache.guacamole.net.auth.UserContext;
|
||||
*/
|
||||
public class DuoAuthenticationProvider extends AbstractAuthenticationProvider {
|
||||
|
||||
/**
|
||||
* The unique identifier for this authentication provider. This is used in
|
||||
* various parts of the Guacamole client to distinguish this provider from
|
||||
* others, particularly when multiple authentication providers are used.
|
||||
*/
|
||||
public static String PROVIDER_IDENTIFER = "duo";
|
||||
|
||||
/**
|
||||
* Injector which will manage the object graph of this authentication
|
||||
* provider.
|
||||
@@ -58,7 +65,7 @@ public class DuoAuthenticationProvider extends AbstractAuthenticationProvider {
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "duo";
|
||||
return PROVIDER_IDENTIFER;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -21,7 +21,6 @@ package org.apache.guacamole.auth.duo;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.duo.api.DuoService;
|
||||
import org.apache.guacamole.auth.duo.conf.ConfigurationService;
|
||||
import org.apache.guacamole.environment.Environment;
|
||||
import org.apache.guacamole.environment.LocalEnvironment;
|
||||
@@ -62,7 +61,6 @@ public class DuoAuthenticationProviderModule extends AbstractModule {
|
||||
|
||||
// Store associated auth provider
|
||||
this.authProvider = authProvider;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,9 +72,7 @@ public class DuoAuthenticationProviderModule extends AbstractModule {
|
||||
|
||||
// Bind Duo-specific services
|
||||
bind(ConfigurationService.class);
|
||||
bind(DuoService.class);
|
||||
bind(UserVerificationService.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,37 +19,59 @@
|
||||
|
||||
package org.apache.guacamole.auth.duo;
|
||||
|
||||
import com.duosecurity.Client;
|
||||
import com.duosecurity.exception.DuoException;
|
||||
import com.duosecurity.model.Token;
|
||||
import com.google.inject.Inject;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.duo.api.DuoService;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
import org.apache.guacamole.auth.duo.conf.ConfigurationService;
|
||||
import org.apache.guacamole.auth.duo.form.DuoSignedResponseField;
|
||||
import org.apache.guacamole.form.Field;
|
||||
import org.apache.guacamole.form.RedirectField;
|
||||
import org.apache.guacamole.language.TranslatableGuacamoleClientException;
|
||||
import org.apache.guacamole.language.TranslatableGuacamoleInsufficientCredentialsException;
|
||||
import org.apache.guacamole.language.TranslatableMessage;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Service for verifying the identity of a user against Duo.
|
||||
*/
|
||||
public class UserVerificationService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(UserVerificationService.class);
|
||||
|
||||
/**
|
||||
* The name of the parameter which Duo will return in it's GET call-back
|
||||
* that contains the code that the client will use to generate a token.
|
||||
*/
|
||||
public static final String DUO_CODE_PARAMETER_NAME = "duo_code";
|
||||
|
||||
/**
|
||||
* The name of the parameter that will be used in the GET call-back that
|
||||
* contains the session state.
|
||||
*/
|
||||
public static final String DUO_STATE_PARAMETER_NAME = "state";
|
||||
|
||||
/**
|
||||
* The value that will be returned in the token if Duo authentication
|
||||
* was successful.
|
||||
*/
|
||||
private static final String DUO_TOKEN_SUCCESS_VALUE = "allow";
|
||||
|
||||
/**
|
||||
* Service for retrieving Duo configuration information.
|
||||
*/
|
||||
@Inject
|
||||
private ConfigurationService confService;
|
||||
|
||||
/**
|
||||
* Service for verifying users against Duo.
|
||||
*/
|
||||
@Inject
|
||||
private DuoService duoService;
|
||||
|
||||
/**
|
||||
* Verifies the identity of the given user via the Duo multi-factor
|
||||
* authentication service. If a signed response from Duo has not already
|
||||
@@ -76,38 +98,71 @@ public class UserVerificationService {
|
||||
if (authenticatedUser.getIdentifier().equals(AuthenticatedUser.ANONYMOUS_IDENTIFIER))
|
||||
return;
|
||||
|
||||
// Retrieve signed Duo response from request
|
||||
String signedResponse = request.getParameter(DuoSignedResponseField.PARAMETER_NAME);
|
||||
String username = authenticatedUser.getIdentifier();
|
||||
|
||||
// If no signed response, request one
|
||||
if (signedResponse == null) {
|
||||
try {
|
||||
|
||||
// Create field which requests a signed response from Duo that
|
||||
// verifies the identity of the given user via the configured
|
||||
// Duo API endpoint
|
||||
Field signedResponseField = new DuoSignedResponseField(
|
||||
String redirectUrl = confService.getRedirectUri().toString();
|
||||
|
||||
String builtUrl = UriComponentsBuilder
|
||||
.fromUriString(redirectUrl)
|
||||
.queryParam(Credentials.RESUME_QUERY, DuoAuthenticationProvider.PROVIDER_IDENTIFER)
|
||||
.build()
|
||||
.toUriString();
|
||||
|
||||
// Set up the Duo Client
|
||||
Client duoClient = new Client.Builder(
|
||||
confService.getClientId(),
|
||||
confService.getClientSecret(),
|
||||
confService.getAPIHostname(),
|
||||
duoService.createSignedRequest(authenticatedUser));
|
||||
builtUrl)
|
||||
.build();
|
||||
|
||||
// Create an overall description of the additional credentials
|
||||
// required to verify identity
|
||||
CredentialsInfo expectedCredentials = new CredentialsInfo(
|
||||
Collections.singletonList(signedResponseField));
|
||||
duoClient.healthCheck();
|
||||
|
||||
// Request additional credentials
|
||||
throw new TranslatableGuacamoleInsufficientCredentialsException(
|
||||
// Retrieve signed Duo Code and State from the request
|
||||
String duoCode = request.getParameter(DUO_CODE_PARAMETER_NAME);
|
||||
String duoState = request.getParameter(DUO_STATE_PARAMETER_NAME);
|
||||
|
||||
// If no code or state is received, assume Duo MFA redirect has not occured and do it
|
||||
if (duoCode == null || duoState == null) {
|
||||
|
||||
// Get a new session state from the Duo client
|
||||
duoState = duoClient.generateState();
|
||||
long expirationTimestamp = System.currentTimeMillis() + (confService.getAuthTimeout() * 1000L);
|
||||
|
||||
// Request additional credentials
|
||||
throw new TranslatableGuacamoleInsufficientCredentialsException(
|
||||
"Verification using Duo is required before authentication "
|
||||
+ "can continue.", "LOGIN.INFO_DUO_AUTH_REQUIRED",
|
||||
expectedCredentials);
|
||||
new CredentialsInfo(Collections.singletonList(
|
||||
new RedirectField(
|
||||
DUO_CODE_PARAMETER_NAME,
|
||||
new URI(duoClient.createAuthUrl(username, duoState)),
|
||||
new TranslatableMessage("LOGIN.INFO_DUO_REDIRECT_PENDING")
|
||||
)
|
||||
)),
|
||||
duoState, DuoAuthenticationProvider.PROVIDER_IDENTIFER,
|
||||
DUO_STATE_PARAMETER_NAME, expirationTimestamp
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// Get the token from the DuoClient using the code and username, and check status
|
||||
Token token = duoClient.exchangeAuthorizationCodeFor2FAResult(duoCode, username);
|
||||
if (token == null
|
||||
|| token.getAuth_result() == null
|
||||
|| !DUO_TOKEN_SUCCESS_VALUE.equals(token.getAuth_result().getStatus()))
|
||||
throw new TranslatableGuacamoleClientException("Provided Duo "
|
||||
+ "validation code is incorrect.",
|
||||
"LOGIN.INFO_DUO_VALIDATION_CODE_INCORRECT");
|
||||
}
|
||||
catch (DuoException e) {
|
||||
throw new GuacamoleServerException("Duo Client error.", e);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new GuacamoleServerException("Error creating URI from Duo Authentication URL.", e);
|
||||
}
|
||||
|
||||
// If signed response does not verify this user's identity, abort auth
|
||||
if (!duoService.isValidSignedResponse(authenticatedUser, signedResponse))
|
||||
throw new TranslatableGuacamoleClientException("Provided Duo "
|
||||
+ "validation code is incorrect.",
|
||||
"LOGIN.INFO_DUO_VALIDATION_CODE_INCORRECT");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,245 +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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.duo.api;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
* Data which describes the identity of the user being verified by Duo.
|
||||
*/
|
||||
public class DuoCookie {
|
||||
|
||||
/**
|
||||
* Pattern which matches valid cookies. Each cookie is made up of three
|
||||
* sections, separated from each other by pipe symbols ("|").
|
||||
*/
|
||||
private static final Pattern COOKIE_FORMAT = Pattern.compile("([^|]+)\\|([^|]+)\\|([0-9]+)");
|
||||
|
||||
/**
|
||||
* The index of the capturing group within COOKIE_FORMAT which contains the
|
||||
* username.
|
||||
*/
|
||||
private static final int USERNAME_GROUP = 1;
|
||||
|
||||
/**
|
||||
* The index of the capturing group within COOKIE_FORMAT which contains the
|
||||
* integration key.
|
||||
*/
|
||||
private static final int INTEGRATION_KEY_GROUP = 2;
|
||||
|
||||
/**
|
||||
* The index of the capturing group within COOKIE_FORMAT which contains the
|
||||
* expiration timestamp.
|
||||
*/
|
||||
private static final int EXPIRATION_TIMESTAMP_GROUP = 3;
|
||||
|
||||
/**
|
||||
* The username of the user being verified.
|
||||
*/
|
||||
private final String username;
|
||||
|
||||
/**
|
||||
* The integration key provided by Duo and specific to this deployment of
|
||||
* Guacamole.
|
||||
*/
|
||||
private final String integrationKey;
|
||||
|
||||
/**
|
||||
* The time that this cookie expires, in seconds since midnight of
|
||||
* 1970-01-01 (UTC).
|
||||
*/
|
||||
private final long expires;
|
||||
|
||||
/**
|
||||
* Creates a new DuoCookie which describes the identity of a user being
|
||||
* verified.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user being verified.
|
||||
*
|
||||
* @param integrationKey
|
||||
* The integration key provided by Duo and specific to this deployment
|
||||
* of Guacamole.
|
||||
*
|
||||
* @param expires
|
||||
* The time that this cookie expires, in seconds since midnight of
|
||||
* 1970-01-01 (UTC).
|
||||
*/
|
||||
public DuoCookie(String username, String integrationKey, long expires) {
|
||||
this.username = username;
|
||||
this.integrationKey = integrationKey;
|
||||
this.expires = expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username of the user being verified.
|
||||
*
|
||||
* @return
|
||||
* The username of the user being verified.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integration key provided by Duo and specific to this
|
||||
* deployment of Guacamole.
|
||||
*
|
||||
* @return
|
||||
* The integration key provided by Duo and specific to this deployment
|
||||
* of Guacamole.
|
||||
*/
|
||||
public String getIntegrationKey() {
|
||||
return integrationKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time that this cookie expires. The expiration time is
|
||||
* represented in seconds since midnight of 1970-01-01 (UTC).
|
||||
*
|
||||
* @return
|
||||
* The time that this cookie expires, in seconds since midnight of
|
||||
* 1970-01-01 (UTC).
|
||||
*/
|
||||
public long getExpirationTimestamp(){
|
||||
return expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current time as the number of seconds elapsed since
|
||||
* midnight of 1970-01-01 (UTC).
|
||||
*
|
||||
* @return
|
||||
* The current time as the number of seconds elapsed since midnight of
|
||||
* 1970-01-01 (UTC).
|
||||
*/
|
||||
public static long currentTimestamp() {
|
||||
return System.currentTimeMillis() / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this cookie has expired (the current time has met or
|
||||
* exceeded the expiration timestamp).
|
||||
*
|
||||
* @return
|
||||
* true if this cookie has expired, false otherwise.
|
||||
*/
|
||||
public boolean isExpired() {
|
||||
return currentTimestamp() >= expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a base64-encoded Duo cookie, producing a new DuoCookie object
|
||||
* containing the data therein. If the given string is not a valid Duo
|
||||
* cookie, an exception is thrown. Note that the cookie may be expired, and
|
||||
* must be checked for expiration prior to actual use.
|
||||
*
|
||||
* @param str
|
||||
* The base64-encoded Duo cookie to parse.
|
||||
*
|
||||
* @return
|
||||
* A new DuoCookie object containing the same data as the given
|
||||
* base64-encoded Duo cookie string.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the given string is not a valid base64-encoded Duo cookie.
|
||||
*/
|
||||
public static DuoCookie parseDuoCookie(String str) throws GuacamoleException {
|
||||
|
||||
// Attempt to decode data as base64
|
||||
String data;
|
||||
try {
|
||||
data = new String(BaseEncoding.base64().decode(str), "UTF-8");
|
||||
}
|
||||
|
||||
// Bail if invalid base64 is provided
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new GuacamoleClientException("Username is not correctly "
|
||||
+ "encoded as base64.", e);
|
||||
}
|
||||
|
||||
// Throw hard errors if standard pieces of Java are missing
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedOperationException("Unexpected lack of "
|
||||
+ "UTF-8 support.", e);
|
||||
}
|
||||
|
||||
// Verify format of provided data
|
||||
Matcher matcher = COOKIE_FORMAT.matcher(data);
|
||||
if (!matcher.matches())
|
||||
throw new GuacamoleClientException("Format of base64-encoded "
|
||||
+ "username is invalid.");
|
||||
|
||||
// Get username and key (simple strings)
|
||||
String username = matcher.group(USERNAME_GROUP);
|
||||
String key = matcher.group(INTEGRATION_KEY_GROUP);
|
||||
|
||||
// Parse expiration time
|
||||
long expires;
|
||||
try {
|
||||
expires = Long.parseLong(matcher.group(EXPIRATION_TIMESTAMP_GROUP));
|
||||
}
|
||||
|
||||
// Bail if expiration timestamp is not a valid long
|
||||
catch (NumberFormatException e) {
|
||||
throw new GuacamoleClientException("Expiration timestamp is "
|
||||
+ "not valid.", e);
|
||||
}
|
||||
|
||||
// Return parsed cookie
|
||||
return new DuoCookie(username, key, expires);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base64-encoded string representation of this DuoCookie. The
|
||||
* format used is identical to that required by the Duo service: the
|
||||
* username, integration key, and expiration timestamp separated by pipe
|
||||
* symbols ("|") and encoded with base64.
|
||||
*
|
||||
* @return
|
||||
* The base64-encoded string representation of this DuoCookie.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
try {
|
||||
|
||||
// Separate each cookie field with pipe symbols
|
||||
String data = username + "|" + integrationKey + "|" + expires;
|
||||
|
||||
// Encode resulting cookie string with base64
|
||||
return BaseEncoding.base64().encode(data.getBytes("UTF-8"));
|
||||
|
||||
}
|
||||
|
||||
// Throw hard errors if standard pieces of Java are missing
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedOperationException("Unexpected lack of UTF-8 support.", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,205 +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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.duo.api;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.duo.conf.ConfigurationService;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Service which produces signed requests and parses/verifies signed responses
|
||||
* as required by Duo's API.
|
||||
*/
|
||||
public class DuoService {
|
||||
|
||||
/**
|
||||
* Logger for this class.
|
||||
*/
|
||||
private static final Logger logger = LoggerFactory.getLogger(DuoService.class);
|
||||
|
||||
/**
|
||||
* Pattern which matches valid Duo responses. Each response is made up of
|
||||
* two sections, separated from each other by a colon, where each section
|
||||
* is a signed Duo cookie.
|
||||
*/
|
||||
private static final Pattern RESPONSE_FORMAT = Pattern.compile("([^:]+):([^:]+)");
|
||||
|
||||
/**
|
||||
* The index of the capturing group within RESPONSE_FORMAT which
|
||||
* contains the DUO_RESPONSE cookie signed by the secret key.
|
||||
*/
|
||||
private static final int DUO_COOKIE_GROUP = 1;
|
||||
|
||||
/**
|
||||
* The index of the capturing group within RESPONSE_FORMAT which
|
||||
* contains the APPLICATION cookie signed by the application key.
|
||||
*/
|
||||
private static final int APP_COOKIE_GROUP = 2;
|
||||
|
||||
/**
|
||||
* The amount of time that each generated cookie remains valid, in seconds.
|
||||
*/
|
||||
private static final int COOKIE_EXPIRATION_TIME = 300;
|
||||
|
||||
/**
|
||||
* Service for retrieving Duo configuration information.
|
||||
*/
|
||||
@Inject
|
||||
private ConfigurationService confService;
|
||||
|
||||
/**
|
||||
* Creates and signs a new request to verify the identity of the given
|
||||
* user. This request may ultimately be sent to Duo, resulting in a signed
|
||||
* response from Duo if that verification succeeds.
|
||||
*
|
||||
* @param authenticatedUser
|
||||
* The user whose identity should be verified.
|
||||
*
|
||||
* @return
|
||||
* A signed user verification request which can be sent to Duo.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If required Duo-specific configuration options are missing or
|
||||
* invalid, or if an error prevents generation of the signature.
|
||||
*/
|
||||
public String createSignedRequest(AuthenticatedUser authenticatedUser)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Generate a cookie associating the username with the integration key
|
||||
DuoCookie cookie = new DuoCookie(authenticatedUser.getIdentifier(),
|
||||
confService.getIntegrationKey(),
|
||||
DuoCookie.currentTimestamp() + COOKIE_EXPIRATION_TIME);
|
||||
|
||||
// Sign cookie with secret key
|
||||
SignedDuoCookie duoCookie = new SignedDuoCookie(cookie,
|
||||
SignedDuoCookie.Type.DUO_REQUEST,
|
||||
confService.getSecretKey());
|
||||
|
||||
// Sign cookie with application key
|
||||
SignedDuoCookie appCookie = new SignedDuoCookie(cookie,
|
||||
SignedDuoCookie.Type.APPLICATION,
|
||||
confService.getApplicationKey());
|
||||
|
||||
// Return signed request containing both signed cookies, separated by
|
||||
// a colon (as required by Duo)
|
||||
return duoCookie + ":" + appCookie;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given signed response is a valid response from Duo
|
||||
* which verifies the identity of the given user. If the given response is
|
||||
* invalid or does not verify the identity of the given user (including if
|
||||
* it is a valid response which verifies the identity of a DIFFERENT user),
|
||||
* false is returned.
|
||||
*
|
||||
* @param authenticatedUser
|
||||
* The user that the given signed response should verify.
|
||||
*
|
||||
* @param signedResponse
|
||||
* The signed response received from Duo in response to a signed
|
||||
* request.
|
||||
*
|
||||
* @return
|
||||
* true if the signed response is a valid response from Duo AND verifies
|
||||
* the identity of the given user, false otherwise.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If required Duo-specific configuration options are missing or
|
||||
* invalid, or if an error occurs prevents validation of the signature.
|
||||
*/
|
||||
public boolean isValidSignedResponse(AuthenticatedUser authenticatedUser,
|
||||
String signedResponse) throws GuacamoleException {
|
||||
|
||||
SignedDuoCookie duoCookie;
|
||||
SignedDuoCookie appCookie;
|
||||
|
||||
// Retrieve username from externally-authenticated user
|
||||
String username = authenticatedUser.getIdentifier();
|
||||
|
||||
// Retrieve Duo-specific keys from configuration
|
||||
String applicationKey = confService.getApplicationKey();
|
||||
String integrationKey = confService.getIntegrationKey();
|
||||
String secretKey = confService.getSecretKey();
|
||||
|
||||
try {
|
||||
|
||||
// Verify format of response
|
||||
Matcher matcher = RESPONSE_FORMAT.matcher(signedResponse);
|
||||
if (!matcher.matches()) {
|
||||
logger.debug("Duo response is not in correct format.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse signed cookie defining the user verified by Duo
|
||||
duoCookie = SignedDuoCookie.parseSignedDuoCookie(secretKey,
|
||||
matcher.group(DUO_COOKIE_GROUP));
|
||||
|
||||
// Parse signed cookie defining the user this application
|
||||
// originally requested
|
||||
appCookie = SignedDuoCookie.parseSignedDuoCookie(applicationKey,
|
||||
matcher.group(APP_COOKIE_GROUP));
|
||||
|
||||
}
|
||||
|
||||
// Simply return false if signature fails to verify
|
||||
catch (GuacamoleException e) {
|
||||
logger.debug("Duo signature verification failed.", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify neither cookie is expired
|
||||
if (duoCookie.isExpired() || appCookie.isExpired()) {
|
||||
logger.debug("Duo response contained expired cookie(s).");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the cookies in the response have the correct types
|
||||
if (duoCookie.getType() != SignedDuoCookie.Type.DUO_RESPONSE
|
||||
|| appCookie.getType() != SignedDuoCookie.Type.APPLICATION) {
|
||||
logger.debug("Duo response did not contain correct cookie type(s).");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify integration key matches both cookies
|
||||
if (!duoCookie.getIntegrationKey().equals(integrationKey)
|
||||
|| !appCookie.getIntegrationKey().equals(integrationKey)) {
|
||||
logger.debug("Integration key of Duo response is incorrect.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify both cookies are for the current user
|
||||
if (!duoCookie.getUsername().equals(username)
|
||||
|| !appCookie.getUsername().equals(username)) {
|
||||
logger.debug("Username of Duo response is incorrect.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// All verifications tests pass
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,332 +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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.duo.api;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
|
||||
/**
|
||||
* A DuoCookie which is cryptographically signed with a provided key using
|
||||
* HMAC-SHA1.
|
||||
*/
|
||||
public class SignedDuoCookie extends DuoCookie {
|
||||
|
||||
/**
|
||||
* Pattern which matches valid signed cookies. Like unsigned cookies, each
|
||||
* signed cookie is made up of three sections, separated from each other by
|
||||
* pipe symbols ("|").
|
||||
*/
|
||||
private static final Pattern SIGNED_COOKIE_FORMAT = Pattern.compile("([^|]+)\\|([^|]+)\\|([0-9a-f]+)");
|
||||
|
||||
/**
|
||||
* The index of the capturing group within SIGNED_COOKIE_FORMAT which
|
||||
* contains the cookie type prefix.
|
||||
*/
|
||||
private static final int PREFIX_GROUP = 1;
|
||||
|
||||
/**
|
||||
* The index of the capturing group within SIGNED_COOKIE_FORMAT which
|
||||
* contains the cookie's base64-encoded data.
|
||||
*/
|
||||
private static final int DATA_GROUP = 2;
|
||||
|
||||
/**
|
||||
* The index of the capturing group within SIGNED_COOKIE_FORMAT which
|
||||
* contains the signature.
|
||||
*/
|
||||
private static final int SIGNATURE_GROUP = 3;
|
||||
|
||||
/**
|
||||
* The signature algorithm that should be used to sign the cookie, as
|
||||
* defined by:
|
||||
* http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Mac
|
||||
*/
|
||||
private static final String SIGNATURE_ALGORITHM = "HmacSHA1";
|
||||
|
||||
/**
|
||||
* The type of a signed Duo cookie. Each signed Duo cookie has an
|
||||
* associated type which determines the prefix included in the string
|
||||
* representation of that cookie. As that type is included in the data
|
||||
* that is signed, different types will result in different signatures,
|
||||
* even if the data portion of the cookie is otherwise identical.
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
/**
|
||||
* A Duo cookie which has been signed with the secret key for inclusion
|
||||
* in a Duo request.
|
||||
*/
|
||||
DUO_REQUEST("TX"),
|
||||
|
||||
/**
|
||||
* A Duo cookie which has been signed with the secret key by Duo and
|
||||
* was included in a Duo response.
|
||||
*/
|
||||
DUO_RESPONSE("AUTH"),
|
||||
|
||||
/**
|
||||
* A Duo cookie which has been signed with the application key for
|
||||
* inclusion in a Duo request. Such cookies are also included in Duo
|
||||
* responses, for verification by the application.
|
||||
*/
|
||||
APPLICATION("APP");
|
||||
|
||||
/**
|
||||
* The prefix associated with the Duo cookie type. This prefix will
|
||||
* be included in the string representation of the cookie.
|
||||
*/
|
||||
private final String prefix;
|
||||
|
||||
/**
|
||||
* Creates a new Duo cookie type associated with the given string
|
||||
* prefix. This prefix will be included in the string representation of
|
||||
* the cookie.
|
||||
*
|
||||
* @param prefix
|
||||
* The prefix to associated with the Duo cookie type.
|
||||
*/
|
||||
Type(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the prefix associated with the Duo cookie type.
|
||||
*
|
||||
* @return
|
||||
* The prefix to associated with this Duo cookie type.
|
||||
*/
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cookie type associated with the given prefix. If no such
|
||||
* cookie type exists, null is returned.
|
||||
*
|
||||
* @param prefix
|
||||
* The prefix of the cookie type to search for.
|
||||
*
|
||||
* @return
|
||||
* The cookie type associated with the given prefix, or null if no
|
||||
* such cookie type exists.
|
||||
*/
|
||||
public static Type fromPrefix(String prefix) {
|
||||
|
||||
// Search through all defined cookie types for the given prefix
|
||||
for (Type type : Type.values()) {
|
||||
if (type.getPrefix().equals(prefix))
|
||||
return type;
|
||||
}
|
||||
|
||||
// No such cookie type exists
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of this Duo cookie.
|
||||
*/
|
||||
private final Type type;
|
||||
|
||||
/**
|
||||
* The signature produced when the cookie was signed with HMAC-SHA1. The
|
||||
* signature covers the prefix of the type and the cookie's base64-encoded
|
||||
* data, separated by a pipe symbol.
|
||||
*/
|
||||
private final String signature;
|
||||
|
||||
/**
|
||||
* Creates a new SignedDuoCookie which describes the identity of a user
|
||||
* being verified and is cryptographically signed with HMAC-SHA1 by a given
|
||||
* key.
|
||||
*
|
||||
* @param cookie
|
||||
* The cookie defining the identity being verified.
|
||||
*
|
||||
* @param type
|
||||
* The type of the cookie being created.
|
||||
*
|
||||
* @param key
|
||||
* The key to use to generate the cryptographic signature. This key
|
||||
* will not be stored within the cookie.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the given signing key is invalid.
|
||||
*/
|
||||
public SignedDuoCookie(DuoCookie cookie, Type type, String key)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Init underlying cookie
|
||||
super(cookie.getUsername(), cookie.getIntegrationKey(),
|
||||
cookie.getExpirationTimestamp());
|
||||
|
||||
// Store cookie type and signature
|
||||
this.type = type;
|
||||
this.signature = sign(key, type.getPrefix() + "|" + cookie.toString());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs the given arbitrary string data with the given key using the
|
||||
* algorithm defined by SIGNATURE_ALGORITHM. Both the data and the key will
|
||||
* be interpreted as UTF-8 bytes.
|
||||
*
|
||||
* @param key
|
||||
* The key which should be used to sign the given data.
|
||||
*
|
||||
* @param data
|
||||
* The data being signed.
|
||||
*
|
||||
* @return
|
||||
* The signature produced by signing the given data with the given key,
|
||||
* encoded as lowercase hexadecimal.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the given signing key is invalid.
|
||||
*/
|
||||
private static String sign(String key, String data) throws GuacamoleException {
|
||||
|
||||
try {
|
||||
|
||||
// Attempt to sign UTF-8 bytes of provided data
|
||||
Mac mac = Mac.getInstance(SIGNATURE_ALGORITHM);
|
||||
mac.init(new SecretKeySpec(key.getBytes("UTF-8"), SIGNATURE_ALGORITHM));
|
||||
|
||||
// Return signature as hex
|
||||
return BaseEncoding.base16().lowerCase().encode(mac.doFinal(data.getBytes("UTF-8")));
|
||||
|
||||
}
|
||||
|
||||
// Re-throw any errors which prevent signature
|
||||
catch (InvalidKeyException e){
|
||||
throw new GuacamoleServerException("Signing key is invalid.", e);
|
||||
}
|
||||
|
||||
// Throw hard errors if standard pieces of Java are missing
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedOperationException("Unexpected lack of UTF-8 support.", e);
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
throw new UnsupportedOperationException("Unexpected lack of support "
|
||||
+ "for required signature algorithm "
|
||||
+ "\"" + SIGNATURE_ALGORITHM + "\".", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this Duo cookie. The Duo cookie type is dictated
|
||||
* by the context of the cookie's use, and is included with the cookie's
|
||||
* underlying data when generating the signature.
|
||||
*
|
||||
* @return
|
||||
* The type of this Duo cookie.
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signature produced when the cookie was signed with HMAC-SHA1.
|
||||
* The signature covers the prefix of the cookie's type and the cookie's
|
||||
* base64-encoded data, separated by a pipe symbol.
|
||||
*
|
||||
* @return
|
||||
* The signature produced when the cookie was signed with HMAC-SHA1.
|
||||
*/
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a signed Duo cookie string, such as that produced by the
|
||||
* toString() function or received from the Duo service, producing a new
|
||||
* SignedDuoCookie object containing the associated cookie data and
|
||||
* signature. If the given string is not a valid Duo cookie, or if the
|
||||
* signature is incorrect, an exception is thrown. Note that the cookie may
|
||||
* be expired, and must be checked for expiration prior to actual use.
|
||||
*
|
||||
* @param key
|
||||
* The key that was used to sign the Duo cookie.
|
||||
*
|
||||
* @param str
|
||||
* The Duo cookie string to parse.
|
||||
*
|
||||
* @return
|
||||
* A new SignedDuoCookie object containing the same data and signature
|
||||
* as the given Duo cookie string.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the given string is not a valid Duo cookie string, or if the
|
||||
* signature of the cookie is invalid.
|
||||
*/
|
||||
public static SignedDuoCookie parseSignedDuoCookie(String key, String str)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Verify format of provided data
|
||||
Matcher matcher = SIGNED_COOKIE_FORMAT.matcher(str);
|
||||
if (!matcher.matches())
|
||||
throw new GuacamoleClientException("Format of signed Duo cookie "
|
||||
+ "is invalid.");
|
||||
|
||||
// Parse type from prefix
|
||||
Type type = Type.fromPrefix(matcher.group(PREFIX_GROUP));
|
||||
if (type == null)
|
||||
throw new GuacamoleClientException("Invalid Duo cookie prefix.");
|
||||
|
||||
// Parse cookie from base64-encoded data
|
||||
DuoCookie cookie = DuoCookie.parseDuoCookie(matcher.group(DATA_GROUP));
|
||||
|
||||
// Verify signature of cookie
|
||||
SignedDuoCookie signedCookie = new SignedDuoCookie(cookie, type, key);
|
||||
if (!signedCookie.getSignature().equals(matcher.group(SIGNATURE_GROUP)))
|
||||
throw new GuacamoleClientException("Duo cookie has incorrect signature.");
|
||||
|
||||
// Cookie has valid signature and has parsed successfully
|
||||
return signedCookie;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of this SignedDuoCookie. The format
|
||||
* used is identical to that required by the Duo service: the type prefix,
|
||||
* base64-encoded cookie data, and HMAC-SHA1 signature separated by pipe
|
||||
* symbols ("|").
|
||||
*
|
||||
* @return
|
||||
* The string representation of this SignedDuoCookie.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return type.getPrefix() + "|" + super.toString() + "|" + signature;
|
||||
}
|
||||
|
||||
}
|
@@ -20,9 +20,12 @@
|
||||
package org.apache.guacamole.auth.duo.conf;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.net.URI;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.environment.Environment;
|
||||
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
||||
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
||||
import org.apache.guacamole.properties.URIGuacamoleProperty;
|
||||
|
||||
/**
|
||||
* Service for retrieving configuration information regarding the Duo
|
||||
@@ -52,15 +55,15 @@ public class ConfigurationService {
|
||||
};
|
||||
|
||||
/**
|
||||
* The property within guacamole.properties which defines the integration
|
||||
* key received from Duo for verifying Guacamole users. This value MUST be
|
||||
* The property within guacamole.properties which defines the client id
|
||||
* received from Duo for verifying Guacamole users. This value MUST be
|
||||
* exactly 20 characters.
|
||||
*/
|
||||
private static final StringGuacamoleProperty DUO_INTEGRATION_KEY =
|
||||
private static final StringGuacamoleProperty DUO_CLIENT_ID =
|
||||
new StringGuacamoleProperty() {
|
||||
|
||||
@Override
|
||||
public String getName() { return "duo-integration-key"; }
|
||||
public String getName() { return "duo-client-id"; }
|
||||
|
||||
};
|
||||
|
||||
@@ -69,25 +72,37 @@ public class ConfigurationService {
|
||||
* received from Duo for verifying Guacamole users. This value MUST be
|
||||
* exactly 40 characters.
|
||||
*/
|
||||
private static final StringGuacamoleProperty DUO_SECRET_KEY =
|
||||
private static final StringGuacamoleProperty DUO_CLIENT_SECRET =
|
||||
new StringGuacamoleProperty() {
|
||||
|
||||
@Override
|
||||
public String getName() { return "duo-secret-key"; }
|
||||
public String getName() { return "duo-client-secret"; }
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The property within guacamole.properties which defines the arbitrary
|
||||
* random key which was generated for Guacamole. Note that this value is not
|
||||
* provided by Duo, but is expected to be generated by the administrator of
|
||||
* the system hosting Guacamole. This value MUST be at least 40 characters.
|
||||
* The property within guacamole.properties which defines the redirect URI
|
||||
* that Duo will call after the second factor has been completed. This
|
||||
* should be the URI used to access Guacamole.
|
||||
*/
|
||||
private static final StringGuacamoleProperty DUO_APPLICATION_KEY =
|
||||
new StringGuacamoleProperty() {
|
||||
private static final URIGuacamoleProperty DUO_REDIRECT_URI =
|
||||
new URIGuacamoleProperty() {
|
||||
|
||||
@Override
|
||||
public String getName() { return "duo-application-key"; }
|
||||
public String getName() { return "duo-redirect-uri"; }
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The property that configures the timeout, in seconds, of in-progress
|
||||
* Duo authentication attempts. Authentication attempts that take longer
|
||||
* than this period of time will be invalidated.
|
||||
*/
|
||||
private static final IntegerGuacamoleProperty DUO_AUTH_TIMEOUT =
|
||||
new IntegerGuacamoleProperty() {
|
||||
|
||||
@Override
|
||||
public String getName() { return "duo-auth-timeout"; }
|
||||
|
||||
};
|
||||
|
||||
@@ -110,51 +125,65 @@ public class ConfigurationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integration key received from Duo for verifying Guacamole
|
||||
* users, as defined in guacamole.properties by the "duo-integration-key"
|
||||
* Returns the Duo client id received from Duo for verifying Guacamole
|
||||
* users, as defined in guacamole.properties by the "duo-client-id"
|
||||
* property. This value MUST be exactly 20 characters.
|
||||
*
|
||||
* @return
|
||||
* The integration key received from Duo for verifying Guacamole
|
||||
* users.
|
||||
* The client id received from Duo for verifying Guacamole users.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the associated property within guacamole.properties is missing.
|
||||
*/
|
||||
public String getIntegrationKey() throws GuacamoleException {
|
||||
return environment.getRequiredProperty(DUO_INTEGRATION_KEY);
|
||||
public String getClientId() throws GuacamoleException {
|
||||
return environment.getRequiredProperty(DUO_CLIENT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secret key received from Duo for verifying Guacamole users,
|
||||
* as defined in guacamole.properties by the "duo-secret-key" property. This
|
||||
* value MUST be exactly 20 characters.
|
||||
* Returns the client secret received from Duo for verifying Guacamole users,
|
||||
* as defined in guacamole.properties by the "duo-client-secret" property.
|
||||
* This value MUST be exactly 20 characters.
|
||||
*
|
||||
* @return
|
||||
* The secret key received from Duo for verifying Guacamole users.
|
||||
* The client secret received from Duo for verifying Guacamole users.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the associated property within guacamole.properties is missing.
|
||||
*/
|
||||
public String getSecretKey() throws GuacamoleException {
|
||||
return environment.getRequiredProperty(DUO_SECRET_KEY);
|
||||
public String getClientSecret() throws GuacamoleException {
|
||||
return environment.getRequiredProperty(DUO_CLIENT_SECRET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arbitrary random key which was generated for Guacamole, as
|
||||
* defined in guacamole.properties by the "duo-application-key" property.
|
||||
* Note that this value is not provided by Duo, but is expected to be
|
||||
* generated by the administrator of the system hosting Guacamole. This
|
||||
* value MUST be at least 40 characters.
|
||||
* Return the callback URI that will be called by Duo after authentication
|
||||
* with Duo has been completed. This should be the URI to return the user
|
||||
* to the Guacamole interface, and will be a full URI.
|
||||
*
|
||||
* @return
|
||||
* The arbitrary random key which was generated for Guacamole.
|
||||
* The URL for Duo to use to callback to the Guacamole interface after
|
||||
* authentication has been completed.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the associated property within guacamole.properties is missing.
|
||||
* If guacamole.properties cannot be read, or if the property is not
|
||||
* defined.
|
||||
*/
|
||||
public String getApplicationKey() throws GuacamoleException {
|
||||
return environment.getRequiredProperty(DUO_APPLICATION_KEY);
|
||||
public URI getRedirectUri() throws GuacamoleException {
|
||||
return environment.getRequiredProperty(DUO_REDIRECT_URI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of seconds after which in-progress authentication attempts with
|
||||
* Duo should be invalidated. The default is 30 seconds.
|
||||
*
|
||||
* @return
|
||||
* The number of seconds after which in-progress Duo MFA attempts should
|
||||
* be invalidated.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If guacamole.properties cannot be parsed.
|
||||
*/
|
||||
public int getAuthTimeout() throws GuacamoleException {
|
||||
return environment.getProperty(DUO_AUTH_TIMEOUT, 30);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,98 +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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.duo.form;
|
||||
|
||||
import org.apache.guacamole.form.Field;
|
||||
|
||||
/**
|
||||
* A custom field type which uses the DuoWeb API to produce a signed response
|
||||
* for a particular user. The signed response serves as an additional
|
||||
* authentication factor, as it cryptographically verifies possession of the
|
||||
* physical device associated with that user's Duo account.
|
||||
*/
|
||||
public class DuoSignedResponseField extends Field {
|
||||
|
||||
/**
|
||||
* The name of the HTTP parameter which an instance of this field will
|
||||
* populate within a user's credentials.
|
||||
*/
|
||||
public static final String PARAMETER_NAME = "guac-duo-signed-response";
|
||||
|
||||
/**
|
||||
* The unique name associated with this field type.
|
||||
*/
|
||||
private static final String FIELD_TYPE_NAME = "GUAC_DUO_SIGNED_RESPONSE";
|
||||
|
||||
/**
|
||||
* The hostname of the DuoWeb API endpoint.
|
||||
*/
|
||||
private final String apiHost;
|
||||
|
||||
/**
|
||||
* The signed request generated by a call to DuoWeb.signRequest().
|
||||
*/
|
||||
private final String signedRequest;
|
||||
|
||||
/**
|
||||
* Creates a new field which uses the DuoWeb API to prompt the user for
|
||||
* additional credentials. The provided credentials, if valid, will
|
||||
* ultimately be verified by Duo's service, resulting in a signed response
|
||||
* which can be cryptographically verified.
|
||||
*
|
||||
* @param apiHost
|
||||
* The hostname of the DuoWeb API endpoint.
|
||||
*
|
||||
* @param signedRequest
|
||||
* A signed request generated for the user in question by a call to
|
||||
* DuoWeb.signRequest().
|
||||
*/
|
||||
public DuoSignedResponseField(String apiHost, String signedRequest) {
|
||||
|
||||
// Init base field type properties
|
||||
super(PARAMETER_NAME, FIELD_TYPE_NAME);
|
||||
|
||||
// Init Duo-specific properties
|
||||
this.apiHost = apiHost;
|
||||
this.signedRequest = signedRequest;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hostname of the DuoWeb API endpoint.
|
||||
*
|
||||
* @return
|
||||
* The hostname of the DuoWeb API endpoint.
|
||||
*/
|
||||
public String getApiHost() {
|
||||
return apiHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signed request string, which must have been generated by a
|
||||
* call to DuoWeb.signRequest().
|
||||
*
|
||||
* @return
|
||||
* The signed request generated by a call to DuoWeb.signRequest().
|
||||
*/
|
||||
public String getSignedRequest() {
|
||||
return signedRequest;
|
||||
}
|
||||
|
||||
}
|
@@ -1,33 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Config block which registers Duo-specific field types.
|
||||
*/
|
||||
angular.module('guacDuo').config(['formServiceProvider',
|
||||
function guacDuoConfig(formServiceProvider) {
|
||||
|
||||
// Define field for the signed response from the Duo service
|
||||
formServiceProvider.registerFieldType('GUAC_DUO_SIGNED_RESPONSE', {
|
||||
module : 'guacDuo',
|
||||
controller : 'duoSignedResponseController',
|
||||
templateUrl : 'app/ext/duo/templates/duoSignedResponseField.html'
|
||||
});
|
||||
|
||||
}]);
|
@@ -1,86 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller for the "GUAC_DUO_SIGNED_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('guacDuo').controller('duoSignedResponseController', ['$scope', '$element',
|
||||
function duoSignedResponseController($scope, $element) {
|
||||
|
||||
/**
|
||||
* The iframe which contains the Duo authentication interface.
|
||||
*
|
||||
* @type HTMLIFrameElement
|
||||
*/
|
||||
var iframe = $element.find('iframe')[0];
|
||||
|
||||
/**
|
||||
* The submit button which should be used to submit the login form once
|
||||
* the Duo response has been received.
|
||||
*
|
||||
* @type HTMLInputElement
|
||||
*/
|
||||
var submit = $element.find('input[type="submit"]')[0];
|
||||
|
||||
/**
|
||||
* Whether the Duo interface has finished loading within the iframe.
|
||||
*
|
||||
* @type Boolean
|
||||
*/
|
||||
$scope.duoInterfaceLoaded = false;
|
||||
|
||||
/**
|
||||
* Submits the signed response from Duo once the user has authenticated.
|
||||
* This is a callback invoked by the DuoWeb API after the user has been
|
||||
* verified and the signed response has been received.
|
||||
*
|
||||
* @param {HTMLFormElement} form
|
||||
* The form element provided by the DuoWeb API containing the signed
|
||||
* response as the value of an input field named "sig_response".
|
||||
*/
|
||||
var submitSignedResponse = function submitSignedResponse(form) {
|
||||
|
||||
// Update model to match received response
|
||||
$scope.$apply(function updateModel() {
|
||||
$scope.model = form.elements['sig_response'].value;
|
||||
});
|
||||
|
||||
// Submit updated credentials
|
||||
submit.click();
|
||||
|
||||
};
|
||||
|
||||
// Update Duo loaded state when iframe finishes loading
|
||||
iframe.onload = function duoLoaded() {
|
||||
$scope.$apply(function updateLoadedState() {
|
||||
$scope.duoInterfaceLoaded = true;
|
||||
});
|
||||
};
|
||||
|
||||
// Initialize Duo interface within iframe
|
||||
Duo.init({
|
||||
iframe : iframe,
|
||||
host : $scope.field.apiHost,
|
||||
sig_request : $scope.field.signedRequest,
|
||||
submit_callback : submitSignedResponse
|
||||
});
|
||||
|
||||
}]);
|
@@ -1,28 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module which provides handling for Duo multi-factor authentication.
|
||||
*/
|
||||
angular.module('guacDuo', [
|
||||
'form'
|
||||
]);
|
||||
|
||||
// Ensure the guacDuo module is loaded along with the rest of the app
|
||||
angular.module('index').requires.push('guacDuo');
|
@@ -20,18 +20,6 @@
|
||||
"translations/pt.json",
|
||||
"translations/ru.json",
|
||||
"translations/zh.json"
|
||||
],
|
||||
|
||||
"js" : [
|
||||
"duo.min.js"
|
||||
],
|
||||
|
||||
"css" : [
|
||||
"duo.min.css"
|
||||
],
|
||||
|
||||
"resources" : {
|
||||
"templates/duoSignedResponseField.html" : "text/html"
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
|
@@ -1,366 +0,0 @@
|
||||
/**
|
||||
* Duo Web SDK v2
|
||||
* Copyright 2015, Duo Security
|
||||
*/
|
||||
window.Duo = (function(document, window) {
|
||||
var DUO_MESSAGE_FORMAT = /^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/;
|
||||
var DUO_ERROR_FORMAT = /^ERR\|[\w\s\.\(\)]+$/;
|
||||
|
||||
var iframeId = 'duo_iframe',
|
||||
postAction = '',
|
||||
postArgument = 'sig_response',
|
||||
host,
|
||||
sigRequest,
|
||||
duoSig,
|
||||
appSig,
|
||||
iframe,
|
||||
submitCallback;
|
||||
|
||||
function throwError(message, url) {
|
||||
throw new Error(
|
||||
'Duo Web SDK error: ' + message +
|
||||
(url ? ('\n' + 'See ' + url + ' for more information') : '')
|
||||
);
|
||||
}
|
||||
|
||||
function hyphenize(str) {
|
||||
return str.replace(/([a-z])([A-Z])/, '$1-$2').toLowerCase();
|
||||
}
|
||||
|
||||
// cross-browser data attributes
|
||||
function getDataAttribute(element, name) {
|
||||
if ('dataset' in element) {
|
||||
return element.dataset[name];
|
||||
} else {
|
||||
return element.getAttribute('data-' + hyphenize(name));
|
||||
}
|
||||
}
|
||||
|
||||
// cross-browser event binding/unbinding
|
||||
function on(context, event, fallbackEvent, callback) {
|
||||
if ('addEventListener' in window) {
|
||||
context.addEventListener(event, callback, false);
|
||||
} else {
|
||||
context.attachEvent(fallbackEvent, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function off(context, event, fallbackEvent, callback) {
|
||||
if ('removeEventListener' in window) {
|
||||
context.removeEventListener(event, callback, false);
|
||||
} else {
|
||||
context.detachEvent(fallbackEvent, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function onReady(callback) {
|
||||
on(document, 'DOMContentLoaded', 'onreadystatechange', callback);
|
||||
}
|
||||
|
||||
function offReady(callback) {
|
||||
off(document, 'DOMContentLoaded', 'onreadystatechange', callback);
|
||||
}
|
||||
|
||||
function onMessage(callback) {
|
||||
on(window, 'message', 'onmessage', callback);
|
||||
}
|
||||
|
||||
function offMessage(callback) {
|
||||
off(window, 'message', 'onmessage', callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the sig_request parameter, throwing errors if the token contains
|
||||
* a server error or if the token is invalid.
|
||||
*
|
||||
* @param {String} sig Request token
|
||||
*/
|
||||
function parseSigRequest(sig) {
|
||||
if (!sig) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
// see if the token contains an error, throwing it if it does
|
||||
if (sig.indexOf('ERR|') === 0) {
|
||||
throwError(sig.split('|')[1]);
|
||||
}
|
||||
|
||||
// validate the token
|
||||
if (sig.indexOf(':') === -1 || sig.split(':').length !== 2) {
|
||||
throwError(
|
||||
'Duo was given a bad token. This might indicate a configuration ' +
|
||||
'problem with one of Duo\'s client libraries.',
|
||||
'https://www.duosecurity.com/docs/duoweb#first-steps'
|
||||
);
|
||||
}
|
||||
|
||||
var sigParts = sig.split(':');
|
||||
|
||||
// hang on to the token, and the parsed duo and app sigs
|
||||
sigRequest = sig;
|
||||
duoSig = sigParts[0];
|
||||
appSig = sigParts[1];
|
||||
|
||||
return {
|
||||
sigRequest: sig,
|
||||
duoSig: sigParts[0],
|
||||
appSig: sigParts[1]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is set up to run when the DOM is ready, if the iframe was
|
||||
* not available during `init`.
|
||||
*/
|
||||
function onDOMReady() {
|
||||
iframe = document.getElementById(iframeId);
|
||||
|
||||
if (!iframe) {
|
||||
throw new Error(
|
||||
'This page does not contain an iframe for Duo to use.' +
|
||||
'Add an element like <iframe id="duo_iframe"></iframe> ' +
|
||||
'to this page. ' +
|
||||
'See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe ' +
|
||||
'for more information.'
|
||||
);
|
||||
}
|
||||
|
||||
// we've got an iframe, away we go!
|
||||
ready();
|
||||
|
||||
// always clean up after yourself
|
||||
offReady(onDOMReady);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that a MessageEvent came from the Duo service, and that it
|
||||
* is a properly formatted payload.
|
||||
*
|
||||
* The Google Chrome sign-in page injects some JS into pages that also
|
||||
* make use of postMessage, so we need to do additional validation above
|
||||
* and beyond the origin.
|
||||
*
|
||||
* @param {MessageEvent} event Message received via postMessage
|
||||
*/
|
||||
function isDuoMessage(event) {
|
||||
return Boolean(
|
||||
event.origin === ('https://' + host) &&
|
||||
typeof event.data === 'string' &&
|
||||
(
|
||||
event.data.match(DUO_MESSAGE_FORMAT) ||
|
||||
event.data.match(DUO_ERROR_FORMAT)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the request token and prepare for the iframe to become ready.
|
||||
*
|
||||
* All options below can be passed into an options hash to `Duo.init`, or
|
||||
* specified on the iframe using `data-` attributes.
|
||||
*
|
||||
* Options specified using the options hash will take precedence over
|
||||
* `data-` attributes.
|
||||
*
|
||||
* Example using options hash:
|
||||
* ```javascript
|
||||
* Duo.init({
|
||||
* iframe: "some_other_id",
|
||||
* host: "api-main.duo.test",
|
||||
* sig_request: "...",
|
||||
* post_action: "/auth",
|
||||
* post_argument: "resp"
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Example using `data-` attributes:
|
||||
* ```
|
||||
* <iframe id="duo_iframe"
|
||||
* data-host="api-main.duo.test"
|
||||
* data-sig-request="..."
|
||||
* data-post-action="/auth"
|
||||
* data-post-argument="resp"
|
||||
* >
|
||||
* </iframe>
|
||||
* ```
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {String} options.iframe The iframe, or id of an iframe to set up
|
||||
* @param {String} options.host Hostname
|
||||
* @param {String} options.sig_request Request token
|
||||
* @param {String} [options.post_action=''] URL to POST back to after successful auth
|
||||
* @param {String} [options.post_argument='sig_response'] Parameter name to use for response token
|
||||
* @param {Function} [options.submit_callback] If provided, duo will not submit the form instead execute
|
||||
* the callback function with reference to the "duo_form" form object
|
||||
* submit_callback can be used to prevent the webpage from reloading.
|
||||
*/
|
||||
function init(options) {
|
||||
if (options) {
|
||||
if (options.host) {
|
||||
host = options.host;
|
||||
}
|
||||
|
||||
if (options.sig_request) {
|
||||
parseSigRequest(options.sig_request);
|
||||
}
|
||||
|
||||
if (options.post_action) {
|
||||
postAction = options.post_action;
|
||||
}
|
||||
|
||||
if (options.post_argument) {
|
||||
postArgument = options.post_argument;
|
||||
}
|
||||
|
||||
if (options.iframe) {
|
||||
if ('tagName' in options.iframe) {
|
||||
iframe = options.iframe;
|
||||
} else if (typeof options.iframe === 'string') {
|
||||
iframeId = options.iframe;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof options.submit_callback === 'function') {
|
||||
submitCallback = options.submit_callback;
|
||||
}
|
||||
}
|
||||
|
||||
// if we were given an iframe, no need to wait for the rest of the DOM
|
||||
if (iframe) {
|
||||
ready();
|
||||
} else {
|
||||
// try to find the iframe in the DOM
|
||||
iframe = document.getElementById(iframeId);
|
||||
|
||||
// iframe is in the DOM, away we go!
|
||||
if (iframe) {
|
||||
ready();
|
||||
} else {
|
||||
// wait until the DOM is ready, then try again
|
||||
onReady(onDOMReady);
|
||||
}
|
||||
}
|
||||
|
||||
// always clean up after yourself!
|
||||
offReady(init);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when a message was received from another domain
|
||||
* using the `postMessage` API. Check that the event came from the Duo
|
||||
* service domain, and that the message is a properly formatted payload,
|
||||
* then perform the post back to the primary service.
|
||||
*
|
||||
* @param event Event object (contains origin and data)
|
||||
*/
|
||||
function onReceivedMessage(event) {
|
||||
if (isDuoMessage(event)) {
|
||||
// the event came from duo, do the post back
|
||||
doPostBack(event.data);
|
||||
|
||||
// always clean up after yourself!
|
||||
offMessage(onReceivedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Point the iframe at Duo, then wait for it to postMessage back to us.
|
||||
*/
|
||||
function ready() {
|
||||
if (!host) {
|
||||
host = getDataAttribute(iframe, 'host');
|
||||
|
||||
if (!host) {
|
||||
throwError(
|
||||
'No API hostname is given for Duo to use. Be sure to pass ' +
|
||||
'a `host` parameter to Duo.init, or through the `data-host` ' +
|
||||
'attribute on the iframe element.',
|
||||
'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!duoSig || !appSig) {
|
||||
parseSigRequest(getDataAttribute(iframe, 'sigRequest'));
|
||||
|
||||
if (!duoSig || !appSig) {
|
||||
throwError(
|
||||
'No valid signed request is given. Be sure to give the ' +
|
||||
'`sig_request` parameter to Duo.init, or use the ' +
|
||||
'`data-sig-request` attribute on the iframe element.',
|
||||
'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// if postAction/Argument are defaults, see if they are specified
|
||||
// as data attributes on the iframe
|
||||
if (postAction === '') {
|
||||
postAction = getDataAttribute(iframe, 'postAction') || postAction;
|
||||
}
|
||||
|
||||
if (postArgument === 'sig_response') {
|
||||
postArgument = getDataAttribute(iframe, 'postArgument') || postArgument;
|
||||
}
|
||||
|
||||
// point the iframe at Duo
|
||||
iframe.src = [
|
||||
'https://', host, '/frame/web/v1/auth?tx=', duoSig,
|
||||
'&parent=', encodeURIComponent(document.location.href),
|
||||
'&v=2.3'
|
||||
].join('');
|
||||
|
||||
// listen for the 'message' event
|
||||
onMessage(onReceivedMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* We received a postMessage from Duo. POST back to the primary service
|
||||
* with the response token, and any additional user-supplied parameters
|
||||
* given in form#duo_form.
|
||||
*/
|
||||
function doPostBack(response) {
|
||||
// create a hidden input to contain the response token
|
||||
var input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = postArgument;
|
||||
input.value = response + ':' + appSig;
|
||||
|
||||
// user may supply their own form with additional inputs
|
||||
var form = document.getElementById('duo_form');
|
||||
|
||||
// if the form doesn't exist, create one
|
||||
if (!form) {
|
||||
form = document.createElement('form');
|
||||
|
||||
// insert the new form after the iframe
|
||||
iframe.parentElement.insertBefore(form, iframe.nextSibling);
|
||||
}
|
||||
|
||||
// make sure we are actually posting to the right place
|
||||
form.method = 'POST';
|
||||
form.action = postAction;
|
||||
|
||||
// add the response token input to the form
|
||||
form.appendChild(input);
|
||||
|
||||
// away we go!
|
||||
if (typeof submitCallback === "function") {
|
||||
submitCallback.call(null, form);
|
||||
} else {
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
// when the DOM is ready, initialize
|
||||
// note that this will get cleaned up if the user calls init directly!
|
||||
onReady(init);
|
||||
|
||||
return {
|
||||
init: init,
|
||||
_parseSigRequest: parseSigRequest,
|
||||
_isDuoMessage: isDuoMessage,
|
||||
_doPostBack: doPostBack
|
||||
};
|
||||
}(document, window));
|
@@ -1,27 +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.
|
||||
*/
|
@@ -1,62 +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.
|
||||
*/
|
||||
|
||||
|
||||
.duo-signature-response-field-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: table;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.duo-signature-response-field {
|
||||
width: 100%;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.duo-signature-response-field input[type="submit"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.duo-signature-response-field iframe {
|
||||
width: 100%;
|
||||
max-width: 620px;
|
||||
height: 330px;
|
||||
border: none;
|
||||
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.5);
|
||||
display: block;
|
||||
margin: 1.5em auto;
|
||||
}
|
||||
|
||||
.duo-signature-response-field iframe {
|
||||
opacity: 1;
|
||||
-webkit-transition: opacity 0.125s;
|
||||
-moz-transition: opacity 0.125s;
|
||||
-ms-transition: opacity 0.125s;
|
||||
-o-transition: opacity 0.125s;
|
||||
transition: opacity 0.125s;
|
||||
}
|
||||
|
||||
.duo-signature-response-field.loading iframe {
|
||||
opacity: 0;
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
<div class="duo-signature-response-field-container">
|
||||
<div class="duo-signature-response-field" ng-class="{ loading : !duoInterfaceLoaded }">
|
||||
<iframe></iframe>
|
||||
<input type="submit">
|
||||
</div>
|
||||
</div>
|
@@ -7,7 +7,8 @@
|
||||
"LOGIN" : {
|
||||
"FIELD_HEADER_GUAC_DUO_SIGNED_RESPONSE" : "",
|
||||
"INFO_DUO_VALIDATION_CODE_INCORRECT" : "Duo validation code incorrect.",
|
||||
"INFO_DUO_AUTH_REQUIRED" : "Please authenticate with Duo to continue."
|
||||
"INFO_DUO_AUTH_REQUIRED" : "Please authenticate with Duo to continue.",
|
||||
"INFO_DUO_REDIRECT_PENDING" : "Please wait, redirecting to Duo..."
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,8 @@
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_DUO_VALIDATION_CODE_INCORRECT" : "Duoの認証コードが間違っています。",
|
||||
"INFO_DUO_AUTH_REQUIRED" : "Duoで認証してください。"
|
||||
"INFO_DUO_AUTH_REQUIRED" : "Duoで認証してください。",
|
||||
"INFO_DUO_REDIRECT_PENDING" : "Duoへリダイレクトしています。"
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,11 +19,11 @@
|
||||
|
||||
package org.apache.guacamole.auth.sso;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.guacamole.net.auth.IdentifierGenerator;
|
||||
|
||||
/**
|
||||
* Service for generating and validating single-use random tokens (nonces).
|
||||
@@ -31,12 +31,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class NonceService {
|
||||
|
||||
/**
|
||||
* Generator of arbitrary, unique, unpredictable identifiers.
|
||||
*/
|
||||
@Inject
|
||||
private IdentifierGenerator idGenerator;
|
||||
|
||||
/**
|
||||
* Map of all generated nonces to their corresponding expiration timestamps.
|
||||
* This Map must be periodically swept of expired nonces to avoid growing
|
||||
@@ -107,7 +101,7 @@ public class NonceService {
|
||||
sweepExpiredNonces();
|
||||
|
||||
// Generate and store nonce, along with expiration timestamp
|
||||
String nonce = idGenerator.generateIdentifier(NONCE_BITS, false);
|
||||
String nonce = IdentifierGenerator.generateIdentifier(NONCE_BITS, false);
|
||||
nonces.put(nonce, System.currentTimeMillis() + maxAge);
|
||||
return nonce;
|
||||
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
package org.apache.guacamole.auth.saml.acs;
|
||||
|
||||
import org.apache.guacamole.auth.sso.AuthenticationSession;
|
||||
import org.apache.guacamole.net.auth.AuthenticationSession;
|
||||
|
||||
/**
|
||||
* Representation of an in-progress SAML authentication attempt.
|
||||
|
@@ -20,7 +20,7 @@
|
||||
package org.apache.guacamole.auth.saml.acs;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import org.apache.guacamole.auth.sso.AuthenticationSessionManager;
|
||||
import org.apache.guacamole.net.auth.AuthenticationSessionManager;
|
||||
|
||||
/**
|
||||
* Manager service that temporarily stores SAML authentication attempts while
|
||||
|
@@ -36,7 +36,7 @@ import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSecurityException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
|
||||
import org.apache.guacamole.auth.sso.IdentifierGenerator;
|
||||
import org.apache.guacamole.net.auth.IdentifierGenerator;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
@@ -58,12 +58,6 @@ public class SAMLService {
|
||||
@Inject
|
||||
private SAMLAuthenticationSessionManager sessionManager;
|
||||
|
||||
/**
|
||||
* Generator of arbitrary, unique, unpredictable identifiers.
|
||||
*/
|
||||
@Inject
|
||||
private IdentifierGenerator idGenerator;
|
||||
|
||||
/**
|
||||
* Creates a new SAML request, beginning the overall authentication flow
|
||||
* that will ultimately result in an asserted user identity if the user is
|
||||
@@ -89,7 +83,7 @@ public class SAMLService {
|
||||
Auth auth = new Auth(samlSettings, null, null);
|
||||
|
||||
// Generate a unique ID to use for the relay state
|
||||
String identifier = idGenerator.generateIdentifier();
|
||||
String identifier = IdentifierGenerator.generateIdentifier();
|
||||
|
||||
// Create the request URL for the SAML IdP
|
||||
String requestUrl = auth.login(
|
||||
|
@@ -24,7 +24,6 @@ import com.onelogin.saml2.settings.IdPMetadataParser;
|
||||
import com.onelogin.saml2.settings.Saml2Settings;
|
||||
import com.onelogin.saml2.settings.SettingsBuilder;
|
||||
import com.onelogin.saml2.util.Constants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
@@ -20,14 +20,8 @@
|
||||
package org.apache.guacamole.auth.ssl;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.ssl.SSLAuthenticationSessionManager;
|
||||
import org.apache.guacamole.auth.sso.SSOAuthenticationEventListener;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
||||
import org.apache.guacamole.net.event.AuthenticationSuccessEvent;
|
||||
import org.apache.guacamole.net.event.listener.Listener;
|
||||
|
||||
/**
|
||||
* A Listener that will reactivate or invalidate SSL auth sessions depending on
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
package org.apache.guacamole.auth.ssl;
|
||||
|
||||
import org.apache.guacamole.auth.sso.AuthenticationSession;
|
||||
import org.apache.guacamole.net.auth.AuthenticationSession;
|
||||
|
||||
/**
|
||||
* Representation of an in-progress SSL/TLS authentication attempt.
|
||||
|
@@ -20,7 +20,7 @@
|
||||
package org.apache.guacamole.auth.ssl;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import org.apache.guacamole.auth.sso.AuthenticationSessionManager;
|
||||
import org.apache.guacamole.net.auth.AuthenticationSessionManager;
|
||||
|
||||
/**
|
||||
* Manager service that temporarily stores SSL/TLS authentication attempts
|
||||
|
@@ -845,14 +845,13 @@ associate_totp() {
|
||||
|
||||
##
|
||||
## Adds properties to guacamole.properties which configure the Duo two-factor
|
||||
## authentication service. Checks to see if all variables are defined and makes sure
|
||||
## DUO_APPLICATION_KEY is >= 40 characters.
|
||||
## authentication service. Checks to see if all variables are defined
|
||||
##
|
||||
associate_duo() {
|
||||
# Verify required parameters are present
|
||||
if [ -z "$DUO_INTEGRATION_KEY" ] || \
|
||||
[ -z "$DUO_SECRET_KEY" ] || \
|
||||
[ ${#DUO_APPLICATION_KEY} -lt 40 ]
|
||||
if [ -z "$DUO_CLIENT_ID" ] || \
|
||||
[ -z "$DUO_CLIENT_SECRET" ] || \
|
||||
[ -z "$DUO_REDIRECT_URI" ]
|
||||
then
|
||||
cat <<END
|
||||
FATAL: Missing required environment variables
|
||||
@@ -862,21 +861,20 @@ following environment variables:
|
||||
|
||||
DUO_API_HOSTNAME The hostname of the Duo API endpoint.
|
||||
|
||||
DUO_INTEGRATION_KEY The integration key provided for Guacamole by Duo.
|
||||
DUO_CLIENT_ID The client id (or integration key) provided for Guacamole by Duo.
|
||||
|
||||
DUO_SECRET_KEY The secret key provided for Guacamole by Duo.
|
||||
DUO_CLIENT_SECRET The secret key provided for Guacamole by Duo.
|
||||
|
||||
DUO_APPLICATION_KEY An arbitrary, random key.
|
||||
This value must be at least 40 characters.
|
||||
DUO_REDIRECT_URI The URI to redirect back to upon successful authentication.
|
||||
END
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Update config file
|
||||
set_property "duo-api-hostname" "$DUO_API_HOSTNAME"
|
||||
set_property "duo-integration-key" "$DUO_INTEGRATION_KEY"
|
||||
set_property "duo-secret-key" "$DUO_SECRET_KEY"
|
||||
set_property "duo-application-key" "$DUO_APPLICATION_KEY"
|
||||
set_property "duo-client-id" "$DUO_CLIENT_ID"
|
||||
set_property "duo-client-secret" "$DUO_CLIENT_SECRET"
|
||||
set_property "duo-redirect-uri" "$DUO_REDIRECT_URI"
|
||||
|
||||
# Add required .jar files to GUACAMOLE_EXT
|
||||
ln -s /opt/guacamole/duo/guacamole-auth-*.jar "$GUACAMOLE_EXT"
|
||||
|
@@ -136,6 +136,46 @@ public class TranslatableGuacamoleInsufficientCredentialsException
|
||||
this(message, new TranslatableMessage(key), credentialsInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TranslatableGuacamoleInsufficientCredentialsException with the specified message,
|
||||
* translation key, the credential information required for authentication, the state token, and
|
||||
* an expiration timestamp for the state token. The message is provided in both a non-translatable
|
||||
* form and as a translatable key which can be used to retrieve the localized message.
|
||||
*
|
||||
* @param message
|
||||
* A human-readable description of the exception that occurred. This
|
||||
* message should be readable on its own and as-written, without
|
||||
* requiring a translation service.
|
||||
*
|
||||
* @param key
|
||||
* The arbitrary key which can be used to look up the message to be
|
||||
* displayed in the user's native language.
|
||||
*
|
||||
* @param credentialsInfo
|
||||
* Information describing the form of valid credentials.
|
||||
*
|
||||
* @param state
|
||||
* An opaque value that may be used by a client to maintain state across requests which are part
|
||||
* of the same authentication transaction.
|
||||
*
|
||||
* @param providerIdentifier
|
||||
* The identifier of the authentication provider that this exception pertains to.
|
||||
*
|
||||
* @param queryIdentifier
|
||||
* The identifier of the specific query parameter within the
|
||||
* authentication process that this exception pertains to.
|
||||
*
|
||||
* @param expires
|
||||
* The timestamp after which the state token associated with the authentication process expires,
|
||||
* specified as the number of milliseconds since the UNIX epoch.
|
||||
*/
|
||||
public TranslatableGuacamoleInsufficientCredentialsException(String message,
|
||||
String key, CredentialsInfo credentialsInfo, String state, String providerIdentifier,
|
||||
String queryIdentifier, long expires) {
|
||||
super(message, credentialsInfo, state, providerIdentifier, queryIdentifier, expires);
|
||||
this.translatableMessage = new TranslatableMessage(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatableMessage getTranslatableMessage() {
|
||||
return translatableMessage;
|
||||
|
@@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.sso;
|
||||
package org.apache.guacamole.net.auth;
|
||||
|
||||
/**
|
||||
* Representation of an in-progress authentication attempt.
|
@@ -17,10 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.sso;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
package org.apache.guacamole.net.auth;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -39,14 +36,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* @param <T>
|
||||
* The type of sessions managed by this session manager.
|
||||
*/
|
||||
@Singleton
|
||||
public class AuthenticationSessionManager<T extends AuthenticationSession> {
|
||||
|
||||
/**
|
||||
* Generator of arbitrary, unique, unpredictable identifiers.
|
||||
*/
|
||||
@Inject
|
||||
private IdentifierGenerator idGenerator;
|
||||
public abstract class AuthenticationSessionManager<T extends AuthenticationSession> {
|
||||
|
||||
/**
|
||||
* Map of authentication session identifiers to their associated
|
||||
@@ -98,7 +88,7 @@ public class AuthenticationSessionManager<T extends AuthenticationSession> {
|
||||
* token.
|
||||
*/
|
||||
public String generateInvalid() {
|
||||
return idGenerator.generateIdentifier();
|
||||
return IdentifierGenerator.generateIdentifier();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +183,7 @@ public class AuthenticationSessionManager<T extends AuthenticationSession> {
|
||||
* given session when calling resume().
|
||||
*/
|
||||
public String defer(T session) {
|
||||
String identifier = idGenerator.generateIdentifier();
|
||||
String identifier = IdentifierGenerator.generateIdentifier();
|
||||
sessions.put(identifier, session);
|
||||
return identifier;
|
||||
}
|
@@ -34,6 +34,16 @@ import javax.servlet.http.HttpSession;
|
||||
*/
|
||||
public class Credentials implements Serializable {
|
||||
|
||||
/**
|
||||
* The RESUME_QUERY is a query parameter key used to determine which
|
||||
* authentication provider's process should be resumed during multi-step
|
||||
* authentication. The auth provider will set this parameter before
|
||||
* redirecting to an external service, and it is checked upon return to
|
||||
* Guacamole to ensure the correct authentication state is continued
|
||||
* without starting over.
|
||||
*/
|
||||
public static final String RESUME_QUERY = "provider_id";
|
||||
|
||||
/**
|
||||
* Unique identifier associated with this specific version of Credentials.
|
||||
*/
|
||||
|
@@ -17,10 +17,9 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.sso;
|
||||
package org.apache.guacamole.net.auth;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.inject.Singleton;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
@@ -29,14 +28,13 @@ import java.security.SecureRandom;
|
||||
* is an arbitrary, random string produced using a cryptographically-secure
|
||||
* random number generator.
|
||||
*/
|
||||
@Singleton
|
||||
public class IdentifierGenerator {
|
||||
|
||||
/**
|
||||
* Cryptographically-secure random number generator for generating unique
|
||||
* identifiers.
|
||||
*/
|
||||
private final SecureRandom secureRandom = new SecureRandom();
|
||||
private static final SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
/**
|
||||
* Generates a unique and unpredictable identifier. Each identifier is at
|
||||
@@ -48,7 +46,7 @@ public class IdentifierGenerator {
|
||||
* A unique and unpredictable identifier with at least 256 bits of
|
||||
* entropy.
|
||||
*/
|
||||
public String generateIdentifier() {
|
||||
public static String generateIdentifier() {
|
||||
return generateIdentifier(256);
|
||||
}
|
||||
|
||||
@@ -65,7 +63,7 @@ public class IdentifierGenerator {
|
||||
* A unique and unpredictable identifier with at least the given number
|
||||
* of bits of entropy.
|
||||
*/
|
||||
public String generateIdentifier(int minBits) {
|
||||
public static String generateIdentifier(int minBits) {
|
||||
return generateIdentifier(minBits, true);
|
||||
}
|
||||
|
||||
@@ -87,7 +85,7 @@ public class IdentifierGenerator {
|
||||
* A unique and unpredictable identifier with at least the given number
|
||||
* of bits of entropy.
|
||||
*/
|
||||
public String generateIdentifier(int minBits, boolean caseSensitive) {
|
||||
public static String generateIdentifier(int minBits, boolean caseSensitive) {
|
||||
|
||||
// Generate a base64 identifier if we're allowed to vary by case
|
||||
if (caseSensitive) {
|
@@ -28,6 +28,95 @@ package org.apache.guacamole.net.auth.credentials;
|
||||
*/
|
||||
public class GuacamoleInsufficientCredentialsException extends GuacamoleCredentialsException {
|
||||
|
||||
/**
|
||||
* The default state token to use when no specific state information is provided.
|
||||
*/
|
||||
private static final String DEFAULT_STATE = "";
|
||||
|
||||
/**
|
||||
* The default provider identifier to use when no specific provider is identified.
|
||||
* This serves as a placeholder indicating that either no specific provider is
|
||||
* responsible for the exception or the responsible provider has not been identified.
|
||||
*/
|
||||
private static final String DEFAULT_PROVIDER_IDENTIFIER = "";
|
||||
|
||||
/**
|
||||
* The default query identifier to use when no specific query is identified.
|
||||
* This serves as a placeholder and indicates that the specific query related to
|
||||
* the provider's state resume operation has not been provided.
|
||||
*/
|
||||
private static final String DEFAULT_QUERY_IDENTIFIER = "";
|
||||
|
||||
/**
|
||||
* The default expiration timestamp to use when no specific expiration is provided,
|
||||
* effectively indicating that the state token does not expire.
|
||||
*/
|
||||
private static final long DEFAULT_EXPIRES = -1L;
|
||||
|
||||
/**
|
||||
* An opaque value that may be used by a client to maintain state across requests
|
||||
* which are part of the same authentication transaction.
|
||||
*/
|
||||
protected final String state;
|
||||
|
||||
/**
|
||||
* The identifier for the authentication provider that threw this exception.
|
||||
* This is used to link the exception back to the originating source of the
|
||||
* authentication attempt, allowing clients to determine which provider's
|
||||
* authentication process should be resumed.
|
||||
*/
|
||||
protected final String providerIdentifier;
|
||||
|
||||
/**
|
||||
* An identifier for the specific query within the URL for this provider that can
|
||||
* be checked to resume the authentication state.
|
||||
*/
|
||||
protected final String queryIdentifier;
|
||||
|
||||
/**
|
||||
* The timestamp after which the state token associated with the authentication process
|
||||
* should no longer be considered valid, expressed as the number of milliseconds since
|
||||
* UNIX epoch.
|
||||
*/
|
||||
protected final long expires;
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleInsufficientCredentialsException with the specified
|
||||
* message, the credential information required for authentication, the state
|
||||
* token associated with the authentication process, and an expiration timestamp.
|
||||
*
|
||||
* @param message
|
||||
* A human-readable description of the exception that occurred.
|
||||
*
|
||||
* @param credentialsInfo
|
||||
* Information describing the form of valid credentials.
|
||||
*
|
||||
* @param state
|
||||
* An opaque value that may be used by a client to maintain state
|
||||
* across requests which are part of the same authentication transaction.
|
||||
*
|
||||
* @param providerIdentifier
|
||||
* The identifier of the authentication provider that this exception pertains to.
|
||||
*
|
||||
* @param queryIdentifier
|
||||
* The identifier of the specific query parameter within the
|
||||
* authentication process that this exception pertains to.
|
||||
*
|
||||
* @param expires
|
||||
* The timestamp after which the state token associated with the
|
||||
* authentication process should no longer be considered valid, expressed
|
||||
* as the number of milliseconds since UNIX epoch.
|
||||
*/
|
||||
public GuacamoleInsufficientCredentialsException(String message,
|
||||
CredentialsInfo credentialsInfo, String state,
|
||||
String providerIdentifier, String queryIdentifier, long expires) {
|
||||
super(message, credentialsInfo);
|
||||
this.state = state;
|
||||
this.providerIdentifier = providerIdentifier;
|
||||
this.queryIdentifier = queryIdentifier;
|
||||
this.expires = expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleInsufficientCredentialsException with the given
|
||||
* message, cause, and associated credential information.
|
||||
@@ -44,6 +133,10 @@ public class GuacamoleInsufficientCredentialsException extends GuacamoleCredenti
|
||||
public GuacamoleInsufficientCredentialsException(String message, Throwable cause,
|
||||
CredentialsInfo credentialsInfo) {
|
||||
super(message, cause, credentialsInfo);
|
||||
this.state = DEFAULT_STATE;
|
||||
this.providerIdentifier = DEFAULT_PROVIDER_IDENTIFIER;
|
||||
this.queryIdentifier = DEFAULT_QUERY_IDENTIFIER;
|
||||
this.expires = DEFAULT_EXPIRES;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +151,10 @@ public class GuacamoleInsufficientCredentialsException extends GuacamoleCredenti
|
||||
*/
|
||||
public GuacamoleInsufficientCredentialsException(String message, CredentialsInfo credentialsInfo) {
|
||||
super(message, credentialsInfo);
|
||||
this.state = DEFAULT_STATE;
|
||||
this.providerIdentifier = DEFAULT_PROVIDER_IDENTIFIER;
|
||||
this.queryIdentifier = DEFAULT_QUERY_IDENTIFIER;
|
||||
this.expires = DEFAULT_EXPIRES;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +169,52 @@ public class GuacamoleInsufficientCredentialsException extends GuacamoleCredenti
|
||||
*/
|
||||
public GuacamoleInsufficientCredentialsException(Throwable cause, CredentialsInfo credentialsInfo) {
|
||||
super(cause, credentialsInfo);
|
||||
this.state = DEFAULT_STATE;
|
||||
this.providerIdentifier = DEFAULT_PROVIDER_IDENTIFIER;
|
||||
this.queryIdentifier = DEFAULT_QUERY_IDENTIFIER;
|
||||
this.expires = DEFAULT_EXPIRES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the state token associated with the authentication process.
|
||||
*
|
||||
* @return The opaque state token used to maintain consistency across multiple
|
||||
* requests in the same authentication transaction.
|
||||
*/
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the identifier of the authentication provider responsible for this exception.
|
||||
*
|
||||
* @return The identifier of the authentication provider, allowing clients to know
|
||||
* which provider's process should be resumed in response to this exception.
|
||||
*/
|
||||
public String getProviderIdentifier() {
|
||||
return providerIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the specific query identifier associated with the URL for the provider
|
||||
* that can be checked to resume the authentication state.
|
||||
*
|
||||
* @return The query identifier that serves as a reference to a specific point or
|
||||
* transaction within the provider's authentication process.
|
||||
*/
|
||||
public String getQueryIdentifier() {
|
||||
return queryIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the expiration timestamp of the state token, specified as the
|
||||
* number of milliseconds since the UNIX epoch.
|
||||
*
|
||||
* @return The expiration timestamp of the state token, or a negative value if
|
||||
* the token does not expire.
|
||||
*/
|
||||
public long getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,11 +21,14 @@ package org.apache.guacamole.rest.auth;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSecurityException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
||||
import org.apache.guacamole.GuacamoleSession;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
@@ -43,9 +46,13 @@ import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A service for performing authentication checks in REST endpoints.
|
||||
*/
|
||||
@Singleton
|
||||
public class AuthenticationService {
|
||||
|
||||
/**
|
||||
@@ -96,6 +103,11 @@ public class AuthenticationService {
|
||||
*/
|
||||
public static final String TOKEN_PARAMETER_NAME = "token";
|
||||
|
||||
/**
|
||||
* Map to store resumable authentication states with an expiration time.
|
||||
*/
|
||||
private Map<String, ResumableAuthenticationState> resumableStateMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Attempts authentication against all AuthenticationProviders, in order,
|
||||
* using the provided credentials. The first authentication failure takes
|
||||
@@ -310,6 +322,20 @@ public class AuthenticationService {
|
||||
try {
|
||||
userContext = authProvider.getUserContext(authenticatedUser);
|
||||
}
|
||||
catch (GuacamoleInsufficientCredentialsException e) {
|
||||
// Store state and expiration
|
||||
String state = e.getState();
|
||||
long expiration = e.getExpires();
|
||||
String queryIdentifier = e.getQueryIdentifier();
|
||||
String providerIdentifier = e.getProviderIdentifier();
|
||||
|
||||
resumableStateMap.put(state, new ResumableAuthenticationState(providerIdentifier,
|
||||
queryIdentifier, expiration, credentials));
|
||||
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication aborted during initial "
|
||||
+ "UserContext creation.", authProvider, e);
|
||||
}
|
||||
catch (GuacamoleException | RuntimeException | Error e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication aborted during initial "
|
||||
@@ -329,6 +355,82 @@ public class AuthenticationService {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes authentication using given credentials if a matching resumable
|
||||
* state is found.
|
||||
*
|
||||
* @param credentials
|
||||
* The initial credentials containing the request object.
|
||||
*
|
||||
* @return
|
||||
* Resumed credentials if a valid resumable state is found; otherwise,
|
||||
* returns null.
|
||||
*/
|
||||
private Credentials resumeAuthentication(Credentials credentials) {
|
||||
|
||||
Credentials resumedCredentials = null;
|
||||
|
||||
// Retrieve signed State from the request
|
||||
HttpServletRequest request = credentials.getRequest();
|
||||
|
||||
// Retrieve the provider id from the query parameters
|
||||
String resumableProviderId = request.getParameter(Credentials.RESUME_QUERY);
|
||||
// Check if a provider id is set
|
||||
if (resumableProviderId == null || resumableProviderId.isEmpty()) {
|
||||
// Return if a provider id is not set
|
||||
return null;
|
||||
}
|
||||
|
||||
// Use an iterator to safely remove entries while iterating
|
||||
Iterator<Map.Entry<String, ResumableAuthenticationState>> iterator = resumableStateMap.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, ResumableAuthenticationState> entry = iterator.next();
|
||||
ResumableAuthenticationState resumableState = entry.getValue();
|
||||
|
||||
// Check if the provider ID from the request matches the one in the map entry
|
||||
boolean providerMatches = resumableProviderId.equals(resumableState.getProviderIdentifier());
|
||||
if (!providerMatches) {
|
||||
// If the provider doesn't match, skip to the next entry
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use the query identifier from the entry to retrieve the corresponding state parameter
|
||||
String stateQueryParameter = resumableState.getQueryIdentifier();
|
||||
String stateFromParameter = request.getParameter(stateQueryParameter);
|
||||
|
||||
// Check if a state parameter is set
|
||||
if (stateFromParameter == null || stateFromParameter.isEmpty()) {
|
||||
// Remove and continue if`state is not provided or is empty
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the key in the entry (state) matches the state parameter provided in the request
|
||||
if (entry.getKey().equals(stateFromParameter)) {
|
||||
|
||||
// Remove the current entry from the map
|
||||
iterator.remove();
|
||||
|
||||
// Check if the resumableState has expired
|
||||
if (!resumableState.isExpired()) {
|
||||
|
||||
// Set the actualCredentials to the credentials from the matched entry
|
||||
resumedCredentials = resumableState.getCredentials();
|
||||
|
||||
if (resumedCredentials != null) {
|
||||
resumedCredentials.setRequest(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Exit the loop since we've found the matching state and it's unique
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return resumedCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates a user using the given credentials and optional
|
||||
* authentication token, returning the authentication token associated with
|
||||
@@ -367,11 +469,16 @@ public class AuthenticationService {
|
||||
AuthenticatedUser authenticatedUser;
|
||||
String authToken;
|
||||
|
||||
// Retrieve credentials if resuming authentication
|
||||
Credentials actualCredentials = resumeAuthentication(credentials);
|
||||
if (actualCredentials == null)
|
||||
actualCredentials = credentials;
|
||||
|
||||
try {
|
||||
|
||||
// Get up-to-date AuthenticatedUser and associated UserContexts
|
||||
authenticatedUser = getAuthenticatedUser(existingSession, credentials);
|
||||
List<DecoratedUserContext> userContexts = getUserContexts(existingSession, authenticatedUser, credentials);
|
||||
authenticatedUser = getAuthenticatedUser(existingSession, actualCredentials);
|
||||
List<DecoratedUserContext> userContexts = getUserContexts(existingSession, authenticatedUser, actualCredentials);
|
||||
|
||||
// Update existing session, if it exists
|
||||
if (existingSession != null) {
|
||||
@@ -401,7 +508,7 @@ public class AuthenticationService {
|
||||
// Log and rethrow any authentication errors
|
||||
catch (GuacamoleAuthenticationProcessException e) {
|
||||
|
||||
listenerService.handleEvent(new AuthenticationFailureEvent(credentials,
|
||||
listenerService.handleEvent(new AuthenticationFailureEvent(actualCredentials,
|
||||
e.getAuthenticationProvider(), e.getCause()));
|
||||
|
||||
// Rethrow exception
|
||||
|
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.rest.auth;
|
||||
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
|
||||
/**
|
||||
* Encapsulates the state information required for resuming an authentication
|
||||
* process. This includes an expiration timestamp to determine state validity
|
||||
* and the original credentials submitted by the user.
|
||||
*/
|
||||
public class ResumableAuthenticationState {
|
||||
|
||||
/**
|
||||
* The timestamp at which this state should no longer be considered valid,
|
||||
* measured in milliseconds since the Unix epoch.
|
||||
*/
|
||||
private long expirationTimestamp;
|
||||
|
||||
/**
|
||||
* The original user credentials that were submitted at the start of the
|
||||
* authentication process.
|
||||
*/
|
||||
private Credentials credentials;
|
||||
|
||||
/**
|
||||
* A unique string identifying the authentication provider related to the state.
|
||||
* This field allows the client to know which provider's authentication process
|
||||
* should be resumed using this state.
|
||||
*/
|
||||
private String providerIdentifier;
|
||||
|
||||
/**
|
||||
* A unique string that can be used to identify a specific query within the
|
||||
* authentication process for the identified provider. This identifier can
|
||||
* help the resumption of an authentication process.
|
||||
*/
|
||||
private String queryIdentifier;
|
||||
|
||||
/**
|
||||
* Constructs a new ResumableAuthenticationState object with the specified
|
||||
* expiration timestamp and user credentials.
|
||||
*
|
||||
* @param providerIdentifier
|
||||
* The identifier of the authentication provider to which this resumable state pertains.
|
||||
*
|
||||
* @param queryIdenifier
|
||||
* The identifier of the specific query within the provider's
|
||||
* authentication process that this state corresponds to.
|
||||
*
|
||||
* @param expirationTimestamp
|
||||
* The timestamp in milliseconds since the Unix epoch when this state
|
||||
* expires and can no longer be used to resume authentication.
|
||||
*
|
||||
* @param credentials
|
||||
* The Credentials object initially submitted by the user and associated
|
||||
* with this resumable state.
|
||||
*/
|
||||
public ResumableAuthenticationState(String providerIdentifier, String queryIdentifier,
|
||||
long expirationTimestamp, Credentials credentials) {
|
||||
this.expirationTimestamp = expirationTimestamp;
|
||||
this.credentials = credentials;
|
||||
this.providerIdentifier = providerIdentifier;
|
||||
this.queryIdentifier = queryIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this resumable state has expired based on the stored expiration
|
||||
* timestamp and the current system time.
|
||||
*
|
||||
* @return
|
||||
* True if the current system time is after the expiration timestamp,
|
||||
* indicating that the state is expired; false otherwise.
|
||||
*/
|
||||
public boolean isExpired() {
|
||||
return System.currentTimeMillis() >= expirationTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the original credentials associated with this resumable state.
|
||||
*
|
||||
* @return
|
||||
* The Credentials object containing user details that were submitted
|
||||
* when the state was created.
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the identifier of the authentication provider associated with this state.
|
||||
*
|
||||
* @return
|
||||
* The identifier of the authentication provider, providing context for this state
|
||||
* within the overall authentication sequence.
|
||||
*/
|
||||
public String getProviderIdentifier() {
|
||||
return this.providerIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the identifier for a specific query in the authentication
|
||||
* process that is associated with this state.
|
||||
*
|
||||
* @return
|
||||
* The query identifier used for retrieving a value representing the state within
|
||||
* the provider's authentication process that should be resumed.
|
||||
*/
|
||||
public String getQueryIdentifier() {
|
||||
return this.queryIdentifier;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user