You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@guacamole.apache.org by GitBox <gi...@apache.org> on 2022/06/21 15:50:06 UTC

[GitHub] [guacamole-client] mike-jumper commented on a diff in pull request #736: GUACAMOLE-1623: Extract domain field directly from the vault, or split out of username.

mike-jumper commented on code in PR #736:
URL: https://github.com/apache/guacamole-client/pull/736#discussion_r902780723


##########
extensions/guacamole-vault/modules/guacamole-vault-base/src/test/java/org/apache/guacamole/vault/util/FieldParsingUtilTest.java:
##########
@@ -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.vault.util;
+
+import org.apache.guacamole.vault.util.FieldParsingUtil.DomainAndUsername;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+/**
+ * Class to test methods in the QCParser utility class.
+ */
+public class FieldParsingUtilTest {
+
+    /**
+     * Verify that the splitWindowsUsernameFromDomain() method correctly strips Windows
+     * domains from provided usernames that include them, and does not modify
+     * usernames that do not have Windows domains.
+     */
+    @Test
+    public void testSplitWindowsUsernameFromDomain() {
+
+        DomainAndUsername usernameAndDomain;
+
+        // If no Windows domain is present in the provided field, the username should
+        // contain the entire field, and no domain should be returned
+        usernameAndDomain = FieldParsingUtil.splitWindowsUsernameFromDomain("bob");
+        assertEquals(usernameAndDomain.getUsername(), "bob");
+        assertFalse(usernameAndDomain.hasDomain());
+
+        // It should parse down-level logon name style domains
+        usernameAndDomain = FieldParsingUtil.splitWindowsUsernameFromDomain("localhost\\bob");
+        assertEquals("bob", usernameAndDomain.getUsername(), "bob");
+        assertTrue(usernameAndDomain.hasDomain());
+        assertEquals("localhost", usernameAndDomain.getDomain());
+
+        // It should parse user principal name style domains
+        usernameAndDomain = FieldParsingUtil.splitWindowsUsernameFromDomain("bob@localhost");
+        assertEquals("bob", usernameAndDomain.getUsername(), "bob");
+        assertTrue(usernameAndDomain.hasDomain());
+        assertEquals("localhost", usernameAndDomain.getDomain());
+
+        // It should not match if there are an invalid number of seperators
+        List<String> invalidSeperators = List.of(

Review Comment:
   separator*



##########
extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/util/FieldParsingUtil.java:
##########
@@ -0,0 +1,163 @@
+/*
+ * 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.vault.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * A set of utility methods for parsing field values for records retrieved
+ * from vaults.
+ */
+public class FieldParsingUtil {
+
+    /**
+     * A pattern for matching a down-level logon name containing a Windows
+     * domain and username - e.g. domain\\user. For more information, see
+     * https://docs.microsoft.com/en-us/windows/win32/secauthn/user-name-formats#down-level-logon-name
+     */
+    private static final Pattern DOWN_LEVEL_LOGON_NAME_PATTERN = Pattern.compile(
+            "(?<domain>[^@\\\\]+)\\\\(?<username>[^@\\\\]+)");
+
+    /**
+     * A pattern for matching a user principal name containing a Windows
+     * domain and username - e.g. user@domain. For more information, see
+     * https://docs.microsoft.com/en-us/windows/win32/secauthn/user-name-formats#user-principal-name
+     */
+    private static final  Pattern USER_PRINCIPAL_NAME_PATTERN = Pattern.compile(
+            "(?<username>[^@\\\\]+)@(?<domain>[^@\\\\]+)");
+
+    /**
+     * A class representating the result of attempting to split a username from
+     * a vault into a Windows domain and username. The username field will always
+     * be set, but if no domain was extracted, the domain field will be null.
+     */
+    public static class DomainAndUsername {
+
+        /**
+         * The username associated with the potential Windows domain/username
+         * value. If no domain is found, the username field will contain the
+         * entire value as read from the vault.
+         */
+        private final String username;
+
+        /**
+         * The dinaun associated with the potential Windows domain/username
+         * value. If no domain is found, this will be null.
+         */
+        private final String domain;
+
+        /**
+         * Create a DomainAndUsername record with no associated domain.
+         *
+         * @param username
+         *     The username, which should be the entire value as extracted
+         *     from the vault.
+         */
+        private DomainAndUsername(@NonNull String username) {
+            this.username = username;
+            this.domain = null;
+        }
+
+        /**
+         * Create a DomainAndUsername record with a username and a domain.
+         *
+         * @param username
+         *     The username portion of the field value from the vault.
+         *
+         * @param domain
+         *     The domain portion of the field value from the vault.
+         */
+        private DomainAndUsername(
+                @NonNull String username, @NonNull String domain) {
+            this.username = username;
+            this.domain = domain;
+        }
+
+        /**
+         * Return the value of the username as extracted from the vault field.
+         * If the domain is null, this will be the entire field value.
+         *
+         * @return
+         *     The username value as extracted from the vault field.
+         */
+        public String getUsername() {
+            return username;
+        }
+
+        /**
+         * Return the value of the domain as extracted from the vault field.
+         * If this is null, it means that no domain was found in the vault field.
+         *
+         * @return
+         *     The domain value as extracted from the vault field.
+         */
+        public String getDomain() {
+            return domain;
+        }
+
+        /**
+         * Return true if a domain was found in the vault field, false otherwise.
+         *
+         * @return
+         */
+        public boolean hasDomain() {
+            return this.domain != null;
+        }
+
+    }
+
+    /**
+     * Strip off a Windows domain from the provided username, if one is
+     * present. For example: "DOMAIN\\user" or "user@DOMAIN" will both
+     * be stripped to just "user". Note: neither the '@' or '\\' characters
+     * are valid in Windows usernames.
+     *
+     * @param vaultField
+     *     The raw field value as retrieved from the vault. This might contain
+     *     a Windows domain.
+     *
+     * @return
+     *     The provided username with the Windows domain stripped off, if one
+     *     is present.
+     */
+    public static DomainAndUsername splitWindowsUsernameFromDomain(String vaultField) {
+
+        // If it's the down-level logon format, return the extracted username and domain
+        Matcher downLevelLogonMatcher = DOWN_LEVEL_LOGON_NAME_PATTERN.matcher(vaultField);
+        if (downLevelLogonMatcher.matches())
+            return new DomainAndUsername(
+                    downLevelLogonMatcher.group("username"),
+                    downLevelLogonMatcher.group("domain"));
+
+        // If it's the user principal format, return the extracted username and domain
+        Matcher userPrincipalMatcher = USER_PRINCIPAL_NAME_PATTERN.matcher(vaultField);
+        if (userPrincipalMatcher.matches())
+            return new DomainAndUsername(
+                    userPrincipalMatcher.group("username"),
+                    userPrincipalMatcher.group("domain"));
+
+        // If none of the expected formats matched, return the username with do domain
+        return new DomainAndUsername(vaultField);
+
+    }

Review Comment:
   Rather than establish a general parsing utility class for all future parsing needs, I suggest instead just defining `DomainAndUsername` and let it do-one-thing-and-do-it-well. ie:
   
   `DomainAndUsername.split(someFieldValue)`
   
   rather than:
   
   `FieldParsingUtil.DomainAndUsername` and `FieldParsingUtil.splitWindowsUsernameFromDomain(someFieldValue)`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@guacamole.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org