]> git.ipfire.org Git - thirdparty/squid.git/blob - src/auth/AclMaxUserIp.cc
72dc1fe283ac99dcf1e7e183bdc8307264944e7e
[thirdparty/squid.git] / src / auth / AclMaxUserIp.cc
1 /*
2 * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 28 Access Control */
10
11 #include "squid.h"
12 #include "acl/FilledChecklist.h"
13 #include "auth/Acl.h"
14 #include "auth/AclMaxUserIp.h"
15 #include "auth/UserRequest.h"
16 #include "ConfigParser.h"
17 #include "Debug.h"
18 #include "Parsing.h"
19 #include "wordlist.h"
20
21 ACLMaxUserIP::ACLMaxUserIP(char const *theClass) :
22 class_(theClass),
23 maximum(0)
24 {}
25
26 ACL *
27 ACLMaxUserIP::clone() const
28 {
29 return new ACLMaxUserIP(*this);
30 }
31
32 char const *
33 ACLMaxUserIP::typeString() const
34 {
35 return class_;
36 }
37
38 bool
39 ACLMaxUserIP::empty() const
40 {
41 return false;
42 }
43
44 bool
45 ACLMaxUserIP::valid() const
46 {
47 return maximum > 0;
48 }
49
50 const Acl::Options &
51 ACLMaxUserIP::options()
52 {
53 static const Acl::BooleanOption BeStrict;
54 static const Acl::Options MyOptions = { { "-s", &BeStrict } };
55 BeStrict.linkWith(&beStrict);
56 return MyOptions;
57 }
58
59 void
60 ACLMaxUserIP::parse()
61 {
62 if (maximum) {
63 debugs(28, DBG_IMPORTANT, "Attempting to alter already set User max IP acl");
64 return;
65 }
66
67 char *t = ConfigParser::strtokFile();
68
69 if (!t)
70 return;
71
72 debugs(28, 5, "aclParseUserMaxIP: First token is " << t);
73
74 maximum = xatoi(t);
75
76 debugs(28, 5, "aclParseUserMaxIP: Max IP address's " << maximum);
77
78 return;
79 }
80
81 /*
82 * aclMatchUserMaxIP - check for users logging in from multiple IP's
83 * 0 : No match
84 * 1 : Match
85 */
86 int
87 ACLMaxUserIP::match(Auth::UserRequest::Pointer auth_user_request, Ip::Address const &src_addr)
88 {
89 /*
90 * the logic for flush the ip list when the limit is hit vs keep
91 * it sorted in most recent access order and just drop the oldest
92 * one off is currently undecided (RBC)
93 */
94
95 if (authenticateAuthUserRequestIPCount(auth_user_request) <= maximum)
96 return 0;
97
98 debugs(28, DBG_IMPORTANT, "aclMatchUserMaxIP: user '" << auth_user_request->username() << "' tries to use too many IP addresses (max " << maximum << " allowed)!");
99
100 /* this is a match */
101 if (beStrict) {
102 /*
103 * simply deny access - the user name is already associated with
104 * the request
105 */
106 /* remove _this_ ip, as it is the culprit for going over the limit */
107 authenticateAuthUserRequestRemoveIp(auth_user_request, src_addr);
108 debugs(28, 4, "aclMatchUserMaxIP: Denying access in strict mode");
109 } else {
110 /*
111 * non-strict - remove some/all of the cached entries
112 * ie to allow the user to move machines easily
113 */
114 authenticateAuthUserRequestClearIp(auth_user_request);
115 debugs(28, 4, "aclMatchUserMaxIP: Denying access in non-strict mode - flushing the user ip cache");
116 }
117
118 return 1;
119 }
120
121 int
122 ACLMaxUserIP::match(ACLChecklist *cl)
123 {
124 ACLFilledChecklist *checklist = Filled(cl);
125 allow_t answer = AuthenticateAcl(checklist);
126 int ti;
127
128 // convert to tri-state ACL match 1,0,-1
129 switch (answer) {
130 case ACCESS_ALLOWED:
131 // check for a match
132 ti = match(checklist->auth_user_request, checklist->src_addr);
133 checklist->auth_user_request = NULL;
134 return ti;
135
136 case ACCESS_DENIED:
137 return 0; // non-match
138
139 case ACCESS_DUNNO:
140 case ACCESS_AUTH_REQUIRED:
141 default:
142 // If the answer is not allowed or denied (matches/not matches) and
143 // async authentication is not in progress, then we are done.
144 if (checklist->keepMatching())
145 checklist->markFinished(answer, "AuthenticateAcl exception");
146 return -1; // other
147 }
148 }
149
150 SBufList
151 ACLMaxUserIP::dump() const
152 {
153 SBufList sl;
154 if (!maximum)
155 return sl;
156 SBuf s;
157 s.Printf("%d", maximum);
158 sl.push_back(s);
159 return sl;
160 }
161