]>
Commit | Line | Data |
---|---|---|
48071869 | 1 | /* |
48071869 | 2 | * DEBUG: section 28 Access Control |
3 | * AUTHOR: Duane Wessels | |
48071869 | 4 | */ |
5 | ||
582c2af2 | 6 | #include "squid.h" |
c0941a6a AR |
7 | #include "acl/FilledChecklist.h" |
8 | #include "auth/Acl.h" | |
9 | #include "auth/AclMaxUserIp.h" | |
2d2b0bb7 | 10 | #include "auth/UserRequest.h" |
582c2af2 | 11 | #include "Debug.h" |
d295d770 | 12 | #include "wordlist.h" |
13 | #include "ConfigParser.h" | |
8a01b99e | 14 | #include "Parsing.h" |
48071869 | 15 | |
48071869 | 16 | ACL * |
17 | ACLMaxUserIP::clone() const | |
18 | { | |
19 | return new ACLMaxUserIP(*this); | |
20 | } | |
21 | ||
d295d770 | 22 | ACLMaxUserIP::ACLMaxUserIP (char const *theClass) : class_ (theClass), maximum(0) |
48071869 | 23 | {} |
24 | ||
a748a390 | 25 | ACLMaxUserIP::ACLMaxUserIP (ACLMaxUserIP const & old) :class_ (old.class_), maximum (old.maximum), flags (old.flags) |
48071869 | 26 | {} |
27 | ||
48071869 | 28 | ACLMaxUserIP::~ACLMaxUserIP() |
29 | {} | |
30 | ||
31 | char const * | |
32 | ACLMaxUserIP::typeString() const | |
33 | { | |
34 | return class_; | |
35 | } | |
36 | ||
4b0f5de8 | 37 | bool |
38 | ACLMaxUserIP::empty () const | |
39 | { | |
40 | return false; | |
41 | } | |
42 | ||
48071869 | 43 | bool |
44 | ACLMaxUserIP::valid () const | |
45 | { | |
4b0f5de8 | 46 | return maximum > 0; |
48071869 | 47 | } |
48 | ||
49 | void | |
50 | ACLMaxUserIP::parse() | |
51 | { | |
a748a390 | 52 | if (maximum) { |
e0236918 | 53 | debugs(28, DBG_IMPORTANT, "Attempting to alter already set User max IP acl"); |
48071869 | 54 | return; |
55 | } | |
56 | ||
d295d770 | 57 | char *t = ConfigParser::strtokFile(); |
48071869 | 58 | |
59 | if (!t) | |
4b0f5de8 | 60 | return; |
48071869 | 61 | |
bf8fe701 | 62 | debugs(28, 5, "aclParseUserMaxIP: First token is " << t); |
48071869 | 63 | |
64 | if (strcmp("-s", t) == 0) { | |
bf8fe701 | 65 | debugs(28, 5, "aclParseUserMaxIP: Going strict"); |
3dd52a0b | 66 | flags.strict = true; |
d295d770 | 67 | t = ConfigParser::strtokFile(); |
48071869 | 68 | } |
69 | ||
70 | if (!t) | |
4b0f5de8 | 71 | return; |
48071869 | 72 | |
0e656b69 | 73 | maximum = xatoi(t); |
48071869 | 74 | |
4a7a3d56 | 75 | debugs(28, 5, "aclParseUserMaxIP: Max IP address's " << maximum); |
48071869 | 76 | |
77 | return; | |
78 | } | |
79 | ||
80 | /* | |
26ac0430 | 81 | * aclMatchUserMaxIP - check for users logging in from multiple IP's |
48071869 | 82 | * 0 : No match |
26ac0430 | 83 | * 1 : Match |
48071869 | 84 | */ |
85 | int | |
c7baff40 | 86 | ACLMaxUserIP::match(Auth::UserRequest::Pointer auth_user_request, Ip::Address const &src_addr) |
48071869 | 87 | { |
88 | /* | |
89 | * the logic for flush the ip list when the limit is hit vs keep | |
90 | * it sorted in most recent access order and just drop the oldest | |
91 | * one off is currently undecided (RBC) | |
92 | */ | |
93 | ||
a748a390 | 94 | if (authenticateAuthUserRequestIPCount(auth_user_request) <= maximum) |
48071869 | 95 | return 0; |
96 | ||
e0236918 | 97 | debugs(28, DBG_IMPORTANT, "aclMatchUserMaxIP: user '" << auth_user_request->username() << "' tries to use too many IP addresses (max " << maximum << " allowed)!"); |
3b2fd4ec | 98 | |
48071869 | 99 | /* this is a match */ |
26ac0430 | 100 | if (flags.strict) { |
48071869 | 101 | /* |
102 | * simply deny access - the user name is already associated with | |
26ac0430 | 103 | * the request |
48071869 | 104 | */ |
105 | /* remove _this_ ip, as it is the culprit for going over the limit */ | |
106 | authenticateAuthUserRequestRemoveIp(auth_user_request, src_addr); | |
bf8fe701 | 107 | debugs(28, 4, "aclMatchUserMaxIP: Denying access in strict mode"); |
26ac0430 | 108 | } else { |
48071869 | 109 | /* |
26ac0430 | 110 | * non-strict - remove some/all of the cached entries |
48071869 | 111 | * ie to allow the user to move machines easily |
112 | */ | |
113 | authenticateAuthUserRequestClearIp(auth_user_request); | |
bf8fe701 | 114 | debugs(28, 4, "aclMatchUserMaxIP: Denying access in non-strict mode - flushing the user ip cache"); |
48071869 | 115 | } |
116 | ||
117 | return 1; | |
118 | } | |
119 | ||
120 | int | |
c0941a6a | 121 | ACLMaxUserIP::match(ACLChecklist *cl) |
48071869 | 122 | { |
c0941a6a | 123 | ACLFilledChecklist *checklist = Filled(cl); |
ccec22f9 | 124 | allow_t answer = AuthenticateAcl(checklist); |
48071869 | 125 | int ti; |
126 | ||
ccec22f9 | 127 | // convert to tri-state ACL match 1,0,-1 |
9b831d57 | 128 | switch (answer) { |
ccec22f9 | 129 | case ACCESS_ALLOWED: |
ccec22f9 AJ |
130 | // check for a match |
131 | ti = match(checklist->auth_user_request, checklist->src_addr); | |
132 | checklist->auth_user_request = NULL; | |
48071869 | 133 | return ti; |
134 | ||
ccec22f9 | 135 | case ACCESS_DENIED: |
ccec22f9 | 136 | return 0; // non-match |
48071869 | 137 | |
ccec22f9 AJ |
138 | case ACCESS_DUNNO: |
139 | case ACCESS_AUTH_REQUIRED: | |
140 | default: | |
e0f7153c | 141 | // If the answer is not allowed or denied (matches/not matches) and |
6f58d7d7 AR |
142 | // async authentication is not in progress, then we are done. |
143 | if (checklist->keepMatching()) | |
e0f7153c | 144 | checklist->markFinished(answer, "AuthenticateAcl exception"); |
ccec22f9 AJ |
145 | return -1; // other |
146 | } | |
48071869 | 147 | } |
148 | ||
149 | wordlist * | |
150 | ACLMaxUserIP::dump() const | |
151 | { | |
a748a390 | 152 | if (!maximum) |
48071869 | 153 | return NULL; |
154 | ||
155 | wordlist *W = NULL; | |
156 | ||
157 | if (flags.strict) | |
158 | wordlistAdd(&W, "-s"); | |
159 | ||
160 | char buf[128]; | |
161 | ||
a748a390 | 162 | snprintf(buf, sizeof(buf), "%lu", (unsigned long int) maximum); |
48071869 | 163 | |
164 | wordlistAdd(&W, buf); | |
165 | ||
166 | return W; | |
167 | } |