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