WvStreams
unisecuregen.cc
1 /*
2  * Worldvisions Weaver Software:
3  * Copyright (C) 2002 Net Integration Technologies, Inc.
4  *
5  * UniSecureGen is a UniConfGen for checking permissions before allowing
6  * access to a UniConf tree. See unisecuregen.h and unipermgen.h.
7  */
8 #include "unisecuregen.h"
9 #include "wvmoniker.h"
10 #include "wvstringlist.h"
11 #include "wvtclstring.h"
12 #include "wvlog.h"
13 #include "wvbuf.h"
14 #include "wvlinkerhack.h"
15 
16 WV_LINK(UniSecureGen);
17 
18 
19 static IUniConfGen *creator(WvStringParm s, IObject *)
20 {
21  return new UniSecureGen(s);
22 }
23 
24 static WvMoniker<IUniConfGen> reg("perm", creator);
25 
26 
27 UniSecureGen::UniSecureGen(WvStringParm moniker, UniPermGen *_perms)
28  : UniFilterGen(NULL)
29 {
30  WvString mainmon(moniker), permmon;
31 
32  if (!_perms)
33  {
34  WvConstInPlaceBuf buf(moniker, moniker.len());
35  permmon = wvtcl_getword(buf);
36  mainmon = wvtcl_getword(buf);
37 
38  IUniConfGen *_perms = wvcreate<IUniConfGen>(permmon);
39  assert(_perms);
40  perms = new UniPermGen(_perms);
41  perms->refresh();
42  }
43 
44  IUniConfGen *main = wvcreate<IUniConfGen>(mainmon);
45  setinner(main);
46 }
47 
48 
49 UniSecureGen::UniSecureGen(IUniConfGen *_gen, UniPermGen *_perms)
50  : UniFilterGen(_gen)
51 {
52  assert(_perms);
53  perms = _perms;
54  perms->refresh();
55 }
56 
57 
58 void UniSecureGen::setcredentials(const UniPermGen::Credentials &_cred)
59 {
60  cred.user = _cred.user;
61  cred.groups.zap();
62  WvStringTable::Iter i(_cred.groups);
63  for (i.rewind(); i.next(); )
64  cred.groups.add(new WvString(*i), true);
65 }
66 
67 
68 void UniSecureGen::setcredentials(WvStringParm user, const WvStringList &groups)
69 {
70  cred.user = user;
71  cred.groups.zap();
72  WvStringList::Iter i(groups);
73  for (i.rewind(); i.next(); )
74  cred.groups.add(new WvString(*i), true);
75 }
76 
77 
79 {
80  perms->refresh();
81  return UniFilterGen::refresh();
82 }
83 
84 
86 {
87  perms->commit();
89 }
90 
91 
93 {
94  if (findperm(key, UniPermGen::READ))
95  {
96  WvString val = UniFilterGen::get(key);
97  return val;
98  }
99 
100  return WvString::null;
101 }
102 
103 
105 {
106  if (findperm(key.removelast(), UniPermGen::EXEC))
107  return UniFilterGen::exists(key);
108  return false;
109 }
110 
111 
113 {
114  if (findperm(key, UniPermGen::WRITE))
115  UniFilterGen::set(key, value);
116 }
117 
118 
120 {
121  if (findperm(key, UniPermGen::EXEC))
122  return UniFilterGen::haschildren(key);
123  return false;
124 }
125 
126 
128 {
129  UniFilterGen::Iter *it;
130  UniSecureGen *gen;
131  UniConfKey subpath;
132 
133 public:
135  it(_it),
136  gen(_gen),
137  subpath(_subpath)
138  { }
139  virtual ~_UniSecureIter()
140  { delete it; }
141 
142  virtual void rewind()
143  { it->rewind(); }
144 
145  virtual bool next()
146  { return it->next(); }
147 
148  virtual UniConfKey key() const
149  { return it->key(); } // if we've come this far, this is ok
150 
151  virtual WvString value() const
152  {
153  UniConfKey realkey = it->key();
154  realkey.prepend(subpath);
155  return gen->get(realkey);
156  }
157 };
158 
159 
161 {
162  // we don't check the permissions on keys returned by the iterator, but
163  // that's okay: since this iterator is non-recursive, and we've checked
164  // permissions on the parent key, we know we're allowed to at least read
165  // the *names* of all child keys (even if the value itself is unreadable)
166  if (findperm(key, UniPermGen::EXEC))
167  return new _UniSecureIter(UniFilterGen::iterator(key), this, key);
168 
169  return NULL;
170 }
171 
172 
174 {
175  // FIXME: this needs to check permissions on *every* key, not just the
176  // top one, so we'll cheat: use the default UniConfGen recursiveiterator
177  // instead, which just calls the non-recursive iterator recursively.
178  // This can be bad for performance, but not in any of the situations
179  // we currently need. (ie. security is usually done on the server side,
180  // but it's the client-to-server connection that needs a fast recursive
181  // iterator, so it'll be fine.)
182  if (findperm(key, UniPermGen::EXEC))
183  return UniConfGen::recursiveiterator(key);
184 
185  return NULL;
186 }
187 
188 
189 void UniSecureGen::gencallback(const UniConfKey &key, WvStringParm value)
190 {
191  if (findperm(key, UniPermGen::READ))
192  delta(key, value);
193 }
194 
195 
196 bool UniSecureGen::findperm(const UniConfKey &key, UniPermGen::Type type)
197 {
198  if (!drilldown(key))
199  return false;
200  else
201  return perms->getperm(key, cred, type);
202 }
203 
204 
205 bool UniSecureGen::drilldown(const UniConfKey &key)
206 {
207  UniConfKey check;
208  UniConfKey left = key;
209 
210  while (!left.isempty())
211  {
212  // check the exec perm
213  if (!perms->getperm(check, cred, UniPermGen::EXEC))
214  return false;
215 
216  // move the first segment of left to check
217  // note that when left is empty, we exit the loop before checking the
218  // last segment. That's on purpose: the last segment is the 'file'
219  // and we only need to check the 'directories'
220  check.append(left.first());
221  left = left.removefirst();
222  }
223  return true;
224 }
The basic interface which is included by all other XPLC interfaces and objects.
Definition: IObject.h:65
An abstract data container that backs a UniConf tree.
Definition: uniconfgen.h:40
An abstract iterator over keys and values in a generator.
Definition: uniconfgen.h:324
virtual bool next()=0
Seeks to the next element in the sequence.
virtual void rewind()=0
Rewinds the iterator.
virtual UniConfKey key() const =0
Returns the current key.
void delta(const UniConfKey &key, WvStringParm value)
Call this when a key's value or children have possibly changed.
Definition: uniconfgen.cc:77
virtual Iter * recursiveiterator(const UniConfKey &key)
Like iterator(), but the returned iterator is recursive, that is, it will return children of the imme...
Definition: uniconfgen.cc:260
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
Definition: uniconfkey.h:39
UniConfKey removefirst(int n=1) const
Returns the path formed by removing the first n segments of this path.
Definition: uniconfkey.h:335
UniConfKey removelast(int n=1) const
Returns the path formed by removing the last n segments of this path.
Definition: uniconfkey.h:346
void prepend(const UniConfKey &other)
Prepends a path to this path.
Definition: uniconfkey.cc:152
void append(const UniConfKey &other)
Appends a path to this path.
Definition: uniconfkey.cc:130
bool isempty() const
Returns true if this path has zero segments (also known as root).
Definition: uniconfkey.h:264
UniConfKey first(int n=1) const
Returns the path formed by the n first segments of this path.
Definition: uniconfkey.h:314
A UniConfGen that delegates all requests to an inner generator.
Definition: unifiltergen.h:18
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
Definition: unifiltergen.cc:93
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
Definition: unifiltergen.cc:76
virtual bool exists(const UniConfKey &key)
Without fetching its value, returns true if a key exists.
virtual bool refresh()
Refreshes information about a key recursively.
Definition: unifiltergen.cc:59
virtual void commit()
Commits any changes.
Definition: unifiltergen.cc:52
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
virtual bool haschildren(const UniConfKey &key)
Returns true if a key has children.
UniPermGen wraps a tree encoding Unix-style permissions, and provides an API for setting and checking...
Definition: unipermgen.h:27
UniSecureGen wraps a given generator and checks permissions (using a Unix-style scheme) before respon...
Definition: unisecuregen.h:33
virtual bool haschildren(const UniConfKey &key)
Returns true if a key has children.
virtual Iter * recursiveiterator(const UniConfKey &key)
Like iterator(), but the returned iterator is recursive, that is, it will return children of the imme...
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
virtual bool refresh()
Refreshes information about a key recursively.
Definition: unisecuregen.cc:78
virtual void commit()
Commits any changes.
Definition: unisecuregen.cc:85
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
Definition: unisecuregen.cc:92
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
virtual bool exists(const UniConfKey &key)
Without fetching its value, returns true if a key exists.
The const in place raw memory buffer type.
Definition: wvbuf.h:188
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition: wvstring.h:94
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
Definition: wvmoniker.h:62
This is a WvList of WvStrings, and is a really handy way to parse strings.
Definition: wvstringlist.h:28
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:330
virtual void rewind()
Rewinds the iterator.
virtual WvString value() const
Returns the value of the current key.
virtual UniConfKey key() const
Returns the current key.
virtual bool next()
Seeks to the next element in the sequence.
Functions to handle "tcl-style" strings and lists.
WvString wvtcl_getword(WvBuf &buf, const WvStringMask &splitchars=WVTCL_SPLITCHARS, bool do_unescape=true)
Get a single tcl word from an input buffer, and return the rest of the buffer untouched.
Definition: wvtclstring.cc:359