]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cache_manager.cc
- Separated raw HTTP headers from their "compiled" values. Squid is now
[thirdparty/squid.git] / src / cache_manager.cc
CommitLineData
22f3fd98 1
2/*
d8b249ef 3 * $Id: cache_manager.cc,v 1.10 1998/03/20 18:06:41 rousskov Exp $
22f3fd98 4 *
5 * DEBUG: section 16 Cache Manager Objects
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
31
32#include "squid.h"
33
34#define MGR_PASSWD_SZ 128
35
36typedef struct {
37 StoreEntry *entry;
38 char *action;
63259c34 39 char *user_name;
22f3fd98 40 char *passwd;
41} cachemgrStateData;
42
43typedef struct _action_table {
44 char *action;
45 char *desc;
46 OBJH *handler;
47 int pw_req_flag;
48 struct _action_table *next;
49} action_table;
50
2ac76861 51static action_table *cachemgrFindAction(const char *action);
63259c34 52static cachemgrStateData *cachemgrParseUrl(const char *url);
2ac76861 53static void cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request);
22f3fd98 54static int cachemgrCheckPassword(cachemgrStateData *);
2ac76861 55static void cachemgrStateFree(cachemgrStateData * mgr);
22f3fd98 56static char *cachemgrPasswdGet(cachemgr_passwd *, const char *);
2ac76861 57static const char *cachemgrActionProtection(const action_table * at);
22f3fd98 58static OBJH cachemgrShutdown;
59static OBJH cachemgrMenu;
60
61action_table *ActionTable = NULL;
62
63void
64cachemgrRegister(const char *action, const char *desc, OBJH * handler, int pw_req_flag)
65{
66 action_table *a;
67 action_table **A;
e45867bd 68 if (cachemgrFindAction(action) != NULL) {
2ac76861 69 debug(16, 3) ("cachemgrRegister: Duplicate '%s'\n", action);
e45867bd 70 return;
71 }
22f3fd98 72 a = xcalloc(1, sizeof(action_table));
73 a->action = xstrdup(action);
74 a->desc = xstrdup(desc);
75 a->handler = handler;
76 a->pw_req_flag = pw_req_flag;
77 for (A = &ActionTable; *A; A = &(*A)->next);
78 *A = a;
2ac76861 79 debug(16, 3) ("cachemgrRegister: registered %s\n", action);
22f3fd98 80}
81
82static action_table *
83cachemgrFindAction(const char *action)
84{
85 action_table *a;
86 for (a = ActionTable; a != NULL; a = a->next) {
87 if (0 == strcmp(a->action, action))
88 return a;
89 }
90 return NULL;
91}
92
93static cachemgrStateData *
63259c34 94cachemgrParseUrl(const char *url)
22f3fd98 95{
96 int t;
97 LOCAL_ARRAY(char, host, MAX_URL);
98 LOCAL_ARRAY(char, request, MAX_URL);
99 LOCAL_ARRAY(char, password, MAX_URL);
100 action_table *a;
101 cachemgrStateData *mgr = NULL;
7395afb8 102 const char *prot;
22f3fd98 103 t = sscanf(url, "cache_object://%[^/]/%[^@]@%s", host, request, password);
104 if (t < 2) {
105 xstrncpy(request, "menu", MAX_URL);
106 } else if ((a = cachemgrFindAction(request)) == NULL) {
63259c34 107 debug(16, 0) ("cachemgrParseUrl: action '%s' not found\n", request);
22f3fd98 108 return NULL;
7395afb8 109 } else {
2ac76861 110 prot = cachemgrActionProtection(a);
7395afb8 111 if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden")) {
112 debug(16, 0) ("cachemgrParseUrl: action '%s' is %s\n", request, prot);
113 return NULL;
114 }
22f3fd98 115 }
63259c34 116 /* set absent entries to NULL so we can test if they are present later */
22f3fd98 117 mgr = xcalloc(1, sizeof(cachemgrStateData));
63259c34 118 mgr->user_name = NULL;
119 mgr->passwd = t == 3 ? xstrdup(password) : NULL;
22f3fd98 120 mgr->action = xstrdup(request);
121 return mgr;
122}
123
63259c34 124static void
2ac76861 125cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request)
63259c34 126{
2ac76861 127 const char *basic_cookie; /* base 64 _decoded_ user:passwd pair */
63259c34 128 const char *authField;
129 const char *passwd_del;
130 assert(mgr && request);
131 /* this parsing will go away when hdrs are added to request_t @?@ */
132 basic_cookie = mime_get_auth(request->headers, "Basic", &authField);
2ac76861 133 debug(16, 9) ("cachemgrParseHeaders: got auth: '%s'\n", authField ? authField : "<none>");
63259c34 134 if (!authField)
135 return;
136 if (!basic_cookie) {
137 debug(16, 1) ("cachemgrParseHeaders: unknown auth format in '%s'\n", authField);
138 return;
139 }
140 if (!(passwd_del = strchr(basic_cookie, ':'))) {
141 debug(16, 1) ("cachemgrParseHeaders: unknown basic_cookie '%s' format in '%s'\n", basic_cookie, authField);
142 return;
143 }
144 /* found user:password pair, reset old values */
145 safe_free(mgr->user_name);
146 safe_free(mgr->passwd);
2ac76861 147 mgr->user_name = xstrdup(basic_cookie);
63259c34 148 mgr->user_name[passwd_del - basic_cookie] = '\0';
2ac76861 149 mgr->passwd = xstrdup(passwd_del + 1);
63259c34 150 /* warning: this prints decoded password which maybe not what you want to do @?@ @?@ */
2ac76861 151 debug(16, 9) ("cachemgrParseHeaders: got user: '%s' passwd: '%s'\n", mgr->user_name, mgr->passwd);
63259c34 152}
153
22f3fd98 154/*
155 * return 0 if mgr->password is good
156 */
157static int
158cachemgrCheckPassword(cachemgrStateData * mgr)
159{
160 char *pwd = cachemgrPasswdGet(Config.passwd_list, mgr->action);
161 action_table *a = cachemgrFindAction(mgr->action);
162 assert(a != NULL);
163 if (pwd == NULL)
164 return a->pw_req_flag;
165 if (strcmp(pwd, "disable") == 0)
166 return 1;
167 if (strcmp(pwd, "none") == 0)
168 return 0;
63259c34 169 if (!mgr->passwd)
170 return 1;
22f3fd98 171 return strcmp(pwd, mgr->passwd);
172}
173
174static void
2ac76861 175cachemgrStateFree(cachemgrStateData * mgr)
22f3fd98 176{
2ac76861 177 safe_free(mgr->action);
178 safe_free(mgr->user_name);
179 safe_free(mgr->passwd);
b771e69f 180 storeUnlockObject(mgr->entry);
2ac76861 181 xfree(mgr);
22f3fd98 182}
183
184void
2ac76861 185cachemgrStart(int fd, request_t * request, StoreEntry * entry)
22f3fd98 186{
187 cachemgrStateData *mgr = NULL;
188 ErrorState *err = NULL;
22f3fd98 189 action_table *a;
190 debug(16, 3) ("objectcacheStart: '%s'\n", storeUrl(entry));
63259c34 191 if ((mgr = cachemgrParseUrl(storeUrl(entry))) == NULL) {
22f3fd98 192 err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND);
193 err->url = xstrdup(storeUrl(entry));
194 errorAppendEntry(entry, err);
195 entry->expires = squid_curtime;
196 return;
197 }
198 mgr->entry = entry;
b771e69f 199 storeLockObject(entry);
22f3fd98 200 entry->expires = squid_curtime;
63259c34 201 debug(16, 5) ("CACHEMGR: %s requesting '%s'\n",
22f3fd98 202 fd_table[fd].ipaddr, mgr->action);
63259c34 203 /* get additional info from request headers */
204 cachemgrParseHeaders(mgr, request);
22f3fd98 205 /* Check password */
206 if (cachemgrCheckPassword(mgr) != 0) {
b771e69f 207 /* build error message */
208 ErrorState *err;
209 HttpReply *rep;
210 err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED);
211 /* warn if user specified incorrect password */
212 if (mgr->passwd)
213 debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n",
214 mgr->user_name ? mgr->user_name : "<unknown>",
215 fd_table[fd].ipaddr, mgr->action);
216 else
217 debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n",
218 mgr->user_name ? mgr->user_name : "<unknown>",
219 fd_table[fd].ipaddr, mgr->action);
220 err->request = requestLink(request);
221 rep = errorBuildReply(err);
222 errorStateFree(err);
223 /*
224 * add Authenticate header, use 'action' as a realm because
225 * password depends on action
226 */
d8b249ef 227 httpHeaderPutAuth(&rep->header, "Basic", mgr->action);
b771e69f 228 /* move info to the mem_obj->reply */
229 httpReplyAbsorb(entry->mem_obj->reply, rep);
230 /* store the reply */
231 httpReplySwapOut(entry->mem_obj->reply, entry);
22f3fd98 232 entry->expires = squid_curtime;
233 storeComplete(entry);
b771e69f 234 cachemgrStateFree(mgr);
22f3fd98 235 return;
236 }
b771e69f 237 debug(16, 1) ("CACHEMGR: %s@%s requesting '%s'\n",
238 mgr->user_name ? mgr->user_name : "<unknown>",
239 fd_table[fd].ipaddr, mgr->action);
22f3fd98 240 /* retrieve object requested */
241 a = cachemgrFindAction(mgr->action);
242 assert(a != NULL);
243 storeBuffer(entry);
cb69b4c7 244 {
245 HttpReply *rep = httpReplyCreate();
b771e69f 246 httpReplySetHeaders(rep,
247 (double) 1.0,
248 HTTP_OK,
249 NULL,
250 "text/plain",
251 -1, /* C-Len */
252 squid_curtime, /* LMT */
253 squid_curtime);
cb69b4c7 254 httpReplySwapOut(rep, entry);
255 httpReplyDestroy(rep);
256 }
22f3fd98 257 a->handler(entry);
258 storeBufferFlush(entry);
259 storeComplete(entry);
260 cachemgrStateFree(mgr);
261}
262
263static void
264cachemgrShutdown(StoreEntry * entryunused)
265{
266 debug(16, 0) ("Shutdown by command.\n");
267 shut_down(0);
268}
269
7395afb8 270static const char *
2ac76861 271cachemgrActionProtection(const action_table * at)
7395afb8 272{
273 char *pwd;
274 assert(at);
275 pwd = cachemgrPasswdGet(Config.passwd_list, at->action);
276 if (!pwd)
277 return at->pw_req_flag ? "hidden" : "public";
278 if (!strcmp(pwd, "disable"))
279 return "disabled";
280 if (strcmp(pwd, "none") == 0)
281 return "public";
282 return "protected";
283}
284
22f3fd98 285static void
2ac76861 286cachemgrMenu(StoreEntry * sentry)
22f3fd98 287{
7395afb8 288 action_table *a;
289 for (a = ActionTable; a != NULL; a = a->next) {
290 storeAppendPrintf(sentry, " %-22s\t%s\t%s\n",
291 a->action, a->desc, cachemgrActionProtection(a));
292 }
22f3fd98 293}
294
295static char *
296cachemgrPasswdGet(cachemgr_passwd * a, const char *action)
297{
298 wordlist *w;
299 while (a != NULL) {
300 for (w = a->actions; w != NULL; w = w->next) {
301 if (0 == strcmp(w->key, action))
302 return a->passwd;
303 if (0 == strcmp(w->key, "all"))
304 return a->passwd;
305 }
306 a = a->next;
307 }
308 return NULL;
309}
310
311void
312cachemgrInit(void)
313{
314 cachemgrRegister("menu",
315 "This Cachemanager Menu",
316 cachemgrMenu, 0);
317 cachemgrRegister("shutdown",
318 "Shut Down the Squid Process",
319 cachemgrShutdown, 1);
320}