2 * Worldvisions Weaver Software:
3 * Copyright (C) 2002 Net Integration Technologies, Inc.
5 * UniSecureGen is a UniConfGen for checking permissions before allowing
6 * access to a UniConf tree. See unisecuregen.h and unipermgen.h.
8 #include "unisecuregen.h"
10 #include "wvstringlist.h"
11 #include "wvtclstring.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
)
30 WvString
mainmon(moniker
), permmon
;
34 WvConstInPlaceBuf
buf(moniker
, moniker
.len());
35 permmon
= wvtcl_getword(buf
);
36 mainmon
= wvtcl_getword(buf
);
38 IUniConfGen
*_perms
= wvcreate
<IUniConfGen
>(permmon
);
40 perms
= new UniPermGen(_perms
);
44 IUniConfGen
*main
= wvcreate
<IUniConfGen
>(mainmon
);
49 UniSecureGen::UniSecureGen(IUniConfGen
*_gen
, UniPermGen
*_perms
)
58 void UniSecureGen::setcredentials(const UniPermGen::Credentials
&_cred
)
60 cred
.user
= _cred
.user
;
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
)
72 WvStringList::Iter
i(groups
);
73 for (i
.rewind(); i
.next(); )
74 cred
.groups
.add(new WvString(*i
), true);
78 bool UniSecureGen::refresh()
81 return UniFilterGen::refresh();
85 void UniSecureGen::commit()
88 UniFilterGen::commit();
92 WvString
UniSecureGen::get(const UniConfKey
&key
)
94 if (findperm(key
, UniPermGen::READ
))
96 WvString val
= UniFilterGen::get(key
);
100 return WvString::null
;
104 bool UniSecureGen::exists(const UniConfKey
&key
)
106 if (findperm(key
.removelast(), UniPermGen::EXEC
))
107 return UniFilterGen::exists(key
);
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
);
127 class _UniSecureIter
: public UniConfGen::Iter
129 UniFilterGen::Iter
*it
;
134 _UniSecureIter(UniFilterGen::Iter
*_it
, UniSecureGen
*_gen
, UniConfKey _subpath
) :
139 virtual ~_UniSecureIter()
142 virtual void rewind()
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
);
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
);
189 void UniSecureGen::gencallback(const UniConfKey
&key
, WvStringParm value
)
191 if (findperm(key
, UniPermGen::READ
))
196 bool UniSecureGen::findperm(const UniConfKey
&key
, UniPermGen::Type type
)
201 return perms
->getperm(key
, cred
, type
);
205 bool UniSecureGen::drilldown(const UniConfKey
&key
)
208 UniConfKey left
= key
;
210 while (!left
.isempty())
212 // check the exec perm
213 if (!perms
->getperm(check
, cred
, UniPermGen::EXEC
))
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();