001    /*
002      Copyright (C) 2001-2002 Renaud Pawlak <renaud@aopsys.com>, 
003      Laurent Martelli <laurent@aopsys.com>
004      
005      This program is free software; you can redistribute it and/or modify
006      it under the terms of the GNU Lesser General Public License as
007      published by the Free Software Foundation; either version 2 of the
008      License, or (at your option) any later version.
009    
010      This program is distributed in the hope that it will be useful,
011      but WITHOUT ANY WARRANTY; without even the implied warranty of
012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013      GNU Lesser General Public License for more details.
014    
015      You should have received a copy of the GNU Lesser General Public License
016      along with this program; if not, write to the Free Software
017      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
018    
019    package org.objectweb.jac.aspects.authentication;
020    
021    import org.aopalliance.intercept.ConstructorInvocation;
022    import org.aopalliance.intercept.MethodInvocation;
023    import org.objectweb.jac.aspects.gui.*;
024    import org.objectweb.jac.core.*;
025    import org.objectweb.jac.core.AspectComponent;
026    import org.objectweb.jac.core.rtti.*;
027    import org.objectweb.jac.util.*;
028    
029    /**
030     * This wrapper uses an authenticator and a controller to ensure that
031     * the current interaction is authenticated and allowed.
032     *
033     * @see AuthenticationAC
034     * @see Authenticator */
035    
036    public class AuthenticationWrapper extends Wrapper {
037    
038            Authenticator authenticator;
039            MethodItem controller;
040    
041            public Object invoke(MethodInvocation invocation) throws Throwable {
042                    return authenticateAndControl((Interaction) invocation);
043            }
044    
045            public Object construct(ConstructorInvocation invocation)
046                    throws Throwable {
047                    return authenticateAndControl((Interaction) invocation);
048            }
049    
050            /**
051             * Constructs a new authentication wrapper.
052             *
053             * @param ac the aspect component that owns this wrapper
054             * @param authenticator the object that authenticates
055             * @param controller the method that grants the rights or not 
056             */
057            public AuthenticationWrapper(
058                    AspectComponent ac,
059                    Authenticator authenticator,
060                    MethodItem controller) 
061        {
062                    super(ac);
063                    Log.trace(
064                            "authentication",
065                            "new authentication wrapper: " + authenticator + "," + controller);
066                    this.authenticator = authenticator;
067                    this.controller = controller;
068            }
069    
070            /**
071             * Sets the access rights controller.
072             *
073             * @param controller a static method of the prototype <code>boolean
074             * controller(String username,Object wrappee,MethodItem method)</code>
075             * @see org.objectweb.jac.aspects.user.UserAC#userController(String,Object,MethodItem)
076             * @see #dummyController(String,Object,MethodItem)
077             */
078            public void setController(MethodItem controller) {
079                    Log.trace(
080                            "authentication",
081                            "wrapper setController(" + controller + ")");
082                    this.controller = controller;
083            }
084    
085            public void setAuthenticator(Authenticator authenticator) {
086                    Log.trace(
087                            "authentication",
088                            "wrapper setAuthenticator(" + authenticator + ")");
089                    this.authenticator = authenticator;
090            }
091    
092            /**
093             * This wrapping method authenticates a call on the wrapped method
094             * and controls that the authentcated user owns the rights to call
095             * it.<p>
096             *
097             * @return the value returned by the wrapped method 
098         */
099            public Object authenticateAndControl(Interaction interaction)
100                    throws AuthenticationFailedException, AccessDeniedException, Throwable {
101    
102                    if (interaction.wrappee instanceof Display
103                            && interaction.method.getName().equals("showCustomized")) {
104                            CustomizedGUI cgui = (CustomizedGUI) interaction.args[1];
105                            if (cgui != null) {
106                                    Log.trace(
107                                            "application",
108                                            "auth sets application to " + cgui.getApplication());
109                                    Collaboration.get().setCurApp(cgui.getApplication());
110                            } else {
111                                    Log.trace(
112                                            "application",
113                                            "auth cannot set the application since "
114                        + "customized GUI is null");
115                            }
116                    }
117    
118                    Log.trace(
119                            "authentication",
120                            "authenticate for method "
121                + interaction.method
122                + " on "
123                + interaction.wrappee);
124                    Log.trace(
125                            "authentication",
126                            "name is: " + (String) attr(AuthenticationAC.USER));
127                    String name = (String) attr(AuthenticationAC.USER);
128                    String password = null;
129                    if (name == null) {
130                            try {
131                                    name = authenticator.authenticate();
132                                    Log.trace("authentication", "authenticated " + name);
133                                    attrdef(AuthenticationAC.USER, name);
134                            } catch (Exception e) {
135                                    Log.trace(
136                                            "authentication",
137                                            "user authentication failed for "
138                        + interaction.method
139                        + " because of exception: "
140                        + e);
141                                    e.printStackTrace();
142                            }
143                    }
144                    try {
145                            Boolean allowed =
146                                    (Boolean) controller.invokeStatic(
147                                            new Object[] {
148                                                    name,
149                                                    interaction.wrappee,
150                                                    interaction.method });
151                            if (allowed.booleanValue()) {
152                                    Log.trace(
153                                            "authentication",
154                                            "accesses granted to "
155                        + name
156                        + " for "
157                        + interaction.method);
158                                    return proceed(interaction);
159                            } else {
160                                    Log.trace(
161                                            "authentication",
162                                            "accesses denied to "
163                        + name
164                        + " for "
165                        + interaction.method);
166                                    throw new AccessDeniedException(
167                                            accessDeniedMessage != null
168                        ? accessDeniedMessage
169                        : "you are not allowed to call "
170                        + interaction.method
171                        + " on "
172                        + interaction.wrappee);
173                            }
174                    } catch (Exception e) {
175                            Log.trace(
176                                    "authentication",
177                                    "accesses denied to "
178                    + name
179                    + " for "
180                    + interaction.method
181                    + " because of exception: "
182                    + e);
183                            Log.trace("authentication", 2, e);
184                            throw new AccessDeniedException(
185                                    "you are not allowed to call "
186                    + interaction.method
187                    + " on "
188                    + interaction.wrappee
189                    + ": "
190                    + e);
191                    }
192            }
193    
194            /**
195             * Returns true if the user is in the trusted users list.
196             *
197             * @param username the name of the user to check
198             * @return true if trusted 
199         */
200            public boolean isTrustedUser(String username) {
201                    Log.trace(
202                            "authentication",
203                            "is trusted user: " + username + ":" + getAspectComponent());
204                    return ((AuthenticationAC) getAspectComponent()).isTrustedUser(
205                            username);
206            }
207    
208            String accessDeniedMessage = "Access denied";
209    
210            /**
211             * Sets the message to show when the access is denied.
212             * 
213             * @param message the message 
214         */
215            public void setAccessDeniedMessage(String message) {
216                    this.accessDeniedMessage = message;
217            }
218    
219            /**
220             * This exception handler reacts when the access is denied.
221             *
222             * @param e the acces denied exception 
223         */
224            public void catchAccessDenied(AccessDeniedException e) {
225                    Log.trace("authentication", "catching " + e.toString());
226                    DisplayContext context =
227                            (DisplayContext) Collaboration.get().getAttribute(
228                                    GuiAC.DISPLAY_CONTEXT);
229                    if (context != null) {
230                            Display display = context.getDisplay();
231                            if (display != null) {
232                                    display.showMessage("Error", accessDeniedMessage);
233                                    return;
234                            }
235                    }
236                    Log.error("no display available");
237            }
238    
239            /**
240             * Always return true. Use to force authentication.
241             *
242             * @param username the user's name
243             * @param wrappee the authenticated method
244             * @param method the authenticated method
245             */
246            public static boolean dummyController(
247                    String username,
248                    Object wrappee,
249                    MethodItem method) {
250                    return true;
251            }
252    
253    }