Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

AccessList.cc

Go to the documentation of this file.
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         // replace \t\tAuthentication with ""
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] == '.') {    /* prefix */
00054                 return STRN_EQ(name, domain, domain_len);
00055         } else if (domain[0] == '.') {  /* suffix */
00056                 int n = name_len - domain_len;
00057                 return n > 0 && STR_EQ(name + n, domain);
00058         } else {                /* exact match */
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 {                /* anything 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                         //port=lex.getToken();
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         // empty field at the end of AuthString?
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 }

Generated on Sun Oct 24 21:08:17 2004 for NewsCache by doxygen 1.3.6-20040222