SecurityManager.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel */
40 /* */
41 /* Primitive wrapper around a security manager */
42 /* */
43 /******************************************************************************/
44 
45 #include "RexxCore.h"
46 #include "SecurityManager.hpp"
47 #include "DirectoryClass.hpp"
48 
49 
50 void *SecurityManager::operator new (size_t size)
51 {
52  /* get a new method object */
53  return new_object(size, T_SecurityManager);
54 }
55 
56 
58 {
59  manager = m;
60  supportCall = false;
61  supportCommand = false;
62  supportEnvironment = false;
63  supportLocal = false;
64  supportMethod = false;
65  supportRequires = false;
66  supportStream = false;
67 
68  if (m == OREF_NULL) return;
69 
70  const RexxMethod *TheNilMethod = (RexxMethod *)TheNilObject;
71 
72  bool unknownDefined = TheNilMethod != m->instanceMethod(OREF_UNKNOWN);
73  bool unknownDisabledDefined = TheNilMethod != m->instanceMethod(OREF_UNKNOWNDISABLED);
74  bool supportUnknown = unknownDefined && !unknownDisabledDefined;
75 
76  supportCall = supportUnknown || (TheNilMethod != m->instanceMethod(OREF_CALL));
77  supportCommand = supportUnknown || (TheNilMethod != m->instanceMethod(OREF_COMMAND));
78  supportEnvironment = supportUnknown || (TheNilMethod != m->instanceMethod(OREF_ENVIRONMENT));
79  supportLocal = supportUnknown || (TheNilMethod != m->instanceMethod(OREF_LOCAL));
80  supportMethod = supportUnknown || (TheNilMethod != m->instanceMethod(OREF_METHODNAME));
81  supportRequires = supportUnknown || (TheNilMethod != m->instanceMethod(OREF_REQUIRES));
82  supportStream = supportUnknown || (TheNilMethod != m->instanceMethod(OREF_STREAM));
83 }
84 
85 
86 void SecurityManager::live(size_t liveMark)
87 /******************************************************************************/
88 /* Function: Normal garbage collection live marking */
89 /******************************************************************************/
90 {
91  memory_mark(this->manager);
92 }
93 
94 
96 /******************************************************************************/
97 /* Function: Generalized object marking */
98 /******************************************************************************/
99 {
101 }
102 
103 /**
104  * Do a security manager check for access to the local environment.
105  *
106  * @param index The name of the index.
107  *
108  * @return A replacement object from the security manager.
109  */
111 {
112  if (manager == OREF_NULL || supportLocal == false)
113  {
114  return OREF_NULL;
115  }
116 
117  RexxDirectory *securityArgs = new_directory();
118  ProtectedObject p(securityArgs);
119 
120  securityArgs->put(index, OREF_NAME);
121  securityArgs->put(TheNilObject, OREF_RESULT);
122  if (callSecurityManager(OREF_LOCAL, securityArgs))
123  {
124  /* get the result and return */
125  return securityArgs->fastAt(OREF_RESULT);
126  }
127  return OREF_NULL; // not handled
128 }
129 
130 
131 /**
132  * Do a security manager check for access to the global
133  * environment.
134  *
135  * @param index The name of the index.
136  *
137  * @return A replacement object from the security manager.
138  */
140 {
141  if (manager == OREF_NULL || supportEnvironment == false)
142  {
143  return OREF_NULL;
144  }
145 
146  RexxDirectory *securityArgs = new_directory();
147  ProtectedObject p(securityArgs);
148 
149  securityArgs->put(index, OREF_NAME);
150  securityArgs->put(TheNilObject, OREF_RESULT);
151  if (callSecurityManager(OREF_ENVIRONMENT, securityArgs))
152  {
153  /* get the result and return */
154  return securityArgs->fastAt(OREF_RESULT);
155  }
156  return OREF_NULL; // not handled
157 }
158 
159 
160 /**
161  * Do the actual invocation of the security manager.
162  *
163  * @param methodName The method name to invoke.
164  * @param arguments The arguments to the specific method.
165  *
166  * @return true if the security manager overrode this, false otherwise.
167  */
169 {
170  // invoke the manager
171  RexxObject *resultObj = manager->sendMessage(methodName, arguments);
172  if (resultObj == OREF_NULL) /* no return result? */
173  {
174  /* need to raise an exception */
176  }
178 }
179 
180 
181 /**
182  * Check for permission to call a protected method.
183  *
184  * @param target The target object.
185  * @param messageName
186  * The name of the message.
187  * @param count The return count.
188  * @param arguments The method arguments.
189  * @param result The returned result.
190  *
191  * @return true if the security manager handled this call, false otherwise.
192  */
193 bool SecurityManager::checkProtectedMethod(RexxObject *target, RexxString *messageName, size_t count, size_t named_count, RexxObject **arguments, ProtectedObject &result)
194 {
195  // no method here
196  if (manager == OREF_NULL || supportMethod == false)
197  {
198  return false;
199  }
200  RexxDirectory *securityArgs = new_directory();
201  ProtectedObject p(securityArgs);
202 
203  securityArgs->put(target, OREF_OBJECTSYM);
204  securityArgs->put(messageName, OREF_NAME);
205  RexxArray *argumentArray = new (count, arguments) RexxArray;
206  securityArgs->put(argumentArray, OREF_ARGUMENTS);
207 
208  // TODO
209  // Directory of named arguments
210 
211  if (callSecurityManager(OREF_METHODNAME, securityArgs))
212  {
213  // get the result and return
214  result = securityArgs->fastAt(OREF_RESULT);
215  return true;
216  }
217  return false; // not handled
218 }
219 
220 
221 /**
222  * Check for permission to call an external function.
223  *
224  * @param functionName
225  * The name of the target function.
226  * @param count The return count.
227  * @param arguments The method arguments.
228  * @param result The returned result.
229  *
230  * @return true if the security manager handled this call, false otherwise.
231  */
232 bool SecurityManager::checkFunctionCall(RexxString *functionName, size_t count, size_t named_count, RexxObject **arguments, ProtectedObject &result)
233 {
234  // no method here
235  if (manager == OREF_NULL || supportCall == false)
236  {
237  return false;
238  }
239  RexxDirectory *securityArgs = new_directory();
240  ProtectedObject p(securityArgs);
241 
242  securityArgs->put(functionName, OREF_NAME);
243  RexxArray *argumentArray = new (count, arguments) RexxArray;
244  securityArgs->put(argumentArray, OREF_ARGUMENTS);
245 
246  // TODO
247  // Directory of named arguments
248 
249  if (callSecurityManager(OREF_CALL, securityArgs))
250  {
251  // get the result and return
252  result = securityArgs->fastAt(OREF_RESULT);
253  return true;
254  }
255  return false; // not handled
256 }
257 
258 
259 /**
260  * Check for permission to call an external command
261  *
262  * @param activity The activity we're running on
263  * @param address
264  * @param command
265  * @param result The returned result.
266  * @param condition
267  *
268  * @return true if the security manager handled this call, false otherwise.
269  */
270 bool SecurityManager::checkCommand(RexxActivity *activity, RexxString *address, RexxString *command, ProtectedObject &result, ProtectedObject &condition)
271 {
272  // no method here
273  if (manager == OREF_NULL || supportCommand == false)
274  {
275  return false;
276  }
277  RexxDirectory *securityArgs = new_directory();
278  ProtectedObject p(securityArgs);
279  /* add the command */
280  securityArgs->put(command, OREF_COMMAND);
281  /* and the target */
282  securityArgs->put(address, OREF_ADDRESS);
283  /* did manager handle this? */
284  if (callSecurityManager(OREF_COMMAND, securityArgs))
285  {
286  /* get the return code */
287  result = securityArgs->fastAt(OREF_RC);
288  if ((RexxObject *)result == OREF_NULL) /* no return code provide? */
289  {
290  result = IntegerZero; /* use a zero return code */
291  }
292  /* failure indicated? */
293  if (securityArgs->fastAt(OREF_FAILURENAME) != OREF_NULL)
294  {
295  // raise the condition when things are done
296  condition = activity->createConditionObject(OREF_FAILURENAME, (RexxObject *)result, command, OREF_NULL, OREF_NULL);
297  }
298  /* how about an error condition? */
299  else if (securityArgs->fastAt(OREF_ERRORNAME) != OREF_NULL)
300  {
301  // raise the condition when things are done
302  condition = activity->createConditionObject(OREF_ERRORNAME, (RexxObject *)result, command, OREF_NULL, OREF_NULL);
303  }
304  return true;
305  }
306 
307  return false; // not handled
308 }
309 
310 
311 /**
312  * Check for stream access permission.
313  *
314  * @param name The name of the stream.
315  *
316  * @return If the security manager handles this, the replacement stream object.
317  */
319 {
320  if (manager == OREF_NULL || supportStream == false)
321  {
322  return OREF_NULL;
323  }
324 
325  RexxDirectory *securityArgs = new_directory();
326  ProtectedObject p(securityArgs);
327 
328  securityArgs->put(name, OREF_NAME);
329  if (callSecurityManager(OREF_STREAM, securityArgs))
330  {
331  // get the result and return
332  return securityArgs->fastAt(OREF_RESULT);
333  }
334  // not handled
335  return OREF_NULL;
336 }
337 
338 
339 /**
340  * Check for requires file access
341  *
342  * @param name The name of the stream.
343  *
344  * @return The actual requires file name that should be loaded. A
345  * return of OREF_NULL means access to this is not permitted.
346  */
348 {
349  // just return the same name if no manager object set.
350  if (manager == OREF_NULL || supportRequires == false)
351  {
352  return name;
353  }
354 
355  RexxDirectory *securityArgs = new_directory();
356  ProtectedObject p(securityArgs);
357 
358  /* add the program name */
359  securityArgs->put(name, OREF_NAME);
360  /* did manager handle this? */
361  if (callSecurityManager(OREF_REQUIRES, securityArgs))
362  {
363  // retrieve any security manager that the security manager wants us to use for
364  // a new file.
365  RexxObject *secObject = securityArgs->fastAt(OREF_SECURITYMANAGER);
366  if (secObject != OREF_NULL && secObject != TheNilObject)
367  {
368  securityManager = secObject;
369  }
370  // the name can be replaced by the security manager
371  return (RexxString *)securityArgs->fastAt(OREF_NAME);
372  }
373  // not handled, return the name unchanged
374  return name;
375 }
376 
void reportException(wholenumber_t error)
@ T_SecurityManager
RexxDirectory * new_directory()
#define OREF_NULL
Definition: RexxCore.h:61
#define TheNilObject
Definition: RexxCore.h:191
#define IntegerZero
Definition: RexxCore.h:199
#define Error_No_result_object_message
#define Error_Logical_value_authorization
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:436
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
RexxDirectory * createConditionObject(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *)
RexxObject * put(RexxObject *, RexxString *)
RexxObject * fastAt(RexxString *name)
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
RexxMethod * instanceMethod(RexxString *)
bool truthValue(int)
bool checkFunctionCall(RexxString *functionName, size_t count, size_t named_count, RexxObject **arguments, ProtectedObject &result)
RexxObject * checkEnvironmentAccess(RexxString *index)
void live(size_t)
RexxObject * checkLocalAccess(RexxString *index)
bool callSecurityManager(RexxString *methodName, RexxDirectory *arguments)
RexxString * checkRequiresAccess(RexxString *name, RexxObject *&securityManager)
RexxObject * checkStreamAccess(RexxString *name)
SecurityManager(RexxObject *m)
void liveGeneral(int reason)
bool checkCommand(RexxActivity *, RexxString *address, RexxString *command, ProtectedObject &result, ProtectedObject &condition)
RexxObject * manager
bool checkProtectedMethod(RexxObject *target, RexxString *messageName, size_t count, size_t named_count, RexxObject **arguments, ProtectedObject &result)