001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.extensions;
028    
029    
030    
031    import java.util.HashSet;
032    import java.util.List;
033    import java.util.Set;
034    
035    import org.opends.messages.Message;
036    import org.opends.server.admin.std.server.WhoAmIExtendedOperationHandlerCfg;
037    import org.opends.server.api.ClientConnection;
038    import org.opends.server.api.ExtendedOperationHandler;
039    import org.opends.server.config.ConfigException;
040    import org.opends.server.controls.ProxiedAuthV1Control;
041    import org.opends.server.controls.ProxiedAuthV2Control;
042    import org.opends.server.core.DirectoryServer;
043    import org.opends.server.core.ExtendedOperation;
044    import org.opends.server.loggers.debug.DebugTracer;
045    import org.opends.server.protocols.asn1.ASN1OctetString;
046    import org.opends.server.types.Control;
047    import org.opends.server.types.DebugLogLevel;
048    import org.opends.server.types.DirectoryException;
049    import org.opends.server.types.DN;
050    import org.opends.server.types.Entry;
051    import org.opends.server.types.InitializationException;
052    import org.opends.server.types.LDAPException;
053    import org.opends.server.types.Privilege;
054    import org.opends.server.types.ResultCode;
055    
056    import static org.opends.server.loggers.debug.DebugLogger.*;
057    import static org.opends.messages.ExtensionMessages.*;
058    import static org.opends.server.util.ServerConstants.*;
059    
060    
061    /**
062     * This class implements the "Who Am I?" extended operation defined in RFC 4532.
063     * It simply returns the authorized ID of the currently-authenticated user.
064     */
065    public class WhoAmIExtendedOperation
066           extends ExtendedOperationHandler<WhoAmIExtendedOperationHandlerCfg>
067    {
068      /**
069       * The tracer object for the debug logger.
070       */
071      private static final DebugTracer TRACER = getTracer();
072    
073    
074    
075      /**
076       * Create an instance of this "Who Am I?" extended operation.  All
077       * initialization should be performed in the
078       * <CODE>initializeExtendedOperationHandler</CODE> method.
079       */
080      public WhoAmIExtendedOperation()
081      {
082        super();
083      }
084    
085    
086      /**
087       * Initializes this extended operation handler based on the information in the
088       * provided configuration entry.  It should also register itself with the
089       * Directory Server for the particular kinds of extended operations that it
090       * will process.
091       *
092       * @param  config       The configuration that contains the information
093       *                      to use to initialize this extended operation handler.
094       *
095       * @throws  ConfigException  If an unrecoverable problem arises in the
096       *                           process of performing the initialization.
097       *
098       * @throws  InitializationException  If a problem occurs during initialization
099       *                                   that is not related to the server
100       *                                   configuration.
101       */
102      public void initializeExtendedOperationHandler(
103                       WhoAmIExtendedOperationHandlerCfg config)
104             throws ConfigException, InitializationException
105      {
106        // No special configuration is required.
107    
108        DirectoryServer.registerSupportedExtension(OID_WHO_AM_I_REQUEST, this);
109    
110        registerControlsAndFeatures();
111      }
112    
113    
114    
115      /**
116       * Performs any finalization that may be necessary for this extended
117       * operation handler.  By default, no finalization is performed.
118       */
119      @Override()
120      public void finalizeExtendedOperationHandler()
121      {
122        DirectoryServer.deregisterSupportedExtension(OID_WHO_AM_I_REQUEST);
123    
124        deregisterControlsAndFeatures();
125      }
126    
127    
128    
129      /**
130       * {@inheritDoc}
131       */
132      @Override()
133      public Set<String> getSupportedControls()
134      {
135        HashSet<String> supportedControls = new HashSet<String>(2);
136    
137        supportedControls.add(OID_PROXIED_AUTH_V1);
138        supportedControls.add(OID_PROXIED_AUTH_V2);
139    
140        return supportedControls;
141      }
142    
143    
144    
145      /**
146       * {@inheritDoc}
147       */
148      @Override()
149      public void processExtendedOperation(ExtendedOperation operation)
150      {
151        // Process any supported controls for this operation, including the
152        // proxied authorization control.
153        ClientConnection clientConnection = operation.getClientConnection();
154        List<Control> requestControls = operation.getRequestControls();
155        if (requestControls != null)
156        {
157          for (Control c : requestControls)
158          {
159            String oid = c.getOID();
160            if (oid.equals(OID_PROXIED_AUTH_V1))
161            {
162              // The requester must have the PROXIED_AUTH privilige in order to
163              // be able to use this control.
164              if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH,
165                                                  operation))
166              {
167    
168                operation.appendErrorMessage(
169                        ERR_EXTOP_WHOAMI_PROXYAUTH_INSUFFICIENT_PRIVILEGES.get());
170                operation.setResultCode(ResultCode.AUTHORIZATION_DENIED);
171                return;
172              }
173    
174    
175              ProxiedAuthV1Control proxyControl;
176              if (c instanceof ProxiedAuthV1Control)
177              {
178                proxyControl = (ProxiedAuthV1Control) c;
179              }
180              else
181              {
182                try
183                {
184                  proxyControl = ProxiedAuthV1Control.decodeControl(c);
185                }
186                catch (LDAPException le)
187                {
188                  if (debugEnabled())
189                  {
190                    TRACER.debugCaught(DebugLogLevel.ERROR, le);
191                  }
192    
193                  operation.setResultCode(ResultCode.valueOf(le.getResultCode()));
194                  operation.appendErrorMessage(le.getMessageObject());
195                  return;
196                }
197              }
198    
199    
200              Entry authorizationEntry;
201              try
202              {
203                authorizationEntry = proxyControl.getAuthorizationEntry();
204              }
205              catch (DirectoryException de)
206              {
207                if (debugEnabled())
208                {
209                  TRACER.debugCaught(DebugLogLevel.ERROR, de);
210                }
211    
212                operation.setResultCode(de.getResultCode());
213                operation.appendErrorMessage(de.getMessageObject());
214                return;
215              }
216    
217              operation.setAuthorizationEntry(authorizationEntry);
218            }
219            else if (oid.equals(OID_PROXIED_AUTH_V2))
220            {
221              // The requester must have the PROXIED_AUTH privilige in order to
222              // be able to use this control.
223              if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH,
224                                                  operation))
225              {
226    
227                operation.appendErrorMessage(
228                        ERR_EXTOP_WHOAMI_PROXYAUTH_INSUFFICIENT_PRIVILEGES.get());
229                operation.setResultCode(ResultCode.AUTHORIZATION_DENIED);
230                return;
231              }
232    
233    
234              ProxiedAuthV2Control proxyControl;
235              if (c instanceof ProxiedAuthV2Control)
236              {
237                proxyControl = (ProxiedAuthV2Control) c;
238              }
239              else
240              {
241                try
242                {
243                  proxyControl = ProxiedAuthV2Control.decodeControl(c);
244                }
245                catch (LDAPException le)
246                {
247                  if (debugEnabled())
248                  {
249                    TRACER.debugCaught(DebugLogLevel.ERROR, le);
250                  }
251    
252                  operation.setResultCode(ResultCode.valueOf(le.getResultCode()));
253                  operation.appendErrorMessage(le.getMessageObject());
254                  return;
255                }
256              }
257    
258    
259              Entry authorizationEntry;
260              try
261              {
262                authorizationEntry = proxyControl.getAuthorizationEntry();
263              }
264              catch (DirectoryException de)
265              {
266                if (debugEnabled())
267                {
268                  TRACER.debugCaught(DebugLogLevel.ERROR, de);
269                }
270    
271                operation.setResultCode(de.getResultCode());
272                operation.appendErrorMessage(de.getMessageObject());
273                return;
274              }
275    
276              operation.setAuthorizationEntry(authorizationEntry);
277            }
278          }
279        }
280    
281    
282        // Get the authorization DN for the operation and add it to the response
283        // value.
284        String authzID;
285        DN authzDN = operation.getAuthorizationDN();
286        if (authzDN == null)
287        {
288          authzID = "";
289        }
290        else
291        {
292          authzID = "dn:" + authzDN.toString();
293        }
294    
295        operation.setResponseValue(new ASN1OctetString(authzID));
296        operation.appendAdditionalLogMessage(
297                Message.raw("authzID=\"" + authzID + "\""));
298        operation.setResultCode(ResultCode.SUCCESS);
299      }
300    }
301