001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.security.twofactor;
029
030import org.opencms.security.twofactor.CmsTwoFactorAuthenticationUserPolicy.CheckType;
031
032import java.util.List;
033import java.util.stream.Collectors;
034
035import org.dom4j.Element;
036
037/**
038 * Represents the configuration for the two-factor authentication feature.
039 */
040public class CmsTwoFactorAuthenticationConfig {
041
042    /** The original XML element from which the configuration was read. */
043    private Element m_element;
044
045    /** True if two-factor authentication should be enabled. */
046    private boolean m_enabled;
047
048    /** The issuer (displayed by authenticator apps). */
049    private String m_issuer;
050
051    /** The policy that controls which users should use two-factor authentication. */
052    private CmsTwoFactorAuthenticationUserPolicy m_policy;
053
054    /** The secret key used to encrypt/decrypt the two-factor authentication data for users. */
055    private String m_secret;
056
057    /** The setup message. */
058    private String m_setupMessage;
059
060    /**
061     * Creates a new configuration from the given XML configuration element.
062     *
063     * @param element the element from which to read the configuration
064     */
065    public CmsTwoFactorAuthenticationConfig(Element element) {
066
067        m_element = element;
068        Element issuerElem = (Element)(element.selectSingleNode("issuer"));
069        m_issuer = issuerElem.getTextTrim();
070        m_enabled = Boolean.parseBoolean(((Element)element.selectSingleNode("enabled")).getTextTrim());
071        m_secret = ((Element)element.selectSingleNode("secret")).getTextTrim();
072        m_policy = parsePolicy(element);
073        Element messageElem = (Element)(element.selectSingleNode("setup-message"));
074        if (messageElem != null) {
075            m_setupMessage = messageElem.getText();
076        }
077
078    }
079
080    /**
081     * Gets the configuration element.
082     *
083     * @return the configuration element
084     */
085    public Element getConfigElement() {
086
087        return m_element;
088    }
089
090    /**
091     * Gets the issuer (encoded in generated QR codes and displayed by authenticator apps).
092     *
093     * @return the issuer
094     */
095    public String getIssuer() {
096
097        return m_issuer;
098    }
099
100    /**
101     * Gets the policy which controls which users should use two-factor authentication.
102     *
103     * @return the user policy
104     */
105    public CmsTwoFactorAuthenticationUserPolicy getPolicy() {
106
107        return m_policy;
108    }
109
110    /**
111     * Gets the secret key which is used to encrypt/decrypt two-factor authentication information stored in the user's additional infos.
112     *
113     * @return the secret key
114     */
115    public String getSecret() {
116
117        return m_secret;
118    }
119
120    /**
121     * Gets the setup message.
122     *
123     * @return the setup message
124     */
125    public String getSetupMessage() {
126
127        return m_setupMessage;
128
129    }
130
131    /**
132     * Checks if two-factor authentication is enabled.
133     *
134     * <p>If it is disabled, users can just log in with user name and password.
135     *
136     * @return true if 2FA is enabled
137     */
138    public boolean isEnabled() {
139
140        return m_enabled;
141    }
142
143    /**
144     * Parses a user policy from the configuration element.
145     *
146     * @param parent the parent XML element
147     * @return the user policy
148     */
149    private CmsTwoFactorAuthenticationUserPolicy parsePolicy(Element parent) {
150
151        List<CmsTwoFactorAuthenticationUserPolicy.Rule> includes = parsePolicyRules(parent, "include-users/*");
152        List<CmsTwoFactorAuthenticationUserPolicy.Rule> excludes = parsePolicyRules(parent, "exclude-users/*");
153        return new CmsTwoFactorAuthenticationUserPolicy(includes, excludes);
154
155    }
156
157    /**
158     * Parses a list of policy rules from the given XML element.
159     *
160     * @param parent the parent XML element
161     * @param xpath the xpath used to locate the rules
162     * @return the parsed rules
163     */
164    private List<CmsTwoFactorAuthenticationUserPolicy.Rule> parsePolicyRules(Element parent, String xpath) {
165
166        return parent.selectNodes(xpath).stream().map(node -> {
167            Element elem = (Element)node;
168            CheckType type = CheckType.valueOf(elem.getName());
169            String name = elem.getTextTrim();
170            return new CmsTwoFactorAuthenticationUserPolicy.Rule(type, name);
171        }).collect(Collectors.toList());
172
173    }
174
175}