View Javadoc
1   /**
2    * Waffle (https://github.com/dblock/waffle)
3    *
4    * Copyright (c) 2010 - 2015 Application Security, Inc.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Eclipse Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/epl-v10.html
10   *
11   * Contributors:
12   *     Application Security, Inc.
13   */
14  package waffle.servlet;
15  
16  import java.io.Serializable;
17  import java.security.Principal;
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  import com.google.common.base.Joiner;
24  
25  import waffle.windows.auth.IWindowsAccount;
26  import waffle.windows.auth.IWindowsIdentity;
27  import waffle.windows.auth.PrincipalFormat;
28  import waffle.windows.auth.WindowsAccount;
29  
30  /**
31   * A Windows Principal.
32   * 
33   * @author dblock[at]dblock[dot]org
34   */
35  public class WindowsPrincipal implements Principal, Serializable {
36  
37      /** The Constant serialVersionUID. */
38      private static final long           serialVersionUID = 1L;
39      
40      /** The fqn. */
41      private final String                      fqn;
42      
43      /** The sid. */
44      private final byte[]                      sid;
45      
46      /** The sid string. */
47      private final String                      sidString;
48      
49      /** The roles. */
50      private final List<String>                roles;
51      
52      /** The identity. */
53      private transient IWindowsIdentity  identity;
54      
55      /** The groups. */
56      private final Map<String, WindowsAccount> groups;
57  
58      /**
59       * A windows principal.
60       * 
61       * @param windowsIdentity
62       *            Windows identity.
63       */
64      public WindowsPrincipal(final IWindowsIdentity windowsIdentity) {
65          this(windowsIdentity, PrincipalFormat.FQN, PrincipalFormat.FQN);
66      }
67  
68      /**
69       * A windows principal.
70       * 
71       * @param windowsIdentity
72       *            Windows identity.
73       * @param principalFormat
74       *            Principal format.
75       * @param roleFormat
76       *            Role format.
77       */
78      public WindowsPrincipal(final IWindowsIdentity windowsIdentity, final PrincipalFormat principalFormat,
79              final PrincipalFormat roleFormat) {
80          this.identity = windowsIdentity;
81          this.fqn = windowsIdentity.getFqn();
82          this.sid = windowsIdentity.getSid();
83          this.sidString = windowsIdentity.getSidString();
84          this.groups = WindowsPrincipal.getGroups(windowsIdentity.getGroups());
85          this.roles = WindowsPrincipal.getRoles(windowsIdentity, principalFormat, roleFormat);
86      }
87  
88      /**
89       * Gets the roles.
90       *
91       * @param windowsIdentity
92       *            the windows identity
93       * @param principalFormat
94       *            the principal format
95       * @param roleFormat
96       *            the role format
97       * @return the roles
98       */
99      private static List<String> getRoles(final IWindowsIdentity windowsIdentity, final PrincipalFormat principalFormat,
100             final PrincipalFormat roleFormat) {
101         final List<String> roles = new ArrayList<String>();
102         roles.addAll(WindowsPrincipal.getPrincipalNames(windowsIdentity, principalFormat));
103         for (final IWindowsAccount group : windowsIdentity.getGroups()) {
104             roles.addAll(WindowsPrincipal.getRoleNames(group, roleFormat));
105         }
106         return roles;
107     }
108 
109     /**
110      * Gets the groups.
111      *
112      * @param groups
113      *            the groups
114      * @return the groups
115      */
116     private static Map<String, WindowsAccount> getGroups(final IWindowsAccount[] groups) {
117         final Map<String, WindowsAccount> groupMap = new HashMap<String, WindowsAccount>();
118         for (final IWindowsAccount group : groups) {
119             groupMap.put(group.getFqn(), new WindowsAccount(group));
120         }
121         return groupMap;
122     }
123 
124     /**
125      * Byte representation of the SID.
126      * 
127      * @return Array of bytes.
128      */
129     public byte[] getSid() {
130         return this.sid.clone();
131     }
132 
133     /**
134      * String representation of the SID.
135      * 
136      * @return String.
137      */
138     public String getSidString() {
139         return this.sidString;
140     }
141 
142     /**
143      * Windows groups that the user is a member of.
144      * 
145      * @return A map of group names to groups.
146      */
147     public Map<String, WindowsAccount> getGroups() {
148         return this.groups;
149     }
150 
151     /**
152      * Returns a list of role principal objects.
153      * 
154      * @param group
155      *            Windows group.
156      * @param principalFormat
157      *            Principal format.
158      * @return List of role principal objects.
159      */
160     private static List<String> getRoleNames(final IWindowsAccount group, final PrincipalFormat principalFormat) {
161         final List<String> principals = new ArrayList<String>();
162         switch (principalFormat) {
163             case FQN:
164                 principals.add(group.getFqn());
165                 break;
166             case SID:
167                 principals.add(group.getSidString());
168                 break;
169             case BOTH:
170                 principals.add(group.getFqn());
171                 principals.add(group.getSidString());
172                 break;
173             case NONE:
174                 break;
175             default:
176                 break;
177         }
178         return principals;
179     }
180 
181     /**
182      * Returns a list of user principal objects.
183      * 
184      * @param windowsIdentity
185      *            Windows identity.
186      * @param principalFormat
187      *            Principal format.
188      * @return A list of user principal objects.
189      */
190     private static List<String> getPrincipalNames(final IWindowsIdentity windowsIdentity,
191             final PrincipalFormat principalFormat) {
192         final List<String> principals = new ArrayList<String>();
193         switch (principalFormat) {
194             case FQN:
195                 principals.add(windowsIdentity.getFqn());
196                 break;
197             case SID:
198                 principals.add(windowsIdentity.getSidString());
199                 break;
200             case BOTH:
201                 principals.add(windowsIdentity.getFqn());
202                 principals.add(windowsIdentity.getSidString());
203                 break;
204             case NONE:
205                 break;
206             default:
207                 break;
208         }
209         return principals;
210     }
211 
212     /**
213      * Get an array of roles as a string.
214      * 
215      * @return Role1, Role2, ...
216      */
217     public String getRolesString() {
218         return Joiner.on(", ").join(this.roles);
219     }
220 
221     /**
222      * Checks whether the principal has a given role.
223      * 
224      * @param role
225      *            Role name.
226      * @return True if the principal has a role, false otherwise.
227      */
228     public boolean hasRole(final String role) {
229         return this.roles.contains(role);
230     }
231 
232     /**
233      * Fully qualified name.
234      * 
235      * @return String.
236      */
237     @Override
238     public String getName() {
239         return this.fqn;
240     }
241 
242     /**
243      * Underlying identity.
244      * 
245      * @return String.
246      */
247     public IWindowsIdentity getIdentity() {
248         return this.identity;
249     }
250 
251     /* (non-Javadoc)
252      * @see java.lang.Object#toString()
253      */
254     @Override
255     public String toString() {
256         return this.getName();
257     }
258 
259 }