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 
112 void UniSecureGen::set(const UniConfKey &key, WvStringParm value)
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 }
UniFilterGen::setinner
void setinner(IUniConfGen *inner)
Rebinds the inner generator and prepares its callback.
Definition: unifiltergen.cc:26
wvtcl_getword
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
UniConfKey::removefirst
UniConfKey removefirst(int n=1) const
Returns the path formed by removing the first n segments of this path.
Definition: uniconfkey.h:335
UniSecureGen::commit
virtual void commit()
Commits any changes.
Definition: unisecuregen.cc:85
UniPermGen::Credentials
Definition: unipermgen.h:38
UniFilterGen::set
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
Definition: unifiltergen.cc:93
wvtclstring.h
UniConfKey::removelast
UniConfKey removelast(int n=1) const
Returns the path formed by removing the last n segments of this path.
Definition: uniconfkey.h:346
_UniSecureIter::key
virtual UniConfKey key() const
Returns the current key.
Definition: unisecuregen.cc:148
UniSecureGen::haschildren
virtual bool haschildren(const UniConfKey &key)
Returns true if a key has children.
Definition: unisecuregen.cc:119
UniConfKey::prepend
void prepend(const UniConfKey &other)
Prepends a path to this path.
Definition: uniconfkey.cc:152
UniSecureGen::recursiveiterator
virtual Iter * recursiveiterator(const UniConfKey &key)
Like iterator(), but the returned iterator is recursive, that is, it will return children of the imme...
Definition: unisecuregen.cc:173
_UniSecureIter
Definition: unisecuregen.cc:127
UniConfGen::recursiveiterator
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
UniConfGen::Iter::key
virtual UniConfKey key() const =0
Returns the current key.
UniFilterGen::get
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
Definition: unifiltergen.cc:76
UniFilterGen::iterator
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
Definition: unifiltergen.cc:137
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
IUniConfGen
An abstract data container that backs a UniConf tree.
Definition: uniconfgen.h:39
UniSecureGen::get
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
Definition: unisecuregen.cc:92
UniPermGen
UniPermGen wraps a tree encoding Unix-style permissions, and provides an API for setting and checking...
Definition: unipermgen.h:26
UniConfKey
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
Definition: uniconfkey.h:38
WvMoniker
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
Definition: wvmoniker.h:61
_UniSecureIter::next
virtual bool next()
Seeks to the next element in the sequence.
Definition: unisecuregen.cc:145
UniConfKey::isempty
bool isempty() const
Returns true if this path has zero segments (also known as root).
Definition: uniconfkey.h:264
UniConfGen::delta
void delta(const UniConfKey &key, WvStringParm value)
Call this when a key's value or children have possibly changed.
Definition: uniconfgen.cc:77
IObject
Definition: IObject.h:65
UniConfKey::first
UniConfKey first(int n=1) const
Returns the path formed by the n first segments of this path.
Definition: uniconfkey.h:314
UniSecureGen
UniSecureGen wraps a given generator and checks permissions (using a Unix-style scheme) before respon...
Definition: unisecuregen.h:32
WvConstInPlaceBuf
The const in place raw memory buffer type.
Definition: wvbuf.h:187
UniConfGen::Iter::rewind
virtual void rewind()=0
Rewinds the iterator.
_UniSecureIter::value
virtual WvString value() const
Returns the value of the current key.
Definition: unisecuregen.cc:151
_UniSecureIter::rewind
virtual void rewind()
Rewinds the iterator.
Definition: unisecuregen.cc:142
UniSecureGen::iterator
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
Definition: unisecuregen.cc:160
UniConfGen::Iter::next
virtual bool next()=0
Seeks to the next element in the sequence.
UniFilterGen::exists
virtual bool exists(const UniConfKey &key)
Without fetching its value, returns true if a key exists.
Definition: unifiltergen.cc:108
UniFilterGen::refresh
virtual bool refresh()
Refreshes information about a key recursively.
Definition: unifiltergen.cc:59
WvStringList
This is a WvList of WvStrings, and is a really handy way to parse strings.
Definition: wvstringlist.h:27
UniFilterGen::commit
virtual void commit()
Commits any changes.
Definition: unifiltergen.cc:52
UniFilterGen::haschildren
virtual bool haschildren(const UniConfKey &key)
Returns true if a key has children.
Definition: unifiltergen.cc:118
UniSecureGen::exists
virtual bool exists(const UniConfKey &key)
Without fetching its value, returns true if a key exists.
Definition: unisecuregen.cc:104
UniConfKey::append
void append(const UniConfKey &other)
Appends a path to this path.
Definition: uniconfkey.cc:130
UniSecureGen::refresh
virtual bool refresh()
Refreshes information about a key recursively.
Definition: unisecuregen.cc:78
UniFilterGen
A UniConfGen that delegates all requests to an inner generator.
Definition: unifiltergen.h:17
UniSecureGen::set
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
Definition: unisecuregen.cc:112
UniConfGen::Iter
An abstract iterator over keys and values in a generator.
Definition: uniconfgen.h:323