You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/02/05 18:04:36 UTC
[18/21] guacamole-client git commit: GUACAMOLE-96: Add configuration
parameters for details of TOTP generation.
GUACAMOLE-96: Add configuration parameters for details of TOTP generation.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/a422fdf9
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/a422fdf9
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/a422fdf9
Branch: refs/heads/master
Commit: a422fdf9c235e898d5c05499cef638501beb6508
Parents: 170a11b
Author: Michael Jumper <mj...@apache.org>
Authored: Mon Nov 20 14:29:03 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Sun Feb 4 19:45:18 2018 -0800
----------------------------------------------------------------------
.../totp/TOTPAuthenticationProviderModule.java | 2 +
.../auth/totp/UserVerificationService.java | 33 +++-
.../auth/totp/conf/ConfigurationService.java | 161 +++++++++++++++++++
.../auth/totp/conf/TOTPModeProperty.java | 62 +++++++
.../auth/totp/form/AuthenticationCodeField.java | 42 ++---
5 files changed, 274 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a422fdf9/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/TOTPAuthenticationProviderModule.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/TOTPAuthenticationProviderModule.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/TOTPAuthenticationProviderModule.java
index 757a412..e72beec 100644
--- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/TOTPAuthenticationProviderModule.java
+++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/TOTPAuthenticationProviderModule.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.totp;
import com.google.inject.AbstractModule;
import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.auth.totp.conf.ConfigurationService;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.auth.AuthenticationProvider;
@@ -71,6 +72,7 @@ public class TOTPAuthenticationProviderModule extends AbstractModule {
bind(Environment.class).toInstance(environment);
// Bind TOTP-specific services
+ bind(ConfigurationService.class);
bind(UserVerificationService.class);
}
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a422fdf9/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java
index a44b6ee..987d4ca 100644
--- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java
+++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java
@@ -20,6 +20,8 @@
package org.apache.guacamole.auth.totp;
import com.google.common.io.BaseEncoding;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
import java.security.InvalidKeyException;
import java.util.Collections;
import java.util.HashMap;
@@ -28,6 +30,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleUnsupportedException;
+import org.apache.guacamole.auth.totp.conf.ConfigurationService;
import org.apache.guacamole.auth.totp.form.AuthenticationCodeField;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.net.auth.AuthenticatedUser;
@@ -67,6 +70,18 @@ public class UserVerificationService {
private static final BaseEncoding BASE32 = BaseEncoding.base32();
/**
+ * Service for retrieving configuration information.
+ */
+ @Inject
+ private ConfigurationService confService;
+
+ /**
+ * Provider for AuthenticationCodeField instances.
+ */
+ @Inject
+ private Provider<AuthenticationCodeField> codeFieldProvider;
+
+ /**
* Retrieves and decodes the base32-encoded TOTP key associated with user
* having the given UserContext. If no TOTP key is associated with the user,
* a random key is generated and associated with the user. If the extension
@@ -100,7 +115,8 @@ public class UserVerificationService {
if (secret == null) {
// Generate random key for user
- UserTOTPKey generated = new UserTOTPKey(username, TOTPGenerator.Mode.SHA1.getRecommendedKeyLength());
+ TOTPGenerator.Mode mode = confService.getMode();
+ UserTOTPKey generated = new UserTOTPKey(username,mode.getRecommendedKeyLength());
if (setKey(context, generated))
return generated;
@@ -223,25 +239,32 @@ public class UserVerificationService {
// If no TOTP provided, request one
if (code == null) {
+ AuthenticationCodeField field = codeFieldProvider.get();
+
// If the user hasn't completed enrollment, request that they do
- if (!key.isConfirmed())
+ if (!key.isConfirmed()) {
+ field.exposeKey(key);
throw new GuacamoleInsufficientCredentialsException(
"LOGIN.INFO_TOTP_REQUIRED", new CredentialsInfo(
- Collections.<Field>singletonList(new AuthenticationCodeField(key))
+ Collections.<Field>singletonList(field)
));
+ }
// Otherwise simply request the user's authentication code
throw new GuacamoleInsufficientCredentialsException(
"LOGIN.INFO_TOTP_REQUIRED", new CredentialsInfo(
- Collections.<Field>singletonList(new AuthenticationCodeField())
+ Collections.<Field>singletonList(field)
));
}
try {
+ // Get generator based on user's key and provided configuration
+ TOTPGenerator totp = new TOTPGenerator(key.getSecret(),
+ confService.getMode(), confService.getDigits());
+
// Verify provided TOTP against value produced by generator
- TOTPGenerator totp = new TOTPGenerator(key.getSecret(), TOTPGenerator.Mode.SHA1, 6);
if (code.equals(totp.generate()) || code.equals(totp.previous())) {
// Record key as confirmed, if it hasn't already been so recorded
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a422fdf9/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java
new file mode 100644
index 0000000..8658849
--- /dev/null
+++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java
@@ -0,0 +1,161 @@
+/*
+ * 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.totp.conf;
+
+import com.google.inject.Inject;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleServerException;
+import org.apache.guacamole.environment.Environment;
+import org.apache.guacamole.properties.IntegerGuacamoleProperty;
+import org.apache.guacamole.properties.StringGuacamoleProperty;
+import org.apache.guacamole.totp.TOTPGenerator;
+
+/**
+ * Service for retrieving configuration information regarding the TOTP
+ * authentication extension.
+ */
+public class ConfigurationService {
+
+ /**
+ * The Guacamole server environment.
+ */
+ @Inject
+ private Environment environment;
+
+ /**
+ * The human-readable name of the entity issuing user accounts. By default,
+ * this will be "Apache Guacamole".
+ */
+ private static final StringGuacamoleProperty TOTP_ISSUER =
+ new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "totp-issuer"; }
+
+ };
+
+ /**
+ * The number of digits which should be included in each generated TOTP
+ * code. By default, this will be 6.
+ */
+ private static final IntegerGuacamoleProperty TOTP_DIGITS=
+ new IntegerGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "totp-digits"; }
+
+ };
+
+ /**
+ * The duration that each generated code should remain valid, in seconds.
+ * By default, this will be 30.
+ */
+ private static final IntegerGuacamoleProperty TOTP_PERIOD =
+ new IntegerGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "totp-period"; }
+
+ };
+
+ /**
+ * The hash algorithm that should be used to generate TOTP codes. By
+ * default, this will be "sha1". Legal values are "sha1", "sha256", and
+ * "sha512".
+ */
+ private static final TOTPModeProperty TOTP_MODE =
+ new TOTPModeProperty() {
+
+ @Override
+ public String getName() { return "totp-mode"; }
+
+ };
+
+ /**
+ * Returns the human-readable name of the entity issuing user accounts. If
+ * not specified, "Apache Guacamole" will be used by default.
+ *
+ * @return
+ * The human-readable name of the entity issuing user accounts.
+ *
+ * @throws GuacamoleException
+ * If the "totp-issuer" property cannot be read from
+ * guacamole.properties.
+ */
+ public String getIssuer() throws GuacamoleException {
+ return environment.getProperty(TOTP_ISSUER, "Apache Guacamole");
+ }
+
+ /**
+ * Returns the number of digits which should be included in each generated
+ * TOTP code. If not specified, 6 will be used by default.
+ *
+ * @return
+ * The number of digits which should be included in each generated
+ * TOTP code.
+ *
+ * @throws GuacamoleException
+ * If the "totp-digits" property cannot be read from
+ * guacamole.properties.
+ */
+ public int getDigits() throws GuacamoleException {
+
+ // Validate legal number of digits
+ int digits = environment.getProperty(TOTP_DIGITS, 6);
+ if (digits < 6 || digits > 8)
+ throw new GuacamoleServerException("TOTP codes may have no fewer "
+ + "than 6 digits and no more than 8 digits.");
+
+ return digits;
+
+ }
+
+ /**
+ * Returns the duration that each generated code should remain valid, in
+ * seconds. If not specified, 30 will be used by default.
+ *
+ * @return
+ * The duration that each generated code should remain valid, in
+ * seconds.
+ *
+ * @throws GuacamoleException
+ * If the "totp-period" property cannot be read from
+ * guacamole.properties.
+ */
+ public int getPeriod() throws GuacamoleException {
+ return environment.getProperty(TOTP_PERIOD, 30);
+ }
+
+ /**
+ * Returns the hash algorithm that should be used to generate TOTP codes. If
+ * not specified, SHA1 will be used by default.
+ *
+ * @return
+ * The hash algorithm that should be used to generate TOTP codes.
+ *
+ * @throws GuacamoleException
+ * If the "totp-mode" property cannot be read from
+ * guacamole.properties.
+ */
+ public TOTPGenerator.Mode getMode() throws GuacamoleException {
+ return environment.getProperty(TOTP_MODE, TOTPGenerator.Mode.SHA1);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a422fdf9/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/TOTPModeProperty.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/TOTPModeProperty.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/TOTPModeProperty.java
new file mode 100644
index 0000000..bfe3ef3
--- /dev/null
+++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/TOTPModeProperty.java
@@ -0,0 +1,62 @@
+/*
+ * 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.totp.conf;
+
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleServerException;
+import org.apache.guacamole.properties.GuacamoleProperty;
+import org.apache.guacamole.totp.TOTPGenerator;
+
+/**
+ * A GuacamoleProperty whose value is a TOTP generation method. The string
+ * values "sha1", "sha256", and "sha512" are each parsed to their corresponding
+ * values within the TOTPGenerator.Mode enum. All other string values result in
+ * parse errors.
+ */
+public abstract class TOTPModeProperty
+ implements GuacamoleProperty<TOTPGenerator.Mode> {
+
+ @Override
+ public TOTPGenerator.Mode parseValue(String value)
+ throws GuacamoleException {
+
+ // If no value provided, return null.
+ if (value == null)
+ return null;
+
+ // SHA1
+ if (value.equals("sha1"))
+ return TOTPGenerator.Mode.SHA1;
+
+ // SHA256
+ if (value.equals("sha256"))
+ return TOTPGenerator.Mode.SHA256;
+
+ // SHA512
+ if (value.equals("sha512"))
+ return TOTPGenerator.Mode.SHA512;
+
+ // The provided value is not legal
+ throw new GuacamoleServerException("TOTP mode must be one of "
+ + "\"sha1\", \"sha256\", or \"sha512\".");
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a422fdf9/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/form/AuthenticationCodeField.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/form/AuthenticationCodeField.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/form/AuthenticationCodeField.java
index 1be5f27..e0333dd 100644
--- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/form/AuthenticationCodeField.java
+++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/form/AuthenticationCodeField.java
@@ -20,6 +20,7 @@
package org.apache.guacamole.auth.totp.form;
import com.google.common.io.BaseEncoding;
+import com.google.inject.Inject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
@@ -32,6 +33,7 @@ import javax.ws.rs.core.UriBuilder;
import javax.xml.bind.DatatypeConverter;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.totp.UserTOTPKey;
+import org.apache.guacamole.auth.totp.conf.ConfigurationService;
import org.apache.guacamole.form.Field;
import org.codehaus.jackson.annotate.JsonProperty;
@@ -67,30 +69,33 @@ public class AuthenticationCodeField extends Field {
private static final BaseEncoding BASE32 = BaseEncoding.base32();
/**
+ * Service for retrieving configuration information.
+ */
+ @Inject
+ private ConfigurationService confService;
+
+ /**
* The TOTP key to expose to the user for the sake of enrollment, if any.
* If no such key should be exposed to the user, this will be null.
*/
- private final UserTOTPKey key;
+ private UserTOTPKey key;
/**
* Creates a new field which prompts the user for an authentication code
- * generated via TOTP, and provide the user with their TOTP key to
- * facilitate enrollment.
- *
- * @param key
- * The TOTP key to expose to the user for the sake of enrollment.
+ * generated via TOTP. The user's TOTP key is not exposed for enrollment.
*/
- public AuthenticationCodeField(UserTOTPKey key) {
+ public AuthenticationCodeField() {
super(PARAMETER_NAME, FIELD_TYPE_NAME);
- this.key = key;
}
/**
- * Creates a new field which prompts the user for an authentication code
- * generated via TOTP. The user's TOTP key is not exposed for enrollment.
+ * Exposes the given key to facilitate enrollment.
+ *
+ * @param key
+ * The TOTP key to expose to the user for the sake of enrollment.
*/
- public AuthenticationCodeField() {
- this(null);
+ public void exposeKey(UserTOTPKey key) {
+ this.key = key;
}
/**
@@ -114,20 +119,15 @@ public class AuthenticationCodeField extends Field {
if (key == null)
return null;
- // FIXME: Pull from configuration
- String issuer = "Some Issuer";
- String algorithm = "SHA1";
- String digits = "6";
- String period = "30";
-
// Format "otpauth" URL (see https://github.com/google/google-authenticator/wiki/Key-Uri-Format)
+ String issuer = confService.getIssuer();
return UriBuilder.fromUri("otpauth://totp/")
.path(issuer + ":" + key.getUsername())
.queryParam("secret", BASE32.encode(key.getSecret()))
.queryParam("issuer", issuer)
- .queryParam("algorithm", algorithm)
- .queryParam("digits", digits)
- .queryParam("period", period)
+ .queryParam("algorithm", confService.getMode())
+ .queryParam("digits", confService.getDigits())
+ .queryParam("period", confService.getPeriod())
.build();
}