42
42
#include "SquidTime.h"
43
43
#include "wordlist.h"
46
/// \ingroup CacheManagerInternal
45
47
#define MGR_PASSWD_SZ 128
58
static CacheManagerAction *cachemgrFindAction(const char *action);
59
static cachemgrStateData *cachemgrParseUrl(const char *url);
60
static void cachemgrParseHeaders(cachemgrStateData * mgr, const HttpRequest * request);
61
static int cachemgrCheckPassword(cachemgrStateData *);
62
static void cachemgrStateFree(cachemgrStateData * mgr);
63
static char *cachemgrPasswdGet(cachemgr_passwd *, const char *);
64
static const char *cachemgrActionProtection(const CacheManagerAction * at);
65
static OBJH cachemgrShutdown;
66
static OBJH cachemgrReconfigure;
67
static OBJH cachemgrMenu;
68
static OBJH cachemgrOfflineToggle;
70
CacheManagerAction *ActionTable = NULL;
51
\ingroup CacheManagerInternals
52
* Constructor. Its purpose is to register internal commands
72
54
CacheManager::CacheManager()
74
registerAction("menu", "This Cachemanager Menu", cachemgrMenu, 0, 1);
75
registerAction("shutdown",
76
"Shut Down the Squid Process",
77
cachemgrShutdown, 1, 1);
78
registerAction("reconfigure",
79
"Reconfigure the Squid Process",
80
cachemgrReconfigure, 1, 1);
81
registerAction("offline_toggle",
82
"Toggle offline_mode setting",
83
cachemgrOfflineToggle, 1, 1);
56
registerAction(new OfflineToggleAction);
57
registerAction(new ShutdownAction);
58
registerAction(new ReconfigureAction);
59
registerAction(new MenuAction(this));
63
\ingroup CacheManagerAPI
64
* Registers a C-style action, which is implemented as a pointer to a function
65
* taking as argument a pointer to a StoreEntry and returning void.
66
* Implemented via CacheManagerActionLegacy.
87
69
CacheManager::registerAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic)
89
CacheManagerAction *a;
90
CacheManagerAction **A;
71
debugs(16, 3, "CacheManager::registerAction: registering legacy " << action);
72
registerAction(new CacheManagerActionLegacy(action,desc,pw_req_flag,atomic,handler));
76
\ingroup CacheManagerAPI
77
* Registers a C++-style action, via a poiner to a subclass of
78
* a CacheManagerAction object, whose run() method will be invoked when
79
* CacheManager identifies that the user has requested the action.
82
CacheManager::registerAction(CacheManagerAction *anAction)
84
char *action = anAction->action;
92
85
if (findAction(action) != NULL) {
93
debugs(16, 3, "CacheManager::registerAction: Duplicate '" << action << "'");
86
debugs(16, 2, "CacheManager::registerAction: Duplicate '" << action << "'. Skipping.");
97
90
assert (strstr (" ", action) == NULL);
98
a = (CacheManagerAction *)xcalloc(1, sizeof(CacheManagerAction));
99
a->action = xstrdup(action);
100
a->desc = xstrdup(desc);
101
a->handler = handler;
102
a->flags.pw_req = pw_req_flag;
103
a->flags.atomic = atomic;
105
for (A = &ActionTable; *A; A = &(*A)->next)
92
ActionsList += anAction;
110
94
debugs(16, 3, "CacheManager::registerAction: registered " << action);
99
\ingroup CacheManagerInternal
100
* Locates an action in the actions registry ActionsList.
101
\retval NULL if Action not found
102
\retval CacheManagerAction* if the action was found
113
104
CacheManagerAction *
114
105
CacheManager::findAction(char const * action)
116
return cachemgrFindAction(action);
119
static CacheManagerAction *
120
cachemgrFindAction(const char *action)
122
CacheManagerAction *a;
124
for (a = ActionTable; a != NULL; a = a->next) {
125
if (0 == strcmp(a->action, action))
107
CacheManagerActionList::iterator a;
109
debugs(16, 5, "CacheManager::findAction: looking for action " << action);
110
for ( a = ActionsList.begin(); a != ActionsList.end(); a++) {
111
if (0 == strcmp((*a)->action, action)) {
112
debugs(16, 6, " found");
117
debugs(16, 6, "Action not found.");
132
static cachemgrStateData *
133
cachemgrParseUrl(const char *url)
122
\ingroup CacheManagerInternal
123
* define whether the URL is a cache-manager URL and parse the action
124
* requested by the user. Checks via CacheManager::ActionProtection() that the
125
* item is accessible by the user.
126
\retval CacheManager::cachemgrStateData state object for the following handling
127
\retval NULL if the action can't be found or can't be accessed by the user
129
CacheManager::cachemgrStateData *
130
CacheManager::ParseUrl(const char *url)
136
133
LOCAL_ARRAY(char, host, MAX_URL);
204
207
mgr->passwd = xstrdup(passwd_del + 1);
206
209
/* warning: this prints decoded password which maybe not what you want to do @?@ @?@ */
207
debugs(16, 9, "cachemgrParseHeaders: got user: '" << mgr->user_name << "' passwd: '" << mgr->passwd << "'");
210
debugs(16, 9, "CacheManager::ParseHeaders: got user: '" << mgr->user_name << "' passwd: '" << mgr->passwd << "'");
211
* return 0 if mgr->password is good
214
\ingroup CacheManagerInternal
216
\retval 0 if mgr->password is good or "none"
217
\retval 1 if mgr->password is "disable"
218
\retval !0 if mgr->password does not match configured password
214
cachemgrCheckPassword(cachemgrStateData * mgr)
221
CacheManager::CheckPassword(cachemgrStateData * mgr)
216
char *pwd = cachemgrPasswdGet(Config.passwd_list, mgr->action);
217
CacheManagerAction *a = cachemgrFindAction(mgr->action);
223
char *pwd = PasswdGet(Config.passwd_list, mgr->action);
224
CacheManagerAction *a = findAction(mgr->action);
226
debugs(16, 4, "CacheManager::CheckPassword for action " << mgr->action);
218
227
assert(a != NULL);
256
\ingroup CacheManagerAPI
257
* Main entry point in the Cache Manager's activity. Gets called as part
258
* of the forward chain if the right URL is detected there. Initiates
259
* all needed internal work and renders the response.
246
cachemgrStart(int fd, HttpRequest * request, StoreEntry * entry)
262
CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry)
248
264
cachemgrStateData *mgr = NULL;
249
265
ErrorState *err = NULL;
250
266
CacheManagerAction *a;
251
debugs(16, 3, "objectcacheStart: '" << entry->url() << "'" );
267
debugs(16, 3, "CacheManager::Start: '" << entry->url() << "'" );
253
if ((mgr = cachemgrParseUrl(entry->url())) == NULL) {
269
if ((mgr = ParseUrl(entry->url())) == NULL) {
254
270
err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, request);
255
271
err->url = xstrdup(entry->url());
256
272
errorAppendEntry(entry, err);
261
277
mgr->entry = entry;
266
280
entry->expires = squid_curtime;
268
debugs(16, 5, "CACHEMGR: " << fd_table[fd].ipaddr << " requesting '" << mgr->action << "'");
282
debugs(16, 5, "CacheManager: " << fd_table[fd].ipaddr << " requesting '" << mgr->action << "'");
270
284
/* get additional info from request headers */
271
cachemgrParseHeaders(mgr, request);
285
ParseHeaders(mgr, request);
273
287
/* Check password */
275
if (cachemgrCheckPassword(mgr) != 0) {
289
if (CheckPassword(mgr) != 0) {
276
290
/* build error message */
291
ErrorState *errState;
279
err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED, request);
293
errState = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED, request);
280
294
/* warn if user specified incorrect password */
283
debugs(16, 1, "CACHEMGR: " <<
284
(mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
285
fd_table[fd].ipaddr << ": incorrect password for '" <<
297
debugs(16, DBG_IMPORTANT, "CacheManager: " <<
298
(mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
299
fd_table[fd].ipaddr << ": incorrect password for '" <<
286
300
mgr->action << "'" );
288
debugs(16, 1, "CACHEMGR: " <<
289
(mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
290
fd_table[fd].ipaddr << ": password needed for '" <<
302
debugs(16, DBG_IMPORTANT, "CacheManager: " <<
303
(mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
304
fd_table[fd].ipaddr << ": password needed for '" <<
291
305
mgr->action << "'" );
293
rep = errorBuildReply(err);
307
rep = errState->BuildHttpReply();
309
errorStateFree(errState);
298
312
* add Authenticate header, use 'action' as a realm because
308
322
entry->complete();
310
cachemgrStateFree(mgr);
315
debugs(16, 1, "CACHEMGR: " <<
316
(mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
317
fd_table[fd].ipaddr << " requesting '" <<
329
debugs(16, 2, "CacheManager: " <<
330
(mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
331
fd_table[fd].ipaddr << " requesting '" <<
318
332
mgr->action << "'" );
319
333
/* retrieve object requested */
320
a = cachemgrFindAction(mgr->action);
334
a = findAction(mgr->action);
321
335
assert(a != NULL);
326
HttpVersion version(1,0);
327
340
HttpReply *rep = new HttpReply;
328
rep->setHeaders(version,
333
squid_curtime, /* LMT */
341
rep->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime);
335
342
entry->replaceHttpReply(rep);
342
349
if (a->flags.atomic)
343
350
entry->complete();
345
cachemgrStateFree(mgr);
349
cachemgrShutdown(StoreEntry * entryunused)
355
/// \ingroup CacheManagerInternal
356
void CacheManager::ShutdownAction::run(StoreEntry *sentry)
351
debugs(16, 0, "Shutdown by command.");
358
debugs(16, DBG_CRITICAL, "Shutdown by Cache Manager command.");
361
/// \ingroup CacheManagerInternal
362
CacheManager::ShutdownAction::ShutdownAction() : CacheManagerAction("shutdown","Shut Down the Squid Process", 1, 1) { }
356
cachemgrReconfigure(StoreEntry * sentry)
364
/// \ingroup CacheManagerInternal
366
CacheManager::ReconfigureAction::run(StoreEntry * sentry)
358
debug(16, 0) ("Reconfigure by command.\n");
368
debugs(16, DBG_IMPORTANT, "Reconfigure by Cache Manager command.");
359
369
storeAppendPrintf(sentry, "Reconfiguring Squid Process ....");
360
370
reconfigure(SIGHUP);
372
/// \ingroup CacheManagerInternal
373
CacheManager::ReconfigureAction::ReconfigureAction() : CacheManagerAction("reconfigure","Reconfigure Squid", 1, 1) { }
363
375
/// \ingroup CacheManagerInternal
365
cachemgrOfflineToggle(StoreEntry * sentry)
377
CacheManager::OfflineToggleAction::run(StoreEntry * sentry)
367
379
Config.onoff.offline = !Config.onoff.offline;
368
debugs(16, 0, "offline_mode now " << (Config.onoff.offline ? "ON" : "OFF") << ".");
380
debugs(16, DBG_IMPORTANT, "offline_mode now " << (Config.onoff.offline ? "ON" : "OFF") << " by Cache Manager request.");
370
382
storeAppendPrintf(sentry, "offline_mode is now %s\n",
371
383
Config.onoff.offline ? "ON" : "OFF");
385
/// \ingroup CacheManagerInternal
386
CacheManager::OfflineToggleAction::OfflineToggleAction() : CacheManagerAction ("offline_toggle", "Toggle offline_mode setting", 1, 1) { }
375
cachemgrActionProtection(const CacheManagerAction * at)
389
\ingroup CacheManagerInternal
390
* Renders the protection level text for an action.
391
* Also doubles as a check for the protection level.
394
CacheManager::ActionProtection(const CacheManagerAction * at)
379
pwd = cachemgrPasswdGet(Config.passwd_list, at->action);
398
pwd = PasswdGet(Config.passwd_list, at->action);
382
401
return at->flags.pw_req ? "hidden" : "public";
390
409
return "protected";
394
cachemgrMenu(StoreEntry * sentry)
412
/// \ingroup CacheManagerInternal
414
CacheManager::MenuAction::run(StoreEntry * sentry)
396
CacheManagerAction *a;
416
CacheManagerActionList::iterator a;
398
for (a = ActionTable; a != NULL; a = a->next) {
418
debugs(16, 4, "CacheManager::MenuCommand invoked");
419
for (a = cmgr->ActionsList.begin(); a != cmgr->ActionsList.end(); ++a) {
420
debugs(16, 5, " showing action " << (*a)->action);
399
421
storeAppendPrintf(sentry, " %-22s\t%-32s\t%s\n",
400
a->action, a->desc, cachemgrActionProtection(a));
422
(*a)->action, (*a)->desc, cmgr->ActionProtection(*a));
425
/// \ingroup CacheManagerInternal
426
CacheManager::MenuAction::MenuAction(CacheManager *aMgr) : CacheManagerAction ("menu", "Cache Manager Menu", 0, 1), cmgr(aMgr) { }
405
cachemgrPasswdGet(cachemgr_passwd * a, const char *action)
429
\ingroup CacheManagerInternal
430
* gets from the global Config the password the user would need to supply
431
* for the action she queried
434
CacheManager::PasswdGet(cachemgr_passwd * a, const char *action)
453
CacheManager* CacheManager::instance=0;
456
\ingroup CacheManagerAPI
457
* Singleton accessor method.
460
CacheManager::GetInstance()
463
debugs(16, 6, "CacheManager::GetInstance: starting cachemanager up");
464
instance = new CacheManager;
470
/// \ingroup CacheManagerInternal
471
void CacheManagerActionLegacy::run(StoreEntry *sentry)
475
/// \ingroup CacheManagerInternal
476
CacheManagerAction::CacheManagerAction(char const *anAction, char const *aDesc, unsigned int isPwReq, unsigned int isAtomic)
478
flags.pw_req = isPwReq;
479
flags.atomic = isAtomic;
480
action = xstrdup (anAction);
481
desc = xstrdup (aDesc);
483
/// \ingroup CacheManagerInternal
484
CacheManagerAction::~CacheManagerAction()
490
/// \ingroup CacheManagerInternal
491
CacheManagerActionLegacy::CacheManagerActionLegacy(char const *anAction, char const *aDesc, unsigned int isPwReq, unsigned int isAtomic, OBJH *aHandler) : CacheManagerAction(anAction, aDesc, isPwReq, isAtomic), handler(aHandler)