001/*
002 * Copyright (c) 2013 - 2016 TDP Ltd All Rights Reserved.
003 * TDP Ltd grants permission, free of charge, to any person obtaining copies
004 * of this software and its associated documentation files (the "Software"),
005 * to deal in the Software without restriction, including to use, copy, adapt,
006 * publish, distribute, display, perform, sublicense, and sell copies of the
007 * Software, subject to the following condition: You must include the above
008 * copyright notice and this permission notice in all full or partial copies
009 * of the Software.
010 * TDP LTD PROVIDES THE SOFTWARE "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY,
011 * INCLUDING WITHOUT THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
012 * PARTICULAR PURPOSE, AND NON-INFRINGMENT. TDP LTD, THE AUTHORS OF THE SOFTWARE,
013 * AND THE OWNERS OF COPYRIGHT IN THE SOFTWARE ARE NOT LIABLE FOR ANY CLAIM, DAMAGES,
014 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING
015 * FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
016 * THE SOFTWARE.
017 */
018package cz.tdp.kshield.client;
019
020import java.io.Serializable;
021import java.util.Collections;
022import java.util.EnumSet;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029
030
031/**
032 * This class contains user data retrieved from the KeyShield SSO Server
033 * @see cz.tdp.kshield.client.KShieldClient
034 */
035public class UserInfo implements Serializable
036{
037  private static final long serialVersionUID = 8935842552519353975L;
038  
039  static final String GUID_ATTRIBUTE = "x-guid";
040  
041  private String usernameAttribute;
042  
043  private String userID;
044  private String connectorID;
045  private String screenName;
046  private String ipAddress;
047  private AuthType authType;
048  private String authMethod;
049  private String client;
050  private boolean hwTokenPresent;
051  private boolean hwTokenEnabled;
052  private boolean hwSwitching;
053  
054  private boolean manual;
055  
056  private final ClientInfo clientInfo = new ClientInfo();
057  private Map<String,List<String>> attributes = Collections.emptyMap();
058  
059  /**
060   * @return the authenticated user username or null if no user is authenticated.
061   * If user ID attribute is defined, then return this attribute value, otherwise return screenName
062   */
063  public String getUsername() {
064    if (usernameAttribute != null && usernameAttribute.length() > 0) {
065      return usernameFromAttribute();
066    }
067    
068    return screenName;
069  }
070  
071  public String getGUID() {
072    return guidFromAttribute();
073  }
074  
075  /**
076   * @return the screenname/username part from the user ID or null if no user is authenticated
077   */
078  public String getScreenName() {
079    return screenName;
080  }
081  
082  void setScreenName(String screenName) {
083    this.screenName = screenName;
084  }
085  
086  /**
087   * @return KeyShield SSO Server user ID / FDN or null if no user is authenticated
088   * For eDirectory it's LDAP FDN and for AD/domain it's domain://DOMAINNAME&#92username.
089   */
090  public String getUserID() {
091    return userID;
092  }
093  
094  
095  void setUserID(String fdn) {
096    this.userID = fdn;
097  }
098  
099  /**
100   * @return KeyShield SSO Server authentication type.
101   * See {@link AuthType} for more info.
102   */
103  public AuthType getAuthType() {
104    return authType;
105  }
106  
107  void setAuthType(AuthType authType) {
108    this.authType = authType;
109  }
110  
111  
112  /**
113   * @return the SSO connector ID
114   */
115  public String getConnectorID() {
116    return connectorID;
117  }
118  
119  void setConnectorID(String connectorID) {
120    this.connectorID = connectorID;
121  }
122  
123  /**
124   * @return the IP address of originating request
125   */
126  public String getIpAddress() {
127    return ipAddress;
128  }
129  
130  
131  void setIpAddress(String ipAddress) {
132    this.ipAddress = ipAddress;
133  }
134  
135  
136  /**
137   * @return true if manual authentication method was used
138   * @deprecated use authType instead
139   */
140  @Deprecated
141  public boolean isManual() {
142    return manual;
143  }
144  
145  /**
146   * @deprecated use authType instead
147   */
148  @Deprecated
149  void setManual(boolean manual) {
150    this.manual = manual;
151  }
152  
153  /**
154   * @return the actual used Authentication method
155   */
156  public String getAuthMethod() {
157    return this.authMethod;
158  }
159  
160  void setAuthMethod(String authMethod) {
161    this.authMethod = authMethod;
162  }
163  
164  /**
165   * @return the client type or null
166   */
167  public String getClient() {
168    return this.client;
169  }
170  
171  void setClient(String client) {
172    this.client = client;
173  }
174  
175  /**
176   * @return true if HW token is present
177   */
178  public boolean isHwTokenPresent() {
179    return this.hwTokenPresent;
180  }
181  
182  void setHwTokenPresent(boolean hwTokenPresent) {
183    this.hwTokenPresent = hwTokenPresent;
184  }
185  
186  /**
187   * @return true if HW token is enabled
188   */
189  public boolean isHwTokenEnabled() {
190    return this.hwTokenEnabled;
191  }
192
193  void setHwTokenEnabled(boolean hwTokenEnabled) {
194    this.hwTokenEnabled = hwTokenEnabled;
195  }
196
197  /**
198   * @return true if user switching is enabled
199   */
200  public boolean isHwSwitching() {
201    return this.hwSwitching;
202  }
203
204  void setHwSwitching(boolean hwSwitching) {
205    this.hwSwitching = hwSwitching;
206  }
207
208  /**
209   * @return additional user attributes retrieved from KeyShield SSO Server
210   * Map contains only attributes with at leas one value
211   */
212  public Map<String,List<String>> getAttributes() {
213    return attributes;
214  }
215  
216  /**
217   * @param attributeName
218   * @return non-null list of values for given attribute name
219   */
220  public List<String> getAttributeValues(String attributeName) {
221    final List<String> values = attributes.get(attributeName.toLowerCase());
222    
223    if (values == null) {
224      return Collections.emptyList();
225    }
226    return values;
227  }
228  
229  /**
230   * @param attributeName
231   * @return first attribute value or null if value doesnt exists
232   */
233  public String getAttributeValue(String attributeName) {
234    final List<String> values = attributes.get(attributeName.toLowerCase());
235    
236    if (values != null && !values.isEmpty()) {
237      return values.get(0);
238    }
239    
240    return null;
241  }
242  
243  void setAttributes(Map<String,List<String>> attributes) {
244    this.attributes = attributes;
245  }
246  
247  public ClientInfo getClientInfo() {
248    return this.clientInfo;
249  }
250
251  /**
252   * @return name of username attribute
253   */
254  public String getUsernameAttribute() {
255    return usernameAttribute;
256  }
257  
258  /**
259   * Set name of username attribute, if null screenName is used as username
260   */
261  public void setUsernameAttribute(String usernameAttribute) {
262    this.usernameAttribute = usernameAttribute;
263  }
264  
265  @Override
266  public String toString() {
267    return userID;
268  }
269  
270  private String usernameFromAttribute() {
271    final List<String> values = attributes.get(usernameAttribute.toLowerCase());
272    
273    if (values != null && !values.isEmpty()) {
274      if (values.size() > 1) {
275        log.warn("Multiple values for usernameAttribute: " + usernameAttribute.toLowerCase() + " = " + values);
276      }
277      
278      return values.get(0);
279    }
280    
281    log.warn("Cannot retrieve valid username attribute, returned attribute values: " + usernameAttribute.toLowerCase() + " = " + values);
282    
283    return null;
284  }
285  
286  private String guidFromAttribute() {
287    final List<String> values = attributes.get(GUID_ATTRIBUTE);
288    
289    if (values != null && !values.isEmpty()) {
290      if (values.size() > 1) {
291        log.warn("Multiple values for GUID: " + GUID_ATTRIBUTE + " = " + values);
292      }
293      
294      return values.get(0);
295    }
296    
297    log.warn("Cannot retrieve valid GUID attribute, returned attribute values: " + GUID_ATTRIBUTE + " = " + values);
298    
299    return null;
300  }
301  
302  private static final Log log = LogFactory.getLog(UserInfo.class);
303  
304  public static final EnumSet<AuthType> DEFAULT_ALLOWED_AUTH_TYPES = EnumSet.complementOf(EnumSet.of(AuthType.UID, AuthType.NOT_AUTHENTICATED));
305  
306  /**
307   * Supported authentication types returned by KeyShield SSO Server
308   */
309  public enum AuthType
310  {
311    /**
312     * user is not authenticated
313     */
314    NOT_AUTHENTICATED(null),
315    
316    /**
317     * user authenticated by UID.
318     */
319    UID("U"),
320    
321    /**
322     * User authenticated using eDirectory method (User ID contains LDAP FDN e.g cn=user1,o=org).
323     */
324    EDIRECTORY("E"),
325    
326    /**
327     * User authenticated using AD domain method (User ID contains domain://domainname&#92username ).
328     */
329    ACTIVEDIRECTORY("A"),
330    
331    /**
332     * Only for backward compatibility
333     * @deprecated Use type MANUAL instead
334     */
335    @Deprecated LDAP("L"),
336    
337    /**
338     * Manual authentication method - not used in KeyShield SSO Server 1.3, since manual users are verified using LDAP
339     * and User ID contains LDAP FDN. - use isManual()
340     */
341    MANUAL("M");
342    
343    private final String code;
344    
345    AuthType(String code) {
346      this.code = code;
347    }
348    
349    /**
350     * @param code
351     * @return AuthType based on code value, for unknown code returns NOT_AUTHENTICATED
352     */
353    public static AuthType fromCode(String code) {
354      final AuthType val = CODE_TO_AUTH_TYPE_MAP.get(code);
355      if (val != null) {
356        return val;
357      }
358      
359      return NOT_AUTHENTICATED;
360    }
361    
362    /**
363     * @return auth type code
364     */
365    public String code() {
366      return code;
367    }
368    
369    private static final Map<String,AuthType> CODE_TO_AUTH_TYPE_MAP = new HashMap<>();
370    
371    static {
372      for (AuthType val : values()) {
373        if (val.code != null) {
374          CODE_TO_AUTH_TYPE_MAP.put(val.code, val);
375        }
376      }
377    }
378  }
379  
380  public static class ClientInfo
381  {
382    private String clientVersion;
383    private String clientOS;
384    private String clientOSVersion;
385    private String clientHostname;
386    private String stationKey;
387    
388    /**
389     * @return kshield client version
390     */
391    public String getClientVersion() {
392      return this.clientVersion;
393    }
394    
395    void setClientVersion(String clientVersion) {
396      this.clientVersion = clientVersion;
397    }
398    
399    /**
400     * @return client OS name
401     */
402    public String getClientOS() {
403      return this.clientOS;
404    }
405    
406    void setClientOS(String clientOS) {
407      this.clientOS = clientOS;
408    }
409    
410    /**
411     * @return client OS version
412     */
413    public String getClientOSVersion() {
414      return this.clientOSVersion;
415    }
416    
417    void setClientOSVersion(String clientOSVersion) {
418      this.clientOSVersion = clientOSVersion;
419    }
420    
421    /**
422     * @return client hostname
423     */
424    public String getClientHostname() {
425      return this.clientHostname;
426    }
427    
428    void setClientHostname(String clientHostname) {
429      this.clientHostname = clientHostname;
430    }
431    
432    /**
433     * @return station key (usually same as hostname)
434     */
435    public String getStationKey() {
436      if (this.stationKey != null) {
437        return this.stationKey;
438      }
439      
440      return this.clientHostname;
441    }
442    
443    void setStationKey(String stationKey) {
444      this.stationKey = stationKey;
445    }
446  }
447}