root/trunk/src/java/org/jcoderz/commons/connector/SecurityUtil.java

Revision 1011, 9.8 kB (checked in by amandel, 4 years ago)

Aligned svn keyword settings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.commons.connector;
34
35import java.security.AccessController;
36import java.security.PrivilegedAction;
37import java.util.Iterator;
38import java.util.Set;
39import java.util.logging.Level;
40import java.util.logging.Logger;
41
42import javax.resource.spi.ConnectionRequestInfo;
43import javax.resource.spi.ManagedConnectionFactory;
44import javax.resource.spi.SecurityException;
45import javax.resource.spi.security.GenericCredential;
46import javax.resource.spi.security.PasswordCredential;
47import javax.security.auth.Subject;
48
49/**
50 * Utility provides method to extract user name and password from a set of
51 * security relevant objects such as
52 * {@link javax.resource.spi.security.PasswordCredential},
53 * {@link javax.resource.spi.ConnectionRequestInfo} and so on.
54 *
55 */
56public final class SecurityUtil
57{
58   /** The full qualified name of this class. */
59   private static final String CLASSNAME = SecurityUtil.class.getName();
60
61   /** The logger to use. */
62   private static final Logger logger = Logger.getLogger(CLASSNAME);
63
64   private SecurityUtil ()
65   {
66
67   }
68
69   /**
70    * Extracts the user name and password from the given set of objects as
71    * specified in the JCA 1.0 Chapter 8.2.6.
72    *
73    * @param subject Current Security Subject passed by the application server.
74    * @param mcf The managed connection factory
75    * @param cri Connection reques info
76    *
77    * @return UserPassword instance. If no user name / password can be
78    * extracted, this method returns {@link UserPassword#EMPTY_USER_PASSWORD}.
79    *
80    * @throws SecurityException Thown if no applicable credentials found in
81    * the Subject.
82    */
83   public static UserPassword getUserPassword (Subject subject,
84      ManagedConnectionFactory mcf, ConnectionRequestInfo cri)
85         throws SecurityException
86   {
87      final String method = "getUserPassword";
88      final boolean finer = logger.isLoggable(Level.FINER);
89      if (finer)
90      {
91         logger.entering(CLASSNAME, method, new Object [] {subject, mcf, cri});
92      }
93
94      UserPassword result = UserPassword.EMPTY_USER_PASSWORD;
95
96      if (subject != null)
97      {
98         // JCA 1.0 8.2.6 Contract for RA (Option A)
99         final PasswordCredential pc = PrivilegedExecutor.getPasswordCredential(
100               subject, mcf);
101         if (pc != null)
102         {
103            result = UserPassword.fromUserPassword(pc.getUserName(), new String(
104                  pc.getPassword()));
105         }
106         else
107         {
108            final SecurityException rse = new SecurityException(
109                  "No applicable credentials found in the Subject passed by the"
110                        + " application server.");
111
112            logger.throwing(CLASSNAME, method, rse);
113            throw rse;
114
115            // TODO Implements this path if required. (required ?)
116
117            // JCA 1.0 8.2.6 Contract for RA (Option B)
118            /*
119            final GenericCredential gc
120                  = PrivilegedExecutor.getGenericCredential(subject, mcf);
121
122            if (gc == null)
123            {
124               throw new SecurityException("No applicable credentials found in"
125                     + " the Subject passed by the application server.");
126            }
127            */
128         }
129
130      }
131      else if (cri != null)
132      {
133         // JCA 1.0 8.2.6 Contract for RA (Option C)
134         if (!(cri instanceof ConnectionRequestInfoBase))
135         {
136            final SecurityException rse = new SecurityException("No applicable "
137                  + "ConnectionRequestInfo passed by the application server.");
138            logger.throwing(CLASSNAME, method, rse);
139            throw rse;
140         }
141
142         result = UserPassword.fromUserPassword(
143               ((ConnectionRequestInfoBase) cri).getUserPassword());
144      }
145
146      if (finer)
147      {
148         logger.exiting(CLASSNAME, method, result);
149      }
150
151      return result;
152   }
153
154   /**
155    * This class is intended to execute a privileged action.
156    * The security contract assumes that a resource adapter has the necessary
157    * security permissions to extract a private credential set from a Subject
158    * instance.
159    */
160   private static class PrivilegedExecutor
161         implements PrivilegedAction
162   {
163      private final Subject mSubject;
164      private final ManagedConnectionFactory mMcf;
165      private final boolean mPcAction;
166
167      PrivilegedExecutor (Subject subject, ManagedConnectionFactory mcf,
168            boolean pcAction)
169      {
170         mSubject = subject;
171         mMcf = mcf;
172         mPcAction = pcAction;
173      }
174
175      /** {@inheritDoc} */
176      public Object run ()
177      {
178         final Object result;
179         if (mPcAction)
180         {
181            result = getPwdCredential();
182         }
183         else
184         {
185            result = getGenCredential();
186         }
187         return result;
188      }
189
190      private Object getPwdCredential ()
191      {
192         // This method implements the behavior of a Resource Adapter specified
193         // in the JCA 1.0 8.2.6 Contract for RA (Option A)
194
195         // The resource adapter explicitly checks whether the passed Subject
196         // instance carries a PasswordCredential instance using the
197         // Subject.getPrivateCredentials method.
198         final Set creds = mSubject.getPrivateCredentials(
199               PasswordCredential.class);
200         PasswordCredential pc = null;
201         // Since a Subject instance can carry multiple PasswordCredential
202         // instances, a Managed- ConnectionFactory should only use a
203         // PasswordCredential instance that has been specifically passed to
204         // it through the security contract.
205         final Iterator credentials = creds.iterator();
206         while (credentials.hasNext())
207         {
208            final PasswordCredential pcCurrent
209                  = (PasswordCredential) credentials.next();
210
211            // The ManagedConnectionFactory implementation uses the equals
212            // method to compare itself with the passed instance.
213            if (pcCurrent.getManagedConnectionFactory().equals(mMcf))
214            {
215               pc = pcCurrent;
216               break;
217            }
218         }
219         return pc;
220      }
221
222      private Object getGenCredential ()
223      {
224         // This method implements the behavior of a Resource Adapter specified
225         // in the JCA 1.0 8.2.6 Contract for RA (Option B)
226
227         // The resource adapter explicitly checks whether passed Subject
228         // instance carries a GenericCredential instance using the methods
229         // getPrivateCredentials and getPublicCredentials defined on the
230         // Subject interface.
231         final Set creds = mSubject.getPrivateCredentials(
232               GenericCredential.class);
233
234         Object result = null;
235
236         final Iterator credentials = creds.iterator();
237         while (credentials.hasNext())
238         {
239            final GenericCredential c = (GenericCredential) credentials.next();
240            result = c;
241            break;
242         }
243         return result;
244      }
245
246      /**
247       * Tries to extract a PasswordCredential from the Subject
248       * <code>subject</code> applicable to the managed connection factory
249       * <code>mcf</code>.
250       * Executes a privileged action.
251       *
252       *
253       * @param subject Current Security Subject passed by the
254       *    application server.
255       * @param mcf The managed connection factory
256       *
257       * @return a PasswordCredential or null.
258       */
259      static PasswordCredential getPasswordCredential (Subject subject,
260            ManagedConnectionFactory mcf)
261      {
262         return (PasswordCredential) AccessController.doPrivileged(
263               new PrivilegedExecutor(subject, mcf, true));
264      }
265
266      /**
267       * Tries to extract a GenericCredential from the Subject
268       * <code>subject</code> applicable to the managed connection factory
269       * <code>mcf</code>.
270       * Executes a privileged action.
271       *
272       * @param subject Current Security Subject passed by the application
273       *    server.
274       *
275       * @param mcf The managed connection factory
276       *
277       * @return a GenericCredential or null.
278       */
279      static GenericCredential getGenericCredential (Subject subject,
280            ManagedConnectionFactory mcf)
281      {
282         return (GenericCredential) AccessController.doPrivileged(
283               new PrivilegedExecutor(subject, mcf, false));
284      }
285   }
286}
Note: See TracBrowser for help on using the browser.