GUACAMOLE-1218: Merge "guacamole-auth-json" extension into Apache Guacamole.

This commit is contained in:
Virtually Nick
2020-12-16 14:20:19 -05:00
committed by GitHub
32 changed files with 4171 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
target/
*~

View File

@@ -0,0 +1,189 @@
guacamole-auth-json
===================
guacamole-auth-json is an authentication extension for [Apache
Guacamole](http://guacamole.apache.org/) which authenticates users using JSON
which has been signed using **HMAC/SHA-256** and encrypted with **128-bit AES
in CBC mode**. This JSON contains all information describing the user being
authenticated, as well as any connections they have access to.
Configuring Guacamole to accept encrypted JSON
----------------------------------------------
To verify and decrypt the received signed and encrypted JSON, a secret key must
be generated which will be shared by both the Guacamole server and systems that
will generate the JSON data. As guacamole-auth-json uses 128-bit AES, this key
must be 128 bits.
An easy way of generating such a key is to echo a passphrase through the
"md5sum" utility. This is the technique OpenSSL itself uses to generate 128-bit
keys from passphrases. For example:
$ echo -n "ThisIsATest" | md5sum
4c0b569e4c96df157eee1b65dd0e4d41 -
The generated key must then be saved within `guacamole.properties` as the full
32-digit hex value using the `json-secret-key` property:
json-secret-key: 4c0b569e4c96df157eee1b65dd0e4d41
JSON format
-----------
The general format of the JSON (prior to being encrypted, signed, and sent to
Guacamole), is as follows:
{
"username" : "arbitraryUsername",
"expires" : TIMESTAMP,
"connections" : {
"Connection Name" : {
"protocol" : "PROTOCOL",
"parameters" : {
"name1" : "value1",
"name2" : "value2",
...
}
},
...
}
}
where `TIMESTAMP` is a standard UNIX epoch timestamp with millisecond
resolution (the number of milliseconds since midnight of January 1, 1970 UTC)
and `PROTOCOL` is the internal name of any of Guacamole's supported protocols,
such as `vnc`, `rdp`, or `ssh`.
The JSON will cease to be accepted as valid after the server time passes the
timestamp. If no timestamp is specified, the data will not expire.
The top-level JSON object which must be submitted to Guacamole has the
following properties:
Property name | Type | Description
--------------|----------|------------
`username` | `string` | The unique username of the user authenticated by the JSON. If the user is anonymous, this should be the empty string (`""`).
`expires` | `number` | The absolute time after which the JSON should no longer be accepted, even if the signature is valid, as a standard UNIX epoch timestamp with millisecond resolution (the number of milliseconds since midnight of January 1, 1970 UTC).
`connections` | `object` | The set of connections which should be exposed to the user by their corresponding, unique names. If no connections will be exposed to the user, this can simply be an empty object (`{}`).
Each normal connection defined within each submitted JSON object has the
following properties:
Property name | Type | Description
--------------|----------|------------
`id` | `string` | An optional opaque value which uniquely identifies this connection across all other connections which may be active at any given time. This property is only required if you wish to allow the connection to be shared or shadowed.
`protocol` | `string` | The internal name of a supported protocol, such as `vnc`, `rdp`, or `ssh`.
`parameters` | `object` | An object representing the connection parameter name/value pairs to apply to the connection, as documented in the [Guacamole manual](https://guacamole.apache.org/doc/gug/configuring-guacamole.html#connection-configuration).
Connections which share or shadow other connections use a `join` property
instead of a `protocol` property, where `join` contains the value of the `id`
property of the connection being joined:
Property name | Type | Description
--------------|----------|------------
`id` | `string` | An optional opaque value which uniquely identifies this connection across all other connections which may be active at any given time. This property is only required if you wish to allow the connection to be shared or shadowed. (Yes, a connection which shadows another connection may itself be shadowed.)
`join` | `string` | The opaque ID given within the `id` property of the connection being joined (shared / shadowed).
`parameters` | `object` | An object representing the connection parameter name/value pairs to apply to the connection, as documented in the [Guacamole manual](https://guacamole.apache.org/doc/gug/configuring-guacamole.html#connection-configuration). Most of the connection configuration is inherited from the connection being joined. In general, the only property relevant to joining connections is `read-only`.
If a connection is configured to join another connection, that connection will
only be usable if the connection being joined is currently active. If two
connections are established having the same `id` value, only the last
connection will be joinable using the given `id`.
Generating encrypted JSON
-------------------------
To authenticate a user with the above JSON format, the JSON must be both signed
and encrypted using the same 128-bit secret key specified with the
`json-secret-key` within `guacamole.properties`:
1. Generate JSON in the format described above
2. Sign the JSON using the secret key (the same 128-bit key stored within
`guacamole.properties` with the `json-secret-key` property) with
**HMAC/SHA-256**. Prepend the binary result of the signing process to the
plaintext JSON that was signed.
3. Encrypt the result of (2) above using **AES in CBC mode**, with the initial
vector (IV) set to all zero bytes.
4. Encode the encrypted result using base64.
5. POST the encrypted result to the `/api/tokens` REST endpoint as the value of
an HTTP parameter named `data` (or include it in the URL of any Guacamole
page as a query parameter named `data`).
For example, if Guacamole is running on localhost at `/guacamole`, and
`BASE64_RESULT` is the result of the above process, the equivalent run of
the "curl" utility would be:
$ curl --data-urlencode "data=BASE64_RESULT" http://localhost:8080/guacamole/api/tokens
**NOTE:** Be sure to URL-encode the base64-encoded result prior to POSTing
it to `/api/tokens` or including it in the URL. Base64 can contain both "+"
and "=" characters, which have special meaning within URLs.
If the data is invalid in any way, if the signature does not match, if
decryption or signature verification fails, or if the submitted data has
expired, the REST service will return an invalid credentials error and fail
without user-visible explanation. Details describing the error that occurred
will be in the Tomcat logs, however.
Reference implementation
------------------------
The source includes a shell script, `doc/encrypt-json.sh`, which uses the
OpenSSL command-line utility to encrypt and sign JSON in the manner that
guacamole-auth-json requires. It is thoroughly commented and should work well
as a reference implementation, for testing, and as a point of comparison for
development. The script is run as:
$ ./encrypt-json.sh HEX_ENCRYPTION_KEY file-to-sign-and-encrypt.json
For example, if you have a file called `auth.json` containing the following:
{
"username" : "test",
"expires" : "1446323765000",
"connections" : {
"My Connection" : {
"protocol" : "rdp",
"parameters" : {
"hostname" : "10.10.209.63",
"port" : "3389"
}
},
"My OTHER Connection" : {
"protocol" : "rdp",
"parameters" : {
"hostname" : "10.10.209.64",
"port" : "3389"
}
}
}
}
and you run:
$ ./encrypt-json.sh 4C0B569E4C96DF157EEE1B65DD0E4D41 auth.json
You will receive the following output:
le2Ug6YIo4perD2GV17QtWvOdfSemVDDtCOdRYJlbdUf3fhN+63LpQa1RDkzU7Zc
DW3+OtyTCBGQ7OLO+HpG6pHNom76BXpmnHSRx1UdQ3WVZelPUXEDzxe74aN6DUP9
G9isXhBMdLUhZwEJf4k4Gpzt9MHAH5PufSKq3DO1UHnrRjdGbKKddug2BcuDrwJM
UJf1tRX9CAEC11/gWEwrHDOhH/abeyeDyElbaEG/oOY8EdoFNYgUsjI2x31OpCuB
sEv7FOFafL05wEoIFv0/pPft0DHk7GuvHBBCqXuK98yMEo3d0zD5D+IsOY8Rmm1+
0CoWkX22mqyRQMFS2fTp/fClCN4QLb0aNn+unweTimd2SXN9cjREmZknXf7Tj8oU
/FNXc37i0HEfG5aVgp5znMCwwRAOFnFhLqG3K2yaTRE+hLNBxltIjLfFmNG5TZZA
gUdKyuegsOd0KS5iHdW6tPI01AwfRO9y2z20t3flsgDp50EGWjT2/TTA5Nkjnnjk
JXNzCOfM7DCI/ioEz6Ga140qXfOX/g8SGiukpwt+j0ANI573TdVt7nsp7MZX2qKg
2GcoNqjBqQxqpqI5ZYz4KVfD4cYu8KDZ9MiFMzbUwwKNSzYxiep1KJwiG0HQThHg
oX2FJYOFCFcinQgGkUOaBJK1K0bo1ouaBSe4iGPjd54=
The resulting base64 data above, if submitted using the `data` parameter to
Guacamole, will authenticate a user and grant them access to the connections
described in the JSON (at least until the expires timestamp is reached, at
which point the JSON will no longer be accepted).

View File

@@ -0,0 +1,116 @@
#!/bin/bash -e
#
# 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.
#
##
## @fn encrypt-json.sh
##
## Encrypts and signs JSON using the provided key, returning base64-encoded
## data ready to be submitted to Guacamole and used by the guacamole-auth-json
## authentication provider. Beware that this base64-encoded must still be
## URL-encoded prior to submission to /api/tokens via POST. Base64 encoding may
## contain + and = characters, which have special meaning in URLs.
##
## To submit the resulting data easily via curl, the following will work:
##
## curl --data-urlencode "data=$(<file_containing_result)" GUAC_URL/api/tokens
##
## @param SECRET_KEY
## The key to encrypt and sign the JSON file with, as a 16-byte (32-digit)
## hexadecimal value. This key must match the key specified within
## guacamole.properties using the "json-secret-key" property.
##
## @param JSON_FILENAME
## The filename of the JSON to encrypt and sign.
##
##
## Encryption/signing key.
##
SECRET_KEY="$1"
##
## The filename of the JSON data being signed and encrypted.
##
JSON_FILENAME="$2"
##
## A null (all zeroes) IV.
##
NULL_IV="00000000000000000000000000000000"
##
## Signs the contents of the given file using the given key. The signature is
## created using HMAC/SHA-256, and is output in binary form to STDOUT, followed
## by the raw contents of the file.
##
## @param KEY
## The key to use to sign the contents of the given file with HMAC/SHA-256.
##
## @param FILENAME
## The filename of the file to sign.
##
sign() {
KEY="$1"
FILENAME="$2"
#
# Write out signature
#
openssl dgst \
-sha256 -mac HMAC -macopt hexkey:"$KEY" \
-binary "$FILENAME"
#
# Write out file contents
#
cat "$FILENAME"
}
##
## Encrypts all data received through STDIN using the provided key. Data is
## encrypted using 128-bit AES in CBC mode (with a null IV). The encrypted
## result is printed to STDOUT encoded with base64.
##
## @param KEY
## The key to encrypt STDIN with, as a 16-byte (32-digit) hexadecimal
## value.
##
encrypt() {
KEY="$1"
#
# Encrypt STDIN
#
openssl enc -aes-128-cbc -K "$KEY" -iv "$NULL_IV" -nosalt -a
}
#
# Sign and encrypt file using secret key
#
sign "$SECRET_KEY" "$JSON_FILENAME" | encrypt "$SECRET_KEY"

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-json</artifactId>
<packaging>jar</packaging>
<version>1.3.0</version>
<name>guacamole-auth-json</name>
<url>http://guacamole.apache.org/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<!-- Written for 1.8 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-Werror</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
<!-- Assembly plugin - for easy distribution -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/dist.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-dist-archive</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Copy dependencies prior to packaging -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<!-- Guice -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>3.0</version>
</dependency>
<!-- Jackson for JSON support -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.2</version>
</dependency>
<!-- Java servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Spring security library (required for IP address matching) -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.4.1</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,265 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================
APACHE GUACAMOLE SUBCOMPONENTS
Apache Guacamole includes a number of subcomponents with separate copyright
notices and license terms. Your use of these subcomponents is subject to the
terms and conditions of the following licenses.
AOP Alliance (http://aopalliance.sourceforge.net/)
--------------------------------------------------
Version: 1.0
From: 'AOP Alliance' (http://aopalliance.sourceforge.net/members.html)
License(s):
Public Domain (bundled/aopalliance-1.0/LICENSE)
Google Guice (https://github.com/google/guice)
----------------------------------------------
Version: 3.0
From: 'Google Inc.' (http://www.google.com/)
License(s):
Apache v2.0 (bundled/guice-3.0/COPYING)
Jackson (https://github.com/FasterXML/jackson)
----------------------------------------------
Version: 1.9.2
From: 'FasterXML, LLC' (https://github.com/FasterXML)
License(s):
Apache v2.0 (bundled/jackson-1.9.2/LICENSE-2.0.txt)
JSR-330 / Dependency Injection for Java (http://code.google.com/p/atinject/)
----------------------------------------------------------------------------
Version: 1
From: 'JSR-330 Expert Group' (https://jcp.org/en/jsr/detail?id=330)
License(s):
Apache v2.0 (bundled/javax.inject-1/LICENSE-2.0.txt)
Spring Framework (https://spring.io/projects/spring-framework)
--------------------------------------------------------------
Version: 5.2.9
From: 'Spring' (https://spring.io/)
License(s):
Apache v2.0 (bundled/spring-framework-5.2.9/LICENSE)
Spring Security (https://spring.io/projects/spring-security)
------------------------------------------------------------
Version: 5.4.1
From: 'Spring' (https://spring.io/)
License(s):
Apache v2.0 (bundled/spring-security-5.4.1/LICENSE)

View File

@@ -0,0 +1,5 @@
Apache Guacamole
Copyright 2020 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

View File

@@ -0,0 +1,4 @@
From http://aopalliance.sourceforge.net/:
LICENCE: all the source code provided by AOP Alliance is Public Domain.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View 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.

View 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.

View File

@@ -0,0 +1,20 @@
======================================================================
== NOTICE file corresponding to section 4(d) of the Apache License, ==
== Version 2.0, in this case for the Spring Security distribution. ==
======================================================================
The end-user documentation included with a redistribution, if any,
must include the following acknowledgement:
"This product includes software developed by Spring Security
Project (https://www.springframework.org/security)."
Alternately, this acknowledgement may appear in the software itself,
if and wherever such third-party acknowledgements normally appear.
The names "Spring", "Spring Security", "Spring Security System",
"SpringSource", "Acegi", "Acegi Security", "Acegi Security System",
"Acegi" or any derivatives thereof may not be used to endorse or
promote products derived from this software without prior written
permission. For written permission, please contact
ben.alex@springsource.com.

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0
http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>dist</id>
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
<!-- Output tar.gz -->
<formats>
<format>tar.gz</format>
</formats>
<!-- Include licenses and extension .jar -->
<fileSets>
<!-- Include licenses -->
<fileSet>
<outputDirectory></outputDirectory>
<directory>src/licenses</directory>
</fileSet>
<!-- Include extension .jar -->
<fileSet>
<directory>target</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,116 @@
/*
* 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.json;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.json.user.AuthenticatedUser;
import org.apache.guacamole.auth.json.user.UserContext;
import org.apache.guacamole.auth.json.user.UserData;
import org.apache.guacamole.auth.json.user.UserDataService;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
/**
* Service providing convenience functions for the JSONAuthenticationProvider.
*/
public class AuthenticationProviderService {
/**
* Service for deriving Guacamole extension API data from UserData objects.
*/
@Inject
private UserDataService userDataService;
/**
* Provider for AuthenticatedUser objects.
*/
@Inject
private Provider<AuthenticatedUser> authenticatedUserProvider;
/**
* Provider for UserContext objects.
*/
@Inject
private Provider<UserContext> userContextProvider;
/**
* Returns an AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @param credentials
* The credentials to use for authentication.
*
* @return
* An AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @throws GuacamoleException
* If an error occurs while authenticating the user, or if access is
* denied.
*/
public AuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// Pull UserData from credentials, if possible
UserData userData = userDataService.fromCredentials(credentials);
if (userData == null)
throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.EMPTY);
// Produce AuthenticatedUser associated with derived UserData
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(credentials, userData);
return authenticatedUser;
}
/**
* Returns a UserContext object initialized with data accessible to the
* given AuthenticatedUser.
*
* @param authenticatedUser
* The AuthenticatedUser to retrieve data for.
*
* @return
* A UserContext object initialized with data accessible to the given
* AuthenticatedUser.
*
* @throws GuacamoleException
* If the UserContext cannot be created due to an error.
*/
public UserContext getUserContext(org.apache.guacamole.net.auth.AuthenticatedUser authenticatedUser)
throws GuacamoleException {
// The JSONAuthenticationProvider only provides data for users it has
// authenticated itself
if (!(authenticatedUser instanceof AuthenticatedUser))
return null;
// Return UserContext containing data from the authenticated user's
// associated UserData object
UserContext userContext = userContextProvider.get();
userContext.init(((AuthenticatedUser) authenticatedUser).getUserData());
return userContext;
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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.json;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Collections;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.ByteArrayProperty;
import org.apache.guacamole.properties.StringListProperty;
/**
* Service for retrieving configuration information regarding the JSON
* authentication provider.
*/
public class ConfigurationService {
/**
* The Guacamole server environment.
*/
@Inject
private Environment environment;
/**
* The encryption key to use for all decryption and signature verification.
*/
private static final ByteArrayProperty JSON_SECRET_KEY = new ByteArrayProperty() {
@Override
public String getName() {
return "json-secret-key";
}
};
/**
* A comma-separated list of all IP addresses or CIDR subnets which should
* be allowed to perform authentication. If not specified, ALL address will
* be allowed.
*/
private static final StringListProperty JSON_TRUSTED_NETWORKS = new StringListProperty() {
@Override
public String getName() {
return "json-trusted-networks";
}
};
/**
* Returns the symmetric key which will be used to encrypt and sign all
* JSON data and should be used to decrypt and verify any received JSON
* data. This is dictated by the "json-secret-key" property specified
* within guacamole.properties.
*
* @return
* The key which should be used to decrypt received JSON data.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed, or if the
* "json-secret-key" property is missing.
*/
public byte[] getSecretKey() throws GuacamoleException {
return environment.getRequiredProperty(JSON_SECRET_KEY);
}
/**
* Returns a collection of all IP address or CIDR subnets which should be
* allowed to submit authentication requests. If empty, authentication
* attempts will be allowed through without restriction.
*
* @return
* A collection of all IP address or CIDR subnets which should be
* allowed to submit authentication requests.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public Collection<String> getTrustedNetworks() throws GuacamoleException {
return environment.getProperty(JSON_TRUSTED_NETWORKS, Collections.<String>emptyList());
}
}

View File

@@ -0,0 +1,199 @@
/*
* 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.json;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
/**
* Service for handling cryptography-related operations, such as decrypting
* encrypted data.
*/
public class CryptoService {
/**
* The length of all signatures, in bytes.
*/
public static final int SIGNATURE_LENGTH = 32;
/**
* The name of the key generation algorithm used for decryption.
*/
private static final String DECRYPTION_KEY_GENERATION_ALGORITHM_NAME = "AES";
/**
* The name of the cipher transformation that should be used to decrypt any
* String provided to decrypt().
*/
private static final String DECRYPTION_CIPHER_NAME = "AES/CBC/PKCS5Padding";
/**
* The name of the key generation algorithm used for verifying signatures.
*/
private static final String SIGNATURE_KEY_GENERATION_ALGORITHM_NAME = "HmacSHA256";
/**
* The name of the MAC algorithm used for verifying signatures.
*/
private static final String SIGNATURE_MAC_ALGORITHM_NAME = "HmacSHA256";
/**
* IV which is all null bytes (all binary zeroes). Usually, using a null IV
* is a horrible idea. As our plaintext will always be prepended with the
* HMAC signature of the rest of the message, we are effectively using the
* HMAC signature itself as the IV. For our purposes, where the encrypted
* value becomes an authentication token, this is OK.
*/
private static final IvParameterSpec NULL_IV = new IvParameterSpec(new byte[] {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
});
/**
* Creates a new key suitable for decryption using the provided raw key
* bytes. The algorithm used to generate this key is dictated by
* DECRYPTION_KEY_GENERATION_ALGORITHM_NAME and must match the algorithm
* used by decrypt().
*
* @param keyBytes
* The raw bytes from which the encryption/decryption key should be
* generated.
*
* @return
* A new key suitable for encryption or decryption, generated from the
* given bytes.
*/
public SecretKey createEncryptionKey(byte[] keyBytes) {
return new SecretKeySpec(keyBytes, DECRYPTION_KEY_GENERATION_ALGORITHM_NAME);
}
/**
* Creates a new key suitable for signature verification using the provided
* raw key bytes. The algorithm used to generate this key is dictated by
* SIGNATURE_KEY_GENERATION_ALGORITHM_NAME and must match the algorithm
* used by sign().
*
* @param keyBytes
* The raw bytes from which the signature verification key should be
* generated.
*
* @return
* A new key suitable for signature verification, generated from the
* given bytes.
*/
public SecretKey createSignatureKey(byte[] keyBytes) {
return new SecretKeySpec(keyBytes, SIGNATURE_KEY_GENERATION_ALGORITHM_NAME);
}
/**
* Decrypts the given ciphertext using the provided key, returning the
* resulting plaintext. If any error occurs during decryption at all, a
* GuacamoleException is thrown. The IV used for the decryption process is
* a null IV (all binary zeroes).
*
* @param key
* The key to use to decrypt the provided ciphertext.
*
* @param cipherText
* The ciphertext to decrypt.
*
* @return
* The plaintext which results from decrypting the ciphertext with the
* provided key.
*
* @throws GuacamoleException
* If any error at all occurs during decryption.
*/
public byte[] decrypt(Key key, byte[] cipherText) throws GuacamoleException {
try {
// Init cipher for descryption using secret key
Cipher cipher = Cipher.getInstance(DECRYPTION_CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, key, NULL_IV);
// Perform decryption
return cipher.doFinal(cipherText);
}
// Rethrow all decryption failures identically
catch (InvalidAlgorithmParameterException
| NoSuchAlgorithmException
| NoSuchPaddingException
| InvalidKeyException
| IllegalBlockSizeException
| BadPaddingException e) {
throw new GuacamoleServerException(e);
}
}
/**
* Signs the given arbitrary data using the provided key, returning the
* resulting signature. If any error occurs during signing at all, a
* GuacamoleException is thrown.
*
* @param key
* The key to use to sign the provided data.
*
* @param data
* The arbitrary data to sign.
*
* @return
* The signature which results from signing the arbitrary data with the
* provided key.
*
* @throws GuacamoleException
* If any error at all occurs during signing.
*/
public byte[] sign(Key key, byte[] data) throws GuacamoleException {
try {
// Init MAC for signing using secret key
Mac mac = Mac.getInstance(SIGNATURE_MAC_ALGORITHM_NAME);
mac.init(key);
// Sign provided data
return mac.doFinal(data);
}
// Rethrow all signature failures identically
catch (NoSuchAlgorithmException | InvalidKeyException | IllegalStateException e) {
throw new GuacamoleServerException(e);
}
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.json;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.UserContext;
/**
* Allows users to be authenticated using encrypted blobs of JSON data. The
* username of the user, all available connections, and the parameters
* associated with those connections are all determined by the contents of the
* provided JSON. The JSON itself is authorized by virtue of being properly
* encrypted with a shared key.
*/
public class JSONAuthenticationProvider extends AbstractAuthenticationProvider {
/**
* Injector which will manage the object graph of this authentication
* provider.
*/
private final Injector injector;
/**
* Creates a new JSON AuthenticationProvider that authenticates users
* using encrypted blobs of JSON data.
*
* @throws GuacamoleException
* If a required property is missing, or an error occurs while parsing
* a property.
*/
public JSONAuthenticationProvider() throws GuacamoleException {
// Set up Guice injector.
injector = Guice.createInjector(new JSONAuthenticationProviderModule(this));
}
@Override
public String getIdentifier() {
return "json";
}
@Override
public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException {
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
return authProviderService.authenticateUser(credentials);
}
@Override
public UserContext getUserContext(AuthenticatedUser authenticatedUser)
throws GuacamoleException {
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
return authProviderService.getUserContext(authenticatedUser);
}
}

View File

@@ -0,0 +1,85 @@
/*
* 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.json;
import com.google.inject.AbstractModule;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.json.connection.ConnectionService;
import org.apache.guacamole.auth.json.user.UserDataService;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.auth.AuthenticationProvider;
/**
* Guice module which configures injections specific to the JSON authentication
* provider.
*/
public class JSONAuthenticationProviderModule extends AbstractModule {
/**
* Guacamole server environment.
*/
private final Environment environment;
/**
* A reference to the JSONAuthenticationProvider on behalf of which this
* module has configured injection.
*/
private final AuthenticationProvider authProvider;
/**
* Creates a new JSON authentication provider module which configures
* injection for the JSONAuthenticationProvider.
*
* @param authProvider
* The AuthenticationProvider for which injection is being configured.
*
* @throws GuacamoleException
* If an error occurs while retrieving the Guacamole server
* environment.
*/
public JSONAuthenticationProviderModule(AuthenticationProvider authProvider)
throws GuacamoleException {
// Get local environment
this.environment = new LocalEnvironment();
// Store associated auth provider
this.authProvider = authProvider;
}
@Override
protected void configure() {
// Bind core implementations of guacamole-ext classes
bind(AuthenticationProvider.class).toInstance(authProvider);
bind(Environment.class).toInstance(environment);
// Bind JSON-specific services
bind(ConfigurationService.class);
bind(ConnectionService.class);
bind(CryptoService.class);
bind(RequestValidationService.class);
bind(UserDataService.class);
}
}

View File

@@ -0,0 +1,102 @@
/*
* 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.json;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.GuacamoleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.util.matcher.IpAddressMatcher;
/**
* Service for testing the validity of received HTTP requests.
*/
public class RequestValidationService {
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(RequestValidationService.class);
/**
* Service for retrieving configuration information regarding the
* JSONAuthenticationProvider.
*/
@Inject
private ConfigurationService confService;
/**
* Returns whether the given request can be used for authentication, taking
* into account restrictions specified within guacamole.properties.
*
* @param request
* The HTTP request to test.
*
* @return
* true if the given request comes from a trusted source and can be
* used for authentication, false otherwise.
*/
public boolean isAuthenticationAllowed(HttpServletRequest request) {
// Pull list of all trusted networks
Collection<String> trustedNetworks;
try {
trustedNetworks = confService.getTrustedNetworks();
}
// Deny all requests if restrictions cannot be parsed
catch (GuacamoleException e) {
logger.warn("Authentication request from \"{}\" is DENIED due to parse error: {}", request.getRemoteAddr(), e.getMessage());
logger.debug("Error parsing authentication request restrictions from guacamole.properties.", e);
return false;
}
// All requests are allowed if no restrictions are defined
if (trustedNetworks.isEmpty()) {
logger.debug("Authentication request from \"{}\" is ALLOWED (no restrictions).", request.getRemoteAddr());
return true;
}
// Build matchers for each trusted network
Collection<IpAddressMatcher> matchers = new ArrayList<>(trustedNetworks.size());
for (String network : trustedNetworks)
matchers.add(new IpAddressMatcher(network));
// Otherwise ensure at least one subnet matches
for (IpAddressMatcher matcher : matchers) {
// Request is allowed if any subnet matches
if (matcher.matches(request)) {
logger.debug("Authentication request from \"{}\" is ALLOWED (matched subnet).", request.getRemoteAddr());
return true;
}
}
// Otherwise request is denied - no subnets matched
logger.debug("Authentication request from \"{}\" is DENIED (did not match subnet).", request.getRemoteAddr());
return false;
}
}

View File

@@ -0,0 +1,303 @@
/*
* 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.json.connection;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.auth.json.user.UserData;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.io.GuacamoleReader;
import org.apache.guacamole.io.GuacamoleWriter;
import org.apache.guacamole.net.GuacamoleSocket;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.InetGuacamoleSocket;
import org.apache.guacamole.net.SSLGuacamoleSocket;
import org.apache.guacamole.net.SimpleGuacamoleTunnel;
import org.apache.guacamole.net.auth.GuacamoleProxyConfiguration;
import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket;
import org.apache.guacamole.protocol.GuacamoleClientInformation;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service which provides a centralized means of establishing connections,
* tracking/joining active connections, and retrieving associated data.
*/
@Singleton
public class ConnectionService {
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(ConnectionService.class);
/**
* The Guacamole server environment.
*/
@Inject
private Environment environment;
/**
* Mapping of the unique IDs of active connections (as specified within the
* UserData.Connection object) to the underlying connection ID (as returned
* via the Guacamole protocol handshake). Only connections with defined IDs
* are tracked here.
*/
private final ConcurrentHashMap<String, String> activeConnections =
new ConcurrentHashMap<>();
/**
* Mapping of the connection IDs of joinable connections (as returned via
* the Guacamole protocol handshake) to the Collection of tunnels shadowing
* those connections.
*/
private final ConcurrentHashMap<String, Collection<GuacamoleTunnel>> shadowers =
new ConcurrentHashMap<>();
/**
* Generates a new GuacamoleConfiguration from the associated protocol and
* parameters of the given UserData.Connection. If the configuration cannot
* be generated (because a connection is being joined by that connection is
* not actually active), null is returned.
*
* @param connection
* The UserData.Connection whose protocol and parameters should be used
* to construct the new GuacamoleConfiguration.
*
* @return
* A new GuacamoleConfiguration generated from the associated protocol
* and parameters of the given UserData.Connection, or null if the
* configuration cannot be generated.
*/
public GuacamoleConfiguration getConfiguration(UserData.Connection connection) {
GuacamoleConfiguration config = new GuacamoleConfiguration();
// Set connection ID if joining an active connection
String primaryConnection = connection.getPrimaryConnection();
if (primaryConnection != null) {
// Verify that the connection being joined actually exists
String id = activeConnections.get(primaryConnection);
if (id == null)
return null;
config.setConnectionID(id);
}
// Otherwise, require protocol
else
config.setProtocol(connection.getProtocol());
// Add all parameter name/value pairs
Map<String, String> parameters = connection.getParameters();
if (parameters != null)
config.setParameters(parameters);
return config;
}
/**
* Closes all tunnels within the given connection. If a GuacamoleException
* is thrown by any tunnel during closure, that exception is ignored.
*
* @param tunnels
* The Collection of tunnels to close.
*/
private void closeAll(Collection<GuacamoleTunnel> tunnels) {
for (GuacamoleTunnel tunnel : tunnels) {
try {
tunnel.close();
}
catch (GuacamoleException e) {
logger.debug("Failure to close tunnel masked by closeAll().", e);
}
}
}
/**
* Establishes a connection to guacd using the information associated with
* the given connection object. The resulting connection will be provided
* the given client information during the Guacamole protocol handshake.
*
* @param connection
* The connection object describing the nature of the connection to be
* established.
*
* @param info
* Information associated with the connecting client.
*
* @return
* A fully-established GuacamoleTunnel.
*
* @throws GuacamoleException
* If an error occurs while connecting to guacd, or if permission to
* connect is denied.
*/
public GuacamoleTunnel connect(UserData.Connection connection,
GuacamoleClientInformation info) throws GuacamoleException {
// Retrieve proxy configuration from environment
GuacamoleProxyConfiguration proxyConfig = environment.getDefaultGuacamoleProxyConfiguration();
// Get guacd connection parameters
String hostname = proxyConfig.getHostname();
int port = proxyConfig.getPort();
// Generate and verify connection configuration
GuacamoleConfiguration config = getConfiguration(connection);
if (config == null) {
logger.debug("Configuration for connection could not be "
+ "generated. Perhaps the connection being joined is not "
+ "active?");
throw new GuacamoleResourceNotFoundException("No such connection");
}
// Determine socket type based on required encryption method
final ConfiguredGuacamoleSocket socket;
switch (proxyConfig.getEncryptionMethod()) {
// If guacd requires SSL, use it
case SSL:
socket = new ConfiguredGuacamoleSocket(
new SSLGuacamoleSocket(hostname, port),
config, info
);
break;
// Connect directly via TCP if encryption is not enabled
case NONE:
socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(hostname, port),
config, info
);
break;
// Abort if encryption method is unknown
default:
throw new GuacamoleServerException("Unimplemented encryption method.");
}
final GuacamoleTunnel tunnel;
// If the current connection is not being tracked (no ID) just use a
// normal, non-tracking tunnel
final String id = connection.getId();
if (id == null)
tunnel = new SimpleGuacamoleTunnel(socket);
// Otherwise, create a tunnel with proper tracking which can be joined
else {
// Allow connection to be joined
final String connectionID = socket.getConnectionID();
final Collection<GuacamoleTunnel> existingTunnels = shadowers.putIfAbsent(connectionID,
Collections.synchronizedList(new ArrayList<>()));
// Duplicate connection IDs cannot exist
assert(existingTunnels == null);
// If the current connection is intended to be tracked (an ID was
// provided), but a connection is already in progress with that ID,
// log a warning that the original connection will no longer be tracked
String activeConnection = activeConnections.put(id, connectionID);
if (activeConnection != null)
logger.warn("A connection with ID \"{}\" is already in progress, "
+ "but another attempt to use this ID has been made. The "
+ "original connection will no longer be joinable.", id);
// Return a tunnel which automatically tracks the active connection
tunnel = new SimpleGuacamoleTunnel(new GuacamoleSocket() {
@Override
public GuacamoleReader getReader() {
return socket.getReader();
}
@Override
public GuacamoleWriter getWriter() {
return socket.getWriter();
}
@Override
public void close() throws GuacamoleException {
// Stop connection from being joined further
activeConnections.remove(id, connectionID);
// Close all connections sharing the closed connection
Collection<GuacamoleTunnel> tunnels = shadowers.remove(connectionID);
if (tunnels != null)
closeAll(tunnels);
socket.close();
}
@Override
public boolean isOpen() {
return socket.isOpen();
}
});
}
// Track tunnels which join connections, such that they can be
// automatically closed when the joined connection closes
String joinedConnection = config.getConnectionID();
if (joinedConnection != null) {
// Track shadower of joined connection if possible
Collection<GuacamoleTunnel> tunnels = shadowers.get(joinedConnection);
if (tunnels != null)
tunnels.add(tunnel);
// Close this tunnel in ALL CASES if the joined connection has
// closed. Note that it is insufficient to simply check whether the
// retrieved Collection is null here, as it may have been removed
// after retrieval. We must ensure that the tunnel is closed in any
// case where it will not automatically be closed due to the
// closure of the shadowed connection.
if (!shadowers.containsKey(joinedConnection))
tunnel.close();
}
return tunnel;
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.json.user;
import com.google.inject.Inject;
import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials;
/**
* An implementation of AuthenticatedUser specific to the
* JSONAuthenticationProvider, providing access to the decrypted contents of
* the JSON provided during authentication.
*/
public class AuthenticatedUser extends AbstractAuthenticatedUser {
/**
* Reference to the authentication provider associated with this
* authenticated user.
*/
@Inject
private AuthenticationProvider authProvider;
/**
* The credentials provided when this user was authenticated.
*/
private Credentials credentials;
/**
* The UserData object derived from the data submitted when this user was
* authenticated.
*/
private UserData userData;
/**
* Initializes this AuthenticatedUser using the given credentials and
* UserData object. The provided UserData object MUST have been derived
* from the data submitted when the user authenticated.
*
* @param credentials
* The credentials provided when this user was authenticated.
*
* @param userData
* The UserData object derived from the data submitted when this user
* was authenticated.
*/
public void init(Credentials credentials, UserData userData) {
this.credentials = credentials;
this.userData = userData;
setIdentifier(userData.getUsername());
}
@Override
public AuthenticationProvider getAuthenticationProvider() {
return authProvider;
}
@Override
public Credentials getCredentials() {
return credentials;
}
/**
* Returns the UserData object derived from the data submitted when this
* user was authenticated.
*
* @return
* The UserData object derived from the data submitted when this user
* was authenticated.
*/
public UserData getUserData() {
return userData;
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.json.user;
import com.google.inject.Inject;
import org.apache.guacamole.net.auth.AbstractUserContext;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.User;
/**
* An implementation of UserContext specific to the JSONAuthenticationProvider
* which obtains all data from the encrypted JSON provided during
* authentication.
*/
public class UserContext extends AbstractUserContext {
/**
* The identifier reserved for the root connection group.
*/
public static final String ROOT_CONNECTION_GROUP = DEFAULT_ROOT_CONNECTION_GROUP;
/**
* Reference to the AuthenticationProvider associated with this
* UserContext.
*/
@Inject
private AuthenticationProvider authProvider;
/**
* Service for deriving Guacamole extension API data from UserData objects.
*/
@Inject
private UserDataService userDataService;
/**
* The UserData object associated with the user to whom this UserContext
* belongs.
*/
private UserData userData;
/**
* Initializes this UserContext using the data associated with the provided
* UserData object.
*
* @param userData
* The UserData object derived from the JSON data received when the
* user authenticated.
*/
public void init(UserData userData) {
this.userData = userData;
}
@Override
public User self() {
return userDataService.getUser(userData);
}
@Override
public AuthenticationProvider getAuthenticationProvider() {
return authProvider;
}
@Override
public Directory<Connection> getConnectionDirectory() {
return userDataService.getConnectionDirectory(userData);
}
}

View File

@@ -0,0 +1,386 @@
/*
* 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.json.user;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
/**
* All data associated with a particular user, as parsed from the JSON supplied
* within the encrypted blob provided during authentication.
*/
public class UserData {
/**
* The username of the user associated with this data.
*/
private String username;
/**
* The time after which this data is no longer valid and must not be used.
* This is a UNIX-style epoch timestamp, stored as the number of
* milliseconds since midnight of January 1, 1970 UTC.
*/
private Long expires;
/**
* Whether this data can only be used once. If set to true, reuse of the
* associated signed data will not be allowed. This is only valid if the
* expiration timestamp has been set.
*/
private boolean singleUse = false;
/**
* All connections accessible by this user. The key of each entry is both
* the connection identifier and the connection name.
*/
private ConcurrentMap<String, Connection> connections;
/**
* The data associated with a Guacamole connection stored within a UserData
* object.
*/
public static class Connection {
/**
* An arbitrary, opaque, unique ID for this connection. If specified
* via the "join" (primaryConnection) property of another connection,
* that connection may be used to join this connection.
*/
private String id;
/**
* The protocol that this connection should use, such as "vnc" or "rdp".
*/
private String protocol;
/**
* The opaque ID of the connection being joined (shared), as given with
* the "id" property. If specified, the provided protocol is ignored.
* This value is exposed via the "join" property within JSON.
*/
private String primaryConnection;
/**
* Map of all connection parameter values, where each key is the parameter
* name. Legal parameter names are dictated by the specified protocol and
* are documented within the Guacamole manual:
*
* http://guac-dev.org/doc/gug/configuring-guacamole.html#connection-configuration
*/
private Map<String, String> parameters;
/**
* Whether this connection can only be used once. If set to true, the
* connection will be removed from the connections directory
* immediately upon use.
*/
private boolean singleUse = false;
/**
* Returns an arbitrary, opaque, unique ID for this connection. If
* defined, this ID may be used via the "join" (primaryConnection)
* property of another connection to join (share) this connection while
* it is in progress.
*
* @return
* An arbitrary, opaque, unique ID for this connection.
*/
public String getId() {
return id;
}
/**
* Sets an arbitrary, opaque ID which uniquely identifies this
* connection. This ID may be used via the "join" (primaryConnection)
* property of another connection to join (share) this connection while
* it is in progress.
*
* @param id
* An arbitrary, opaque, unique ID for this connection.
*/
public void setId(String id) {
this.id = id;
}
/**
* Returns the protocol that this connection should use, such as "vnc"
* or "rdp".
*
* @return
* The name of the protocol to use, such as "vnc" or "rdp".
*/
public String getProtocol() {
return protocol;
}
/**
* Sets the protocol that this connection should use, such as "vnc"
* or "rdp".
*
* @param protocol
* The name of the protocol to use, such as "vnc" or "rdp".
*/
public void setProtocol(String protocol) {
this.protocol = protocol;
}
/**
* Returns the opaque ID of the connection being joined (shared), if
* any. If specified, any provided protocol is ignored. This value is
* exposed via the "join" property within JSON.
*
* @return
* The opaque ID of the connection being joined (shared), if any.
*/
@JsonProperty("join")
public String getPrimaryConnection() {
return primaryConnection;
}
/**
* Sets the opaque ID of the connection being joined (shared). If
* specified, any provided protocol is ignored. This is exposed via the
* "join" property within JSON.
*
* @param primaryConnection
* The opaque ID of the connection being joined (shared).
*/
@JsonProperty("join")
public void setPrimaryConnection(String primaryConnection) {
this.primaryConnection = primaryConnection;
}
/**
* Returns a map of all parameter name/value pairs, where the key of
* each entry in the map is the corresponding parameter name. Changes
* to this map directly affect the parameters associated with this
* connection.
*
* @return
* A map of all parameter name/value pairs associated with this
* connection.
*/
public Map<String, String> getParameters() {
return parameters;
}
/**
* Replaces all parameters associated with this connection with the
* name/value pairs in the provided map, where the key of each entry
* in the map is the corresponding parameter name. Changes to this map
* directly affect the parameters associated with this connection.
*
* @param parameters
* The map of all parameter name/value pairs to associate with this
* connection.
*/
public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
}
/**
* Returns whether this connection is intended for single-use only. A
* single-use connection cannot be used more than once.
*
* After a single-use connection is used, it should be automatically
* and atomically removed from any underlying data (such as with
* UserData.removeConnection()).
*
* @return
* true if this connection is intended for single-use only, false
* otherwise.
*/
public boolean isSingleUse() {
return singleUse;
}
/**
* Sets whether this connection is intended for single-use only. A
* single-use connection cannot be used more than once. By default,
* connections are NOT single-use.
*
* After a single-use connection is used, it should be automatically
* and atomically removed from any underlying data (such as with
* UserData.removeConnection()).
*
* @param singleUse
* true if this connection is intended for single-use only, false
* otherwise.
*/
public void setSingleUse(boolean singleUse) {
this.singleUse = singleUse;
}
}
/**
* Returns the username of the user associated with the data stored in this
* object.
*
* @return
* The username of the user associated with the data stored in this
* object.
*/
public String getUsername() {
return username;
}
/**
* Sets the username of the user associated with the data stored in this
* object.
*
* @param username
* The username of the user to associate with the data stored in this
* object.
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Returns the time after which the data stored in this object is invalid
* and must not be used. The time returned is a UNIX-style epoch timestamp
* whose value is the number of milliseconds since midnight of January 1,
* 1970 UTC. If this object does not expire, null is returned.
*
* @return
* The time after which the data stored in this object is invalid and
* must not be used, or null if this object does not expire.
*/
public Long getExpires() {
return expires;
}
/**
* Sets the time after which the data stored in this object is invalid
* and must not be used. The time provided MUST be a UNIX-style epoch
* timestamp whose value is the number of milliseconds since midnight of
* January 1, 1970 UTC. If this object should not expire, the value
* provided should be null.
*
* @param expires
* The time after which the data stored in this object is invalid and
* must not be used, or null if this object does not expire.
*/
public void setExpires(Long expires) {
this.expires = expires;
}
/**
* Returns whether this user data is intended for single-use only.
* Single-use data cannot be used more than once. This flag only has
* meaning if the data also has an expires timestamp.
*
* @return
* true if this data is intended for single-use only, false
* otherwise.
*/
public boolean isSingleUse() {
return singleUse;
}
/**
* Sets whether this user data is intended for single-use only. Single-use
* data cannot be used more than once. This flag only has meaning if the
* data also has an expires timestamp. By default, user data is NOT
* single-use.
*
* @param singleUse
* true if this data is intended for single-use only, false
* otherwise.
*/
public void setSingleUse(boolean singleUse) {
this.singleUse = singleUse;
}
/**
* Returns all connections stored within this UserData object as an
* unmodifiable map. Each of these connections is accessible by the user
* specified by getUsername(). The key of each entry within the map is the
* identifier and human-readable name of the corresponding connection.
*
* @return
* An unmodifiable map of all connections stored within this
* UserData object, where the key of each entry is the identifier of
* the corresponding connection.
*/
public Map<String, Connection> getConnections() {
return connections == null ? null : Collections.unmodifiableMap(connections);
}
/**
* Replaces all connections stored within this UserData object with the
* given connections. Each of these connections will be accessible by the
* user specified by getUsername(). The key of each entry within the map is
* the identifier and human-readable name of the corresponding connection.
*
* @param connections
* A map of all connections to be stored within this UserData object,
* where the key of each entry is the identifier of the corresponding
* connection.
*/
public void setConnections(Map<String, Connection> connections) {
this.connections = new ConcurrentHashMap<>(connections);
}
/**
* Removes the connection having the given identifier from the overall map
* of connections, such that it cannot be used further. This operation is
* atomic.
*
* @param identifier
* The identifier of the connection to remove.
*
* @return
* The connection that was removed, or null if no such connection
* exists.
*/
public Connection removeConnection(String identifier) {
return connections.remove(identifier);
}
/**
* Returns whether the data within this UserData object is expired, and
* thus must not be used, according to the timestamp returned by
* getExpires().
*
* @return
* true if the data within this UserData object is expired and must not
* be used, false otherwise.
*/
@JsonIgnore
public boolean isExpired() {
// Do not bother comparing if this UserData object does not expire
Long expirationTimestamp = getExpires();
if (expirationTimestamp == null)
return false;
// Otherwise, compare expiration timestamp against system time
return System.currentTimeMillis() > expirationTimestamp;
}
}

View File

@@ -0,0 +1,187 @@
/*
* 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.json.user;
import com.google.inject.Inject;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.auth.json.connection.ConnectionService;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.protocol.GuacamoleClientInformation;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
/**
* Connection implementation which automatically manages related UserData if
* the connection is used. Connections which are marked as single-use will
* be removed from the given UserData such that only the first connection
* attempt can succeed.
*/
public class UserDataConnection implements Connection {
/**
* Service for establishing and managing connections.
*/
@Inject
private ConnectionService connectionService;
/**
* A human-readable value which both uniquely identifies this connection
* and serves as the connection display name.
*/
private String identifier;
/**
* The UserData associated with this connection. This UserData will be
* automatically updated as this connection is used.
*/
private UserData data;
/**
* The connection entry for this connection within the associated UserData.
*/
private UserData.Connection connection;
/**
* Initializes this UserDataConnection with the given data, unique
* identifier, and connection information. This function MUST be invoked
* before any particular UserDataConnection is actually used.
*
* @param data
* The UserData that this connection should manage.
*
* @param identifier
* The identifier associated with this connection within the given
* UserData.
*
* @param connection
* The connection data associated with this connection within the given
* UserData.
*
* @return
* A reference to this UserDataConnection.
*/
public UserDataConnection init(UserData data, String identifier,
UserData.Connection connection) {
this.identifier = identifier;
this.data = data;
this.connection = connection;
return this;
}
@Override
public String getIdentifier() {
return identifier;
}
@Override
public void setIdentifier(String identifier) {
throw new UnsupportedOperationException("UserDataConnection is immutable.");
}
@Override
public String getName() {
return identifier;
}
@Override
public void setName(String name) {
throw new UnsupportedOperationException("UserDataConnection is immutable.");
}
@Override
public String getParentIdentifier() {
return UserContext.ROOT_CONNECTION_GROUP;
}
@Override
public void setParentIdentifier(String parentIdentifier) {
throw new UnsupportedOperationException("UserDataConnection is immutable.");
}
@Override
public GuacamoleConfiguration getConfiguration() {
// Generate configuration, using a skeleton configuration if generation
// fails
GuacamoleConfiguration config = connectionService.getConfiguration(connection);
if (config == null)
config = new GuacamoleConfiguration();
return config;
}
@Override
public void setConfiguration(GuacamoleConfiguration config) {
throw new UnsupportedOperationException("UserDataConnection is immutable.");
}
@Override
public Map<String, String> getAttributes() {
return Collections.<String, String>emptyMap();
}
@Override
public void setAttributes(Map<String, String> attributes) {
throw new UnsupportedOperationException("UserDataConnection is immutable.");
}
@Override
public Date getLastActive() {
return null;
}
@Override
public Set<String> getSharingProfileIdentifiers() throws GuacamoleException {
return Collections.<String>emptySet();
}
@Override
public int getActiveConnections() {
return 0;
}
@Override
public GuacamoleTunnel connect(GuacamoleClientInformation info,
Map<String, String> tokens) throws GuacamoleException {
// Prevent future use immediately upon connect
if (connection.isSingleUse()) {
// Deny access if another user already used the connection
if (data.removeConnection(getIdentifier()) == null)
throw new GuacamoleSecurityException("Permission denied");
}
// Perform connection operation
return connectionService.connect(connection, info);
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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.json.user;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.xml.bind.DatatypeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Atomic denylist of UserData objects, stored by their associated
* cryptographic signatures. UserData objects stored within this denylist MUST
* have an associated expiration timestamp, and will automatically be removed
* from the denylist once they have expired.
*/
public class UserDataDenylist {
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(UserDataDenylist.class);
/**
* All denylisted UserData objects, stored by their associated
* cryptographic signatures. NOTE: Each key into this map is the hex
* string produced by encoding the binary signature using DatatypeConverter.
* A byte[] cannot be used directly.
*/
private final ConcurrentMap<String, UserData> denylist = new ConcurrentHashMap<>();
/**
* Removes all expired UserData objects from the denylist. This will
* automatically be invoked whenever new UserData is added to the denylist.
*/
public void removeExpired() {
// Remove expired data from denylist
Iterator<Map.Entry<String, UserData>> current = denylist.entrySet().iterator();
while (current.hasNext()) {
// Remove entry from map if its associated with expired data
Map.Entry<String, UserData> entry = current.next();
if (entry.getValue().isExpired())
current.remove();
}
}
/**
* Adds the given UserData to the denylist, storing it according to the
* provided cryptographic signature. The UserData MUST have an associated
* expiration timestamp. If any UserData objects already within the
* denylist have expired, they will automatically be removed when this
* function is invoked.
*
* @param data
* The UserData to store within the denylist.
*
* @param signature
* The cryptographic signature associated with the UserData.
*
* @return
* true if the UserData was not already denylisted and has
* successfully been added, false otherwise.
*/
public boolean add(UserData data, byte[] signature) {
// Expiration timestamps must be provided
if (data.getExpires() == null) {
logger.warn("An expiration timestamp MUST be provided for "
+ "single-use data.");
return false;
}
// Remove any expired entries
removeExpired();
// Expired user data is implicitly denylisted
if (data.isExpired())
return false;
// Add to denylist only if not already present
String signatureHex = DatatypeConverter.printHexBinary(signature);
return denylist.putIfAbsent(signatureHex, data) == null;
}
}

View File

@@ -0,0 +1,373 @@
/*
* 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.json.user;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.json.ConfigurationService;
import org.apache.guacamole.auth.json.CryptoService;
import org.apache.guacamole.auth.json.RequestValidationService;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.simple.SimpleDirectory;
import org.apache.guacamole.net.auth.simple.SimpleObjectPermissionSet;
import org.apache.guacamole.net.auth.simple.SimpleUser;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service for deriving Guacamole extension API data from UserData objects.
*/
@Singleton
public class UserDataService {
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(UserDataService.class);
/**
* ObjectMapper for deserializing UserData objects.
*/
private static final ObjectMapper mapper = new ObjectMapper();
/**
* Denylist of single-use user data objects which have already been used.
*/
private final UserDataDenylist denylist = new UserDataDenylist();
/**
* Service for retrieving configuration information regarding the
* JSONAuthenticationProvider.
*/
@Inject
private ConfigurationService confService;
/**
* Service for testing the validity of HTTP requests.
*/
@Inject
private RequestValidationService requestService;
/**
* Service for handling cryptography-related operations.
*/
@Inject
private CryptoService cryptoService;
/**
* Provider for UserDataConnection instances.
*/
@Inject
private Provider<UserDataConnection> userDataConnectionProvider;
/**
* The name of the HTTP parameter from which base64-encoded, encrypted JSON
* data should be read. The value of this parameter, when decoded and
* decrypted, must be valid JSON prepended with the 32-byte raw binary
* signature generated through signing the JSON with the secret key using
* HMAC/SHA-256.
*/
public static final String ENCRYPTED_DATA_PARAMETER = "data";
/**
* Derives a new UserData object from the data contained within the given
* Credentials. If no such data is present, or the data present is invalid,
* null is returned.
*
* @param credentials
* The Credentials from which the new UserData object should be
* derived.
*
* @return
* A new UserData object derived from the data contained within the
* given Credentials, or null if no such data is present or if the data
* present is invalid.
*/
public UserData fromCredentials(Credentials credentials) {
String json;
byte[] correctSignature;
// Pull HTTP request, if available
HttpServletRequest request = credentials.getRequest();
if (request == null)
return null;
// Abort if the request itself is not allowed
if (!requestService.isAuthenticationAllowed(request))
return null;
// Pull base64-encoded, encrypted JSON data from HTTP request, if any
// such data is present
String base64 = request.getParameter(ENCRYPTED_DATA_PARAMETER);
if (base64 == null)
return null;
// Decrypt base64-encoded parameter
try {
// Decrypt using defined encryption key
byte[] decrypted = cryptoService.decrypt(
cryptoService.createEncryptionKey(confService.getSecretKey()),
DatatypeConverter.parseBase64Binary(base64)
);
// Abort if decrypted value cannot possibly have a signature AND data
if (decrypted.length <= CryptoService.SIGNATURE_LENGTH) {
logger.warn("Submitted data is too small to contain both a signature and JSON.");
return null;
}
// Split data into signature and JSON portions
byte[] receivedSignature = Arrays.copyOf(decrypted, CryptoService.SIGNATURE_LENGTH);
byte[] receivedJSON = Arrays.copyOfRange(decrypted, CryptoService.SIGNATURE_LENGTH, decrypted.length);
// Produce signature for decrypted data
correctSignature = cryptoService.sign(
cryptoService.createSignatureKey(confService.getSecretKey()),
receivedJSON
);
// Verify signatures
if (!Arrays.equals(receivedSignature, correctSignature)) {
logger.warn("Signature of submitted data is incorrect.");
return null;
}
// Convert from UTF-8
json = new String(receivedJSON, "UTF-8");
}
// Fail if base64 data is not valid
catch (IllegalArgumentException e) {
logger.warn("Submitted data is not proper base64.");
logger.debug("Invalid base64 data.", e);
return null;
}
// Handle lack of standard UTF-8 support (should never happen)
catch (UnsupportedEncodingException e) {
logger.error("Unexpected lack of support for UTF-8: {}", e.getMessage());
logger.debug("Unable to decode base64 data as UTF-8.", e);
return null;
}
// Fail if decryption or key retrieval fails for any reason
catch (GuacamoleException e) {
logger.error("Decryption of received data failed: {}", e.getMessage());
logger.debug("Unable to decrypt received data.", e);
return null;
}
// Deserialize UserData from submitted JSON data
try {
// Deserialize UserData, but reject if expired
UserData userData = mapper.readValue(json, UserData.class);
if (userData.isExpired())
return null;
// Reject if data is single-use and already present in the denylist
if (userData.isSingleUse() && !denylist.add(userData, correctSignature))
return null;
return userData;
}
// Fail UserData creation if JSON is invalid/unreadable
catch (IOException e) {
logger.error("Received JSON is invalid: {}", e.getMessage());
logger.debug("Error parsing UserData JSON.", e);
return null;
}
}
/**
* Returns the identifiers of all users readable by the user whose data is
* given by the provided UserData object. As users of the
* JSONAuthenticationProvider can only see themselves, this will always
* simply be a set of the user's own username.
*
* @param userData
* All data associated with the user whose accessible user identifiers
* are being retrieved.
*
* @return
* A set containing the identifiers of all users readable by the user
* whose data is given by the provided UserData object.
*/
public Set<String> getUserIdentifiers(UserData userData) {
// Each user can only see themselves
return Collections.singleton(userData.getUsername());
}
/**
* Returns the user object of the user to whom the given UserData object
* belongs.
*
* @param userData
* All data associated with the user whose own user object is being
* retrieved.
*
* @return
* The user object of the user to whom the given UserData object
* belongs.
*/
public User getUser(UserData userData) {
// Build user object with READ access to all available data
return new SimpleUser(userData.getUsername()) {
@Override
public ObjectPermissionSet getUserPermissions() throws GuacamoleException {
return new SimpleObjectPermissionSet(getUserIdentifiers(userData));
}
@Override
public ObjectPermissionSet getConnectionPermissions() throws GuacamoleException {
return new SimpleObjectPermissionSet(getConnectionIdentifiers(userData));
}
@Override
public ObjectPermissionSet getConnectionGroupPermissions() throws GuacamoleException {
return new SimpleObjectPermissionSet(getConnectionGroupIdentifiers(userData));
}
};
}
/**
* Returns the identifiers of all connections readable by the user whose
* data is given by the provided UserData object. If the provided UserData
* is not expired, this will be the set of all connection identifiers
* within the UserData. If the UserData is expired, this will be an empty
* set.
*
* @param userData
* All data associated with the user whose accessible connection
* identifiers are being retrieved.
*
* @return
* A set containing the identifiers of all connections readable by the
* user whose data is given by the provided UserData object.
*/
public Set<String> getConnectionIdentifiers(UserData userData) {
// Do not return any connections if empty or expired
Map<String, UserData.Connection> connections = userData.getConnections();
if (connections == null || userData.isExpired())
return Collections.<String>emptySet();
// Return all available connection identifiers
return connections.keySet();
}
/**
* Returns a Directory containing all connections accessible by the user
* whose data is given by the provided UserData object. If the given
* UserData object is not expired, this Directory will contain absolutely
* all connections defined within the given UserData. If the given UserData
* object is expired, this Directory will be empty.
*
* @param userData
* All data associated with the user whose connection directory is
* being retrieved.
*
* @return
* A Directory containing all connections accessible by the user whose
* data is given by the provided UserData object.
*/
public Directory<Connection> getConnectionDirectory(UserData userData) {
// Do not return any connections if empty or expired
Map<String, UserData.Connection> connections = userData.getConnections();
if (connections == null || userData.isExpired())
return new SimpleDirectory<>();
// Convert UserData.Connection objects to normal Connections
Map<String, Connection> directoryContents = new HashMap<>();
for (Map.Entry<String, UserData.Connection> entry : connections.entrySet()) {
// Pull connection and associated identifier
String identifier = entry.getKey();
UserData.Connection connection = entry.getValue();
// Create Guacamole connection containing the defined identifier
// and parameters
Connection guacConnection = userDataConnectionProvider.get().init(
userData,
identifier,
connection
);
// Add corresponding Connection to directory
directoryContents.put(identifier, guacConnection);
}
return new SimpleDirectory<>(directoryContents);
}
/**
* Returns the identifiers of all connection groups readable by the user
* whose data is given by the provided UserData object. This will always be
* a set containing only the root connection group identifier. The
* JSONAuthenticationProvider does not define any other connection groups.
*
* @param userData
* All data associated with the user whose accessible connection group
* identifiers are being retrieved.
*
* @return
* A set containing the identifiers of all connection groups readable
* by the user whose data is given by the provided UserData object.
*/
public Set<String> getConnectionGroupIdentifiers(UserData userData) {
// The only connection group available is the root group
return Collections.singleton(UserContext.ROOT_CONNECTION_GROUP);
}
}

View File

@@ -0,0 +1,16 @@
{
"guacamoleVersion" : "1.3.0",
"name" : "Encrypted JSON Authentication",
"namespace" : "guac-json",
"authProviders" : [
"org.apache.guacamole.auth.json.JSONAuthenticationProvider"
],
"translations" : [
"translations/en.json"
]
}

View File

@@ -0,0 +1,7 @@
{
"DATA_SOURCE_JSON" : {
"NAME" : "JSON"
}
}