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