cache_manager.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:10k
源码类别:

代理服务器

开发平台:

Unix_Linux

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