00001 #include "util.h"
00002 #include "AccessList.h"
00003 #ifdef HAVE_SSTREAM
00004 #include <sstream>
00005 #else
00006 #include <strstream>
00007 #endif
00008
00009
00010 #include <algorithm>
00011
00012 using namespace std;
00013
00014 ostream & operator<<(ostream & os, const AccessEntry & ae)
00015 {
00016 #ifdef HAVE_SSTREAM
00017 stringstream sb;
00018 #else
00019 strstream sb;
00020 #endif
00021
00022 os << ae.hostname << '{' << endl;
00023 os << " access_flags=" << ae.access_flags << " (";
00024 ae.printAccessFlags(&os);
00025 os << ")"<< endl;
00026 os << " list=" << ae.list << endl;
00027 os << " read=" << ae.read << endl;
00028 os << " postto=" << ae.postTo << endl;
00029 ae.authentication.printParameters (&sb);
00030 os << " PAMServicename " << ae.PAMServicename << endl;
00031 string t = sb.str();
00032
00033 t.replace(0, 17, "");
00034 os << " authentication=" << t << endl;
00035 os << '}';
00036
00037 return os;
00038 }
00039
00040 #define STRN_EQ(x,y,l) (strncasecmp((x),(y),(l)) == 0)
00041 #define STRN_NE(x,y,l) (strncasecmp((x),(y),(l)) != 0)
00042 #define STR_EQ(x,y) (strcasecmp((x),(y)) == 0)
00043 #define STR_NE(x,y) (strcasecmp((x),(y)) != 0)
00044
00045
00046 #define NOT_INADDR(s) (s[strspn(s,"01234567890./")] != 0)
00047
00048 int in_domain(const char *name, const char *domain)
00049 {
00050 int name_len = strlen(name);
00051 int domain_len = strlen(domain);
00052
00053 if (domain[domain_len - 1] == '.') {
00054 return STRN_EQ(name, domain, domain_len);
00055 } else if (domain[0] == '.') {
00056 int n = name_len - domain_len;
00057 return n > 0 && STR_EQ(name + n, domain);
00058 } else {
00059 return STR_EQ(name, domain);
00060 }
00061 }
00062
00063 int matchaddress(const char *pattern,
00064 const char *name, const struct in_addr &host_addr)
00065 {
00066 const char *p = pattern;
00067
00068 while (*p && *p != '/')
00069 ++p;
00070
00071 if (*p) {
00072 string net(pattern, p - pattern);
00073 string mask(p + 1);
00074
00075 struct in_addr net_addr, mask_addr;
00076 if (!inet_aton(net.c_str(), &net_addr))
00077 return 0;
00078 if (!inet_aton(mask.c_str(), &mask_addr))
00079 return 0;
00080
00081 return (host_addr.s_addr & mask_addr.s_addr) ==
00082 net_addr.s_addr;
00083 } else {
00084 return NOT_INADDR(name) && in_domain(name, pattern);
00085 }
00086 }
00087
00088 AccessEntry *AccessList::client(const char *name, struct in_addr addr)
00089 {
00090 std::vector < AccessEntry >::iterator begin = vector.begin(), end =
00091 vector.end();
00092
00093 while (begin != end) {
00094 if (matchaddress(begin->hostname, name, addr) ||
00095 begin->hostname[0] == '\0') {
00096 return &(*begin);
00097 }
00098 ++begin;
00099 }
00100 return NULL;
00101 }
00102
00103 void AccessList::read(Lexer & lex)
00104 {
00105 string tok, host, port;
00106 int default_found = 0;
00107 tok = lex.getToken();
00108 if (tok != "{")
00109 throw SyntaxError(lex, "expected '{'", ERROR_LOCATION);
00110 for (;;) {
00111 tok = lex.getToken();
00112 if (tok == "Client") {
00113 host = lex.getToken();
00114
00115 readClient(lex, host.c_str());
00116 } else if (tok == "Default") {
00117 readClient(lex, "");
00118 default_found++;
00119 } else if (tok == "}") {
00120 break;
00121 } else {
00122 throw SyntaxError(lex,
00123 "expected declaration or '}'",
00124 ERROR_LOCATION);
00125 }
00126 }
00127 if (!default_found)
00128 throw SyntaxError(lex,
00129 "'Default' entry not found in NewsClientList",
00130 ERROR_LOCATION);
00131 }
00132
00133 #define ACCESSLIST_SET_FILTERS \
00134 if (!(filter_set&0x01)) cur.list=a1; \
00135 if (!(filter_set&0x02)) cur.read=a1; \
00136 if (!(filter_set&0x04)) cur.postTo=a1;
00137
00138 void AccessEntry::printParameters (ostream *pOut)
00139 {
00140 if (hostname[0] != '\0') {
00141 *pOut << "\tClient " << hostname << " {" << endl;
00142 } else {
00143 *pOut << "\tDefault {" << endl;
00144 }
00145 *pOut << "\t\tallow";
00146 printAccessFlags (pOut);
00147 *pOut << endl;
00148 if (list.getRulelist() != "") {
00149 *pOut << "\t\tList " << list.getRulelist() << endl;
00150 }
00151 if (read.getRulelist() != "") {
00152 *pOut << "\t\tRead " << read.getRulelist() << endl;
00153 }
00154 if (postTo.getRulelist() != "") {
00155 *pOut << "\t\tPostTo " << postTo.getRulelist() << endl;
00156 }
00157 authentication.printParameters (pOut);
00158 *pOut << "\t\tPAMServicename " << PAMServicename << endl;
00159 *pOut << "\t}" << endl;
00160 }
00161
00162 void AccessEntry::modifyAccessFlags (const string &flags)
00163 {
00164 string t;
00165 string::size_type i=0, j;
00166
00167 if (flags.length() == 0) {
00168 return;
00169 }
00170
00171 do {
00172 if ((j=flags.find (",", i)) == string::npos) {
00173 j=flags.length();
00174 }
00175 t = flags.substr (i, j-i);
00176 slog.p(Logger::Debug) << "j: " << (unsigned int)j << " flags: "
00177 << flags << " t: " << t << "\t";
00178 if (t == "read") {
00179 access_flags |= af_read;
00180 } else if (t == "!read") {
00181 access_flags |= ~af_read;
00182 } else if (t == "post") {
00183 access_flags |= af_post;
00184 } else if (t == "!post") {
00185 access_flags |= ~af_post;
00186 } else if (t == "debug") {
00187 access_flags |= af_debug;
00188 } else if (t == "!debug") {
00189 access_flags |= ~af_debug;
00190 }
00191 i=++j;
00192 } while (j<flags.length());
00193
00194 }
00195
00196
00197 void AccessList::readClient(Lexer & lex, const char *address)
00198 {
00199 string tok, a1, a2, a3;
00200 int filter_set = 0;
00201 AccessEntry cur;
00202 strcpy(cur.hostname, address);
00203
00204 tok = lex.getToken();
00205 if (tok != "{")
00206 throw SyntaxError(lex, "expected '{'", ERROR_LOCATION);
00207 for (;;) {
00208 tok = lex.getToken();
00209 if (tok == "allow") {
00210 for (;;) {
00211 a1 = lex.getToken();
00212 if (a1 == "read")
00213 cur.access_flags |=
00214 AccessEntry::af_read;
00215 else if (a1 == "post")
00216 cur.access_flags |=
00217 AccessEntry::af_post;
00218 else if (a1 == "debug")
00219 cur.access_flags |=
00220 AccessEntry::af_debug;
00221 else if (a1 == "authentication")
00222 cur.access_flags |=
00223 AccessEntry::af_authentication;
00224 else if (a1 == "none")
00225 cur.access_flags = 0x0;
00226 else
00227 break;
00228 }
00229 lex.putbackToken(a1);
00230 } else if (tok == "List") {
00231 a1 = lex.getToken();
00232 cur.list = a1;
00233 filter_set |= 0x01;
00234 ACCESSLIST_SET_FILTERS;
00235 } else if (tok == "Read") {
00236 cur.read = a1 = lex.getToken();
00237 filter_set |= 0x02;
00238 ACCESSLIST_SET_FILTERS;
00239 } else if (tok == "PostTo") {
00240 cur.postTo = a1 = lex.getToken();
00241 filter_set |= 0x04;
00242 ACCESSLIST_SET_FILTERS;
00243 } else if (tok == "Authentication") {
00244 string t = lex.getToken();
00245 cur.authentication.set (t);
00246 } else if (tok == "PAMServicename") {
00247 cur.PAMServicename = lex.getToken();
00248 } else if (tok == "}") {
00249 break;
00250 } else {
00251 throw SyntaxError(lex,
00252 "expected declaration or '}'",
00253 ERROR_LOCATION);
00254 }
00255 }
00256
00257 vector.push_back(cur);
00258 }
00259
00260 void AccessList::printParameters (std::ostream *pOut)
00261 {
00262 std::vector<AccessEntry>::iterator begin, end;
00263
00264 *pOut << "AccessList {" << endl;
00265
00266 for (begin=vector.begin(), end=vector.end();
00267 begin != end; begin++) {
00268 begin->printParameters (pOut);
00269 }
00270
00271 *pOut << "}" << endl;
00272 }
00273
00274 void Authentication::set (const string &AuthString)
00275 {
00276 string::size_type beg=0, end=0;
00277
00278 fields.clear();
00279
00280 if (AuthString.length() == 0) {
00281 return;
00282 }
00283
00284 do {
00285 if ((end=AuthString.find(":",beg)) == string::npos) {
00286 end=AuthString.length();
00287 }
00288 if (end>beg) {
00289 fields.push_back (AuthString.substr(beg, end-beg));
00290 } else {
00291 fields.push_back (string(""));
00292 }
00293 beg=++end;
00294 } while (end<AuthString.length());
00295
00296
00297 if (AuthString[AuthString.length()-1] == ':') {
00298 fields.push_back (string(""));
00299 }
00300 }
00301
00302 void Authentication::printParameters (ostream *pOut) const
00303 {
00304 int i,e=fields.size();
00305
00306 if (e == 0) {
00307 return;
00308 }
00309
00310 for (i=0; i<e; i++) {
00311 if (i==0) {
00312 *pOut << "\t\tAuthentication ";
00313 } else {
00314 *pOut << ":";
00315 }
00316 *pOut << fields[i];
00317 }
00318 *pOut << endl;
00319 }
00320
00321 void Authentication::modify (unsigned int start, Authentication &source)
00322 {
00323 unsigned int i;
00324 vector<string>::iterator sp, se;
00325 vector<string>::iterator dp, de;
00326
00327 sp = source.fields.begin();
00328 se = source.fields.end();
00329 dp = fields.begin();
00330 de = fields.end();
00331
00332 for (i=0; sp != se && dp != de; i++) {
00333 if (dp == de) {
00334 if (i>=start)
00335 fields.push_back (*sp);
00336 sp++;
00337 } else if (sp == se) {
00338 if (i>=start)
00339 fields.push_back (string(""));
00340 dp++;
00341 } else {
00342 if (i>=start)
00343 (*dp) += (*sp);
00344 sp++; dp++;
00345 }
00346 }
00347 }
00348
00349 int Authentication::typeEqual (const string &v)
00350 {
00351 const char *s = fields[0].c_str();
00352 const char *p = v.c_str();
00353
00354 while (*s!='\0') {
00355 if (*p=='\0')
00356 return -1;
00357 if (*s!=*p)
00358 return -1;
00359 s++; p++;
00360 }
00361 if (*p=='\0' || *p==':')
00362 return 0;
00363 else
00364 return -1;
00365
00366 }