configure.ac: if neither boost nor tr1 is available, die right away.
[wvstreams.git] / uniconf / unisecuregen.cc
blob40a5dab47c6d6d2d618df83297768b4bdbcaf808
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"
16 WV_LINK(UniSecureGen);
19 static IUniConfGen *creator(WvStringParm s, IObject *)
21 return new UniSecureGen(s);
24 static WvMoniker<IUniConfGen> reg("perm", creator);
27 UniSecureGen::UniSecureGen(WvStringParm moniker, UniPermGen *_perms)
28 : UniFilterGen(NULL)
30 WvString mainmon(moniker), permmon;
32 if (!_perms)
34 WvConstInPlaceBuf buf(moniker, moniker.len());
35 permmon = wvtcl_getword(buf);
36 mainmon = wvtcl_getword(buf);
38 IUniConfGen *_perms = wvcreate<IUniConfGen>(permmon);
39 assert(_perms);
40 perms = new UniPermGen(_perms);
41 perms->refresh();
44 IUniConfGen *main = wvcreate<IUniConfGen>(mainmon);
45 setinner(main);
49 UniSecureGen::UniSecureGen(IUniConfGen *_gen, UniPermGen *_perms)
50 : UniFilterGen(_gen)
52 assert(_perms);
53 perms = _perms;
54 perms->refresh();
58 void UniSecureGen::setcredentials(const UniPermGen::Credentials &_cred)
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);
68 void UniSecureGen::setcredentials(WvStringParm user, const WvStringList &groups)
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);
78 bool UniSecureGen::refresh()
80 perms->refresh();
81 return UniFilterGen::refresh();
85 void UniSecureGen::commit()
87 perms->commit();
88 UniFilterGen::commit();
92 WvString UniSecureGen::get(const UniConfKey &key)
94 if (findperm(key, UniPermGen::READ))
96 WvString val = UniFilterGen::get(key);
97 return val;
100 return WvString::null;
104 bool UniSecureGen::exists(const UniConfKey &key)
106 if (findperm(key.removelast(), UniPermGen::EXEC))
107 return UniFilterGen::exists(key);
108 return false;
112 void UniSecureGen::set(const UniConfKey &key, WvStringParm value)
114 if (findperm(key, UniPermGen::WRITE))
115 UniFilterGen::set(key, value);
119 bool UniSecureGen::haschildren(const UniConfKey &key)
121 if (findperm(key, UniPermGen::EXEC))
122 return UniFilterGen::haschildren(key);
123 return false;
127 class _UniSecureIter : public UniConfGen::Iter
129 UniFilterGen::Iter *it;
130 UniSecureGen *gen;
131 UniConfKey subpath;
133 public:
134 _UniSecureIter(UniFilterGen::Iter *_it, UniSecureGen *_gen, UniConfKey _subpath) :
135 it(_it),
136 gen(_gen),
137 subpath(_subpath)
139 virtual ~_UniSecureIter()
140 { delete it; }
142 virtual void rewind()
143 { it->rewind(); }
145 virtual bool next()
146 { return it->next(); }
148 virtual UniConfKey key() const
149 { return it->key(); } // if we've come this far, this is ok
151 virtual WvString value() const
153 UniConfKey realkey = it->key();
154 realkey.prepend(subpath);
155 return gen->get(realkey);
160 UniConfGen::Iter *UniSecureGen::iterator(const UniConfKey &key)
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);
169 return NULL;
173 UniConfGen::Iter *UniSecureGen::recursiveiterator(const UniConfKey &key)
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);
185 return NULL;
189 void UniSecureGen::gencallback(const UniConfKey &key, WvStringParm value)
191 if (findperm(key, UniPermGen::READ))
192 delta(key, value);
196 bool UniSecureGen::findperm(const UniConfKey &key, UniPermGen::Type type)
198 if (!drilldown(key))
199 return false;
200 else
201 return perms->getperm(key, cred, type);
205 bool UniSecureGen::drilldown(const UniConfKey &key)
207 UniConfKey check;
208 UniConfKey left = key;
210 while (!left.isempty())
212 // check the exec perm
213 if (!perms->getperm(check, cred, UniPermGen::EXEC))
214 return false;
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();
223 return true;