1/*
2  Copyright (C) 2002-2005 SKYRIX Software AG
3
4  This file is part of SOPE.
5
6  SOPE is free software; you can redistribute it and/or modify it under
7  the terms of the GNU Lesser General Public License as published by the
8  Free Software Foundation; either version 2, or (at your option) any
9  later version.
10
11  SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14  License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with SOPE; see the file COPYING.  If not, write to the
18  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19  02111-1307, USA.
20*/
21
22#include "SoClassSecurityInfo.h"
23#include "SoClass.h"
24#include "common.h"
25
26@implementation SoClassSecurityInfo
27
28- (id)initWithSoClass:(SoClass *)_class {
29  if ((self = [self init])) {
30    self->className = [[_class className] copy];
31  }
32  return self;
33}
34
35- (void)dealloc {
36  [self->defaultAccess release];
37  [self->publicNames   release];
38  [self->privateNames  release];
39  [self->nameToPerm    release];
40  [self->defRoles      release];
41  [self->objectPermission release];
42  [self->className     release];
43  [super dealloc];
44}
45
46/* attribute security */
47
48- (void)_logPermAlreadySetForName:(NSString *)_name {
49  [self warnWithFormat:
50          @"tried to declare permission for attribute '%@' twice!", _name];
51}
52
53- (void)setDefaultAccess:(NSString *)_access {
54  if (self->defaultAccess)
55    [self _logPermAlreadySetForName:@"<default>"];
56  else {
57    self->defaultAccess = [_access isNotNull] ? [_access copy] : nil;
58    [self debugWithFormat:@"set default access: '%@'", self->defaultAccess];
59  }
60}
61- (NSString *)defaultAccess {
62  return self->defaultAccess;
63}
64- (BOOL)hasDefaultAccessDeclaration {
65  return [self->defaultAccess length] > 0 ? YES : NO;
66}
67
68- (void)declarePublic:(NSString *)_firstName, ... {
69  va_list va;
70  NSString *aname;
71
72  if (self->publicNames == nil)
73    self->publicNames = [[NSMutableSet alloc] init];
74
75  va_start(va, _firstName);
76  for (aname = _firstName; aname != nil; aname = va_arg(va, id)) {
77    if ([self->publicNames containsObject:aname])
78      [self _logPermAlreadySetForName:aname];
79    else if ([self->privateNames containsObject:aname])
80      [self _logPermAlreadySetForName:aname];
81    else if ([self->nameToPerm objectForKey:aname])
82      [self _logPermAlreadySetForName:aname];
83    else {
84      [self->publicNames addObject:aname];
85      [self debugWithFormat:@"set key public: '%@'", aname];
86    }
87  }
88  va_end(va);
89}
90
91- (void)declarePrivate:(NSString *)_firstName, ... {
92  va_list va;
93  NSString *aname;
94
95  if (self->privateNames == nil)
96    self->privateNames = [[NSMutableSet alloc] init];
97
98  va_start(va, _firstName);
99  for (aname = _firstName; aname != nil; aname = va_arg(va, id)) {
100    if ([self->publicNames containsObject:aname])
101      [self _logPermAlreadySetForName:aname];
102    else if ([self->privateNames containsObject:aname])
103      [self _logPermAlreadySetForName:aname];
104    else if ([self->nameToPerm objectForKey:aname])
105      [self _logPermAlreadySetForName:aname];
106    else {
107      [self->privateNames addObject:aname];
108      [self debugWithFormat:@"set key private: '%@'", aname];
109    }
110  }
111  va_end(va);
112}
113
114- (void)declareProtected:(NSString *)_perm :(NSString *)_firstName, ... {
115  va_list  va;
116  NSString *aname;
117
118  _perm = [_perm lowercaseString];
119
120  if (self->nameToPerm == nil)
121    self->nameToPerm = [[NSMutableDictionary alloc] initWithCapacity:16];
122
123  va_start(va, _firstName);
124  for (aname = _firstName; aname != nil; aname = va_arg(va, id)) {
125    if ([self->publicNames containsObject:aname])
126      [self _logPermAlreadySetForName:aname];
127    else if ([self->privateNames containsObject:aname])
128      [self _logPermAlreadySetForName:aname];
129    else if ([self->nameToPerm objectForKey:aname])
130      [self _logPermAlreadySetForName:aname];
131    else {
132      [self->nameToPerm setObject:_perm forKey:aname];
133      [self debugWithFormat:@"protect key by '%@': '%@'", _perm, aname];
134    }
135  }
136  va_end(va);
137}
138
139- (BOOL)hasProtectionsForKey:(NSString *)_key {
140  if (_key == nil) return NO;
141
142  if ([self->publicNames  containsObject:_key]) return YES;
143  if ([self->privateNames containsObject:_key]) return YES;
144  if ([self->nameToPerm objectForKey:_key]) return YES;
145  return NO;
146}
147
148- (BOOL)isKeyPrivate:(NSString *)_key {
149  return [self->privateNames containsObject:_key];
150}
151- (BOOL)isKeyPublic:(NSString *)_key {
152  return [self->publicNames containsObject:_key];
153}
154- (NSString *)permissionRequiredForKey:(NSString *)_key {
155  return [self->nameToPerm objectForKey:_key];
156}
157
158/* object security */
159
160- (void)_logObjPermAlreadySet {
161  [self warnWithFormat:@"tried to declare object permission twice! "
162          @"(perm=%@,private=%s,public=%s)",
163          self->objectPermission,
164          self->isObjectPrivate?"yes":"no",
165          self->isObjectPublic?"yes":"no"];
166}
167
168- (BOOL)hasObjectProtections {
169  if (self->objectPermission) return YES;
170  if (self->isObjectPrivate)  return YES;
171  if (self->isObjectPublic)   return YES;
172  return NO;
173}
174- (BOOL)isObjectPublic {
175  return self->isObjectPublic;
176}
177- (BOOL)isObjectPrivate {
178  return self->isObjectPrivate;
179}
180- (NSString *)permissionRequiredForObject {
181  return self->objectPermission;
182}
183
184- (void)declareObjectPublic {
185  if ([self->objectPermission isNotNull] || self->isObjectPrivate)
186    [self _logObjPermAlreadySet];
187  else {
188    [self debugWithFormat:@"declared object public"];
189    self->isObjectPublic = YES;
190  }
191}
192- (void)declareObjectPrivate {
193  if ([self->objectPermission isNotNull] || self->isObjectPublic)
194    [self _logObjPermAlreadySet];
195  else {
196    [self debugWithFormat:@"declared object private"];
197    self->isObjectPrivate = YES;
198  }
199}
200- (void)declareObjectProtected:(NSString *)_perm {
201  _perm = [_perm isNotNull] ? [_perm lowercaseString] : (NSString *)nil;
202
203  if ([_perm length] == 0) {
204    [self logWithFormat:@"tried to declare empty permission !", _perm];
205    return;
206  }
207
208  if (self->isObjectPrivate || self->isObjectPublic ||
209      (self->objectPermission != nil)) {
210    [self _logObjPermAlreadySet];
211  }
212  else {
213    [self debugWithFormat:@"declared object protected by: %@", _perm];
214    self->objectPermission = [_perm copy];
215  }
216}
217
218/* default role mappings */
219
220- (BOOL)hasDefaultRoleForPermission:(NSString *)_p {
221  if (_p == nil) return NO;
222  _p = [_p lowercaseString];
223  return [self->defRoles objectForKey:_p] == nil ? NO : YES;
224}
225
226- (void)declareRole:(NSString *)_role asDefaultForPermission:(NSString *)_per{
227  id tmp;
228
229  _per = [_per isNotNull] ? [_per lowercaseString] : (NSString *)nil;
230
231  if (self->defRoles == nil)
232    self->defRoles = [[NSMutableDictionary alloc] initWithCapacity:8];
233
234  if ((tmp = [self->defRoles objectForKey:_per])) {
235    [self warnWithFormat:@"tried to set default role of '%@' twice!"
236            @" (set to %@)", _per, tmp];
237    return;
238  }
239
240  tmp = [_role isNotNull] ? [NSArray arrayWithObject:_role] : [NSArray array];
241  [self->defRoles setObject:tmp forKey:_per];
242}
243- (void)declareRole:(NSString *)_role
244  asDefaultForPermissions:(NSString *)_p,...
245{
246  va_list va;
247  NSString *aperm;
248
249  va_start(va, _p);
250  for (aperm = _p; aperm != nil; aperm = va_arg(va, id)) {
251    [self declareRole:_role asDefaultForPermission:aperm];
252  }
253  va_end(va);
254}
255
256- (void)declareRoles:(NSArray *)_roles asDefaultForPermission:(NSString *)_p {
257  id tmp;
258
259  _p = [_p isNotNull] ? [_p lowercaseString] : (NSString *)nil;
260
261  if (self->defRoles == nil)
262    self->defRoles = [[NSMutableDictionary alloc] initWithCapacity:8];
263
264  if ((tmp = [self->defRoles objectForKey:_p])) {
265    [self warnWithFormat:@"tried to set default role of '%@' twice!"
266            @" (set to %@)", _p, tmp];
267    return;
268  }
269
270  tmp = [_roles isNotNull] ? _roles : (NSArray *)[NSArray array];
271  [self->defRoles setObject:tmp forKey:_p];
272}
273
274- (NSArray *)defaultViewRoles {
275  static NSArray *defViewRoles = nil;
276  if (defViewRoles == nil) {
277    defViewRoles = [[NSArray alloc] initWithObjects:
278				      @"Anonymous", @"Manager", nil];
279  }
280  return defViewRoles;
281}
282- (NSArray *)defaultContentsRoles {
283  static NSArray *defContentRoles = nil;
284  if (defContentRoles == nil) {
285    defContentRoles = [[NSArray alloc] initWithObjects:
286					 @"Anonymous", @"Manager", nil];
287  }
288  return defContentRoles;
289}
290- (NSArray *)defaultRoles {
291  static NSArray *defRolesA = nil;
292  if (defRolesA == nil)
293    defRolesA = [[NSArray alloc] initWithObjects:@"Manager", nil];
294  return defRolesA;
295}
296
297- (NSArray *)defaultRolesForPermission:(NSString *)_p {
298  NSArray *roles;
299
300  _p = [_p lowercaseString];
301
302  if ((roles = [self->defRoles objectForKey:_p]))
303    ;
304  else if ([_p isEqualToString:@"view"])
305    roles = [self defaultViewRoles];
306  else if ([_p isEqualToString:@"access contents information"])
307    roles = [self defaultContentsRoles];
308  else
309    roles = [self defaultRoles];
310
311  return roles;
312}
313
314@end /* SoClassSecurityInfo */
315
316@implementation SoClassSecurityInfo(Logging)
317
318- (NSString *)loggingPrefix {
319  return [self->className length] > 0
320    ? [NSString stringWithFormat:@"[so-secinfo %@]", self->className]
321    : [NSString stringWithFormat:@"[so-secinfo 0x%p]", self];
322}
323- (BOOL)isDebuggingEnabled {
324  static int debugOn = -1;
325  if (debugOn == -1) {
326    debugOn = [[NSUserDefaults standardUserDefaults]
327		boolForKey:@"SoLogSecurityDeclarations"] ? 1 : 0;
328  }
329  return debugOn ? YES : NO;
330}
331
332@end /* SoClassSecurityInfo(Logging) */
333