]>
git.ipfire.org Git - thirdparty/squid.git/blob - tools/cachemgr.cc
2 * DEBUG: section -- CGI Cache Manager
3 * AUTHOR: Duane Wessels
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
35 #include "getfullhostname.h"
36 #include "html_quote.h"
37 #include "ip/Address.h"
61 #include <gnumalloc.h>
81 #include <sys/param.h>
84 #include <sys/socket.h>
87 #include <netinet/in.h>
90 #include <arpa/inet.h>
123 #ifndef DEFAULT_CACHEMGR_CONFIG
124 #define DEFAULT_CACHEMGR_CONFIG "/etc/squid/cachemgr.conf"
140 * Static variables and constants
142 static const time_t passwd_ttl
= 60 * 60 * 3; /* in sec */
143 static const char *script_name
= "/cgi-bin/cachemgr.cgi";
144 static const char *progname
= NULL
;
148 * Function prototypes
150 static const char *safe_str(const char *str
);
151 static const char *xstrtok(char **str
, char del
);
152 static void print_trailer(void);
153 static void auth_html(const char *host
, int port
, const char *user_name
);
154 static void error_html(const char *msg
);
155 static char *menu_url(cachemgr_request
* req
, const char *action
);
156 static int parse_status_line(const char *sline
, const char **statusStr
);
157 static cachemgr_request
*read_request(void);
158 static char *read_get_request(void);
159 static char *read_post_request(void);
161 static void make_pub_auth(cachemgr_request
* req
);
162 static void decode_pub_auth(cachemgr_request
* req
);
163 static void reset_auth(cachemgr_request
* req
);
164 static const char *make_auth_header(const cachemgr_request
* req
);
166 static int check_target_acl(const char *hostname
, int port
);
169 static int s_iInitCount
= 0;
171 int Win32SockInit(void)
173 int iVersionRequested
;
177 if (s_iInitCount
> 0) {
180 } else if (s_iInitCount
< 0)
181 return (s_iInitCount
);
183 /* s_iInitCount == 0. Do the initailization */
184 iVersionRequested
= MAKEWORD(2, 0);
186 err
= WSAStartup((WORD
) iVersionRequested
, &wsaData
);
190 return (s_iInitCount
);
193 if (LOBYTE(wsaData
.wVersion
) != 2 ||
194 HIBYTE(wsaData
.wVersion
) != 0) {
197 return (s_iInitCount
);
201 return (s_iInitCount
);
204 void Win32SockCleanup(void)
206 if (--s_iInitCount
== 0)
212 #endif /* ifdef _SQUID_MSWIN_ */
215 safe_str(const char *str
)
217 return str
? str
: "";
220 /* relaxed number format */
222 is_number(const char *str
)
224 return strspn(str
, "\t -+01234567890./\n") == strlen(str
);
228 xstrtok(char **str
, char del
)
231 char *p
= strchr(*str
, del
);
244 while (len
&& xisspace(tok
[len
- 1]))
247 while (xisspace(*tok
))
258 printf("<HR noshade size=\"1px\">\n");
259 printf("<ADDRESS>\n");
260 printf("Generated %s, by %s/%s@%s\n",
261 mkrfc1123(now
), progname
, VERSION
, getfullhostname());
262 printf("</ADDRESS></BODY></HTML>\n");
266 auth_html(const char *host
, int port
, const char *user_name
)
274 if (!host
|| !strlen(host
))
277 printf("Content-Type: text/html\r\n\r\n");
279 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
281 printf("<HTML><HEAD><TITLE>Cache Manager Interface</TITLE>\n");
283 printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE></HEAD>\n");
285 printf("<BODY><H1>Cache Manager Interface</H1>\n");
287 printf("<P>This is a WWW interface to the instrumentation interface\n");
289 printf("for the Squid object cache.</P>\n");
291 printf("<HR noshade size=\"1px\">\n");
293 printf("<FORM METHOD=\"POST\" ACTION=\"%s\">\n", script_name
);
295 printf("<TABLE BORDER=\"0\" CELLPADDING=\"10\" CELLSPACING=\"1\">\n");
298 fp
= fopen("cachemgr.conf", "r");
301 fp
= fopen(DEFAULT_CACHEMGR_CONFIG
, "r");
305 char config_line
[BUFSIZ
];
307 while (fgets(config_line
, BUFSIZ
, fp
)) {
308 char *server
, *comment
;
309 strtok(config_line
, "\r\n");
311 if (config_line
[0] == '#')
314 if (config_line
[0] == '\0')
317 if ((server
= strtok(config_line
, " \t")) == NULL
)
320 if (strchr(server
, '*') || strchr(server
, '[') || strchr(server
, '?')) {
325 comment
= strtok(NULL
, "");
328 while (*comment
== ' ' || *comment
== '\t')
331 if (!comment
|| !*comment
)
335 printf("<TR><TH ALIGN=\"left\">Cache Server:</TH><TD><SELECT NAME=\"server\">\n");
338 printf("<OPTION VALUE=\"%s\"%s>%s</OPTION>\n", server
, (servers
|| *host
) ? "" : " SELECTED", comment
);
343 if (need_host
== 1 && !*host
)
347 printf("<OPTION VALUE=\"\"%s>Other</OPTION>\n", (*host
) ? " SELECTED" : "");
349 printf("</SELECT></TR>\n");
356 if (need_host
== 1 && !*host
)
359 printf("<TR><TH ALIGN=\"left\">Cache Host:</TH><TD><INPUT NAME=\"host\" ");
361 printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", host
);
363 printf("<TR><TH ALIGN=\"left\">Cache Port:</TH><TD><INPUT NAME=\"port\" ");
365 printf("size=\"30\" VALUE=\"%d\"></TD></TR>\n", port
);
368 printf("<TR><TH ALIGN=\"left\">Manager name:</TH><TD><INPUT NAME=\"user_name\" ");
370 printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", user_name
);
372 printf("<TR><TH ALIGN=\"left\">Password:</TH><TD><INPUT TYPE=\"password\" NAME=\"passwd\" ");
374 printf("size=\"30\" VALUE=\"\"></TD></TR>\n");
376 printf("</TABLE><BR CLEAR=\"all\">\n");
378 printf("<INPUT TYPE=\"submit\" VALUE=\"Continue...\">\n");
386 error_html(const char *msg
)
388 printf("Content-Type: text/html\r\n\r\n");
389 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
390 printf("<HTML><HEAD><TITLE>Cache Manager Error</TITLE>\n");
391 printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE></HEAD>\n");
392 printf("<BODY><H1>Cache Manager Error</H1>\n");
393 printf("<P>\n%s</P>\n", html_quote(msg
));
397 /* returns http status extracted from status line or -1 on parsing failure */
399 parse_status_line(const char *sline
, const char **statusStr
)
401 const char *sp
= strchr(sline
, ' ');
406 if (strncasecmp(sline
, "HTTP/", 5) || !sp
)
409 while (xisspace(*++sp
));
420 menu_url(cachemgr_request
* req
, const char *action
)
422 static char url
[1024];
423 snprintf(url
, sizeof(url
), "%s?host=%s&port=%d&user_name=%s&operation=%s&auth=%s",
427 safe_str(req
->user_name
),
429 safe_str(req
->pub_auth
));
434 munge_menu_line(const char *buf
, cachemgr_request
* req
)
442 static char html
[2 * 1024];
450 buf_copy
= x
= xstrdup(buf
);
452 a
= xstrtok(&x
, '\t');
454 d
= xstrtok(&x
, '\t');
456 p
= xstrtok(&x
, '\t');
458 a_url
= xstrdup(menu_url(req
, a
));
460 /* no reason to give a url for a disabled action */
461 if (!strcmp(p
, "disabled"))
462 snprintf(html
, sizeof(html
), "<LI type=\"circle\">%s (disabled)<A HREF=\"%s\">.</A>\n", d
, a_url
);
464 /* disable a hidden action (requires a password, but password is not in squid.conf) */
465 if (!strcmp(p
, "hidden"))
466 snprintf(html
, sizeof(html
), "<LI type=\"circle\">%s (hidden)<A HREF=\"%s\">.</A>\n", d
, a_url
);
468 /* disable link if authentication is required and we have no password */
469 if (!strcmp(p
, "protected") && !req
->passwd
)
470 snprintf(html
, sizeof(html
), "<LI type=\"circle\">%s (requires <a href=\"%s\">authentication</a>)<A HREF=\"%s\">.</A>\n",
471 d
, menu_url(req
, "authenticate"), a_url
);
473 /* highlight protected but probably available entries */
474 if (!strcmp(p
, "protected"))
475 snprintf(html
, sizeof(html
), "<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\n",
478 /* public entry or unknown type of protection */
480 snprintf(html
, sizeof(html
), "<LI type=\"disk\"><A HREF=\"%s\">%s</A>\n", a_url
, d
);
490 munge_other_line(const char *buf
, cachemgr_request
* req
)
492 static const char *ttags
[] = {"td", "th"};
494 static char html
[4096];
495 static int table_line_num
= 0;
496 static int next_is_header
= 0;
502 /* does it look like a table? */
504 if (!strchr(buf
, '\t') || *buf
== '\t') {
505 /* nope, just text */
506 snprintf(html
, sizeof(html
), "%s%s",
507 table_line_num
? "</table>\n<pre>" : "", html_quote(buf
));
512 /* start html table */
513 if (!table_line_num
) {
514 l
+= snprintf(html
+ l
, sizeof(html
) - l
, "</pre><table cellpadding=\"2\" cellspacing=\"1\">\n");
519 is_header
= (!table_line_num
|| next_is_header
) && !strchr(buf
, ':') && !is_number(buf
);
521 ttag
= ttags
[is_header
];
524 l
+= snprintf(html
+ l
, sizeof(html
) - l
, "<tr>");
526 /* substitute '\t' */
527 buf_copy
= x
= xstrdup(buf
);
529 if ((p
= strchr(x
, '\n')))
532 while (x
&& strlen(x
)) {
534 const char *cell
= xstrtok(&x
, '\t');
536 while (x
&& *x
== '\t') {
541 l
+= snprintf(html
+ l
, sizeof(html
) - l
, "<%s colspan=\"%d\" align=\"%s\">%s</%s>",
543 is_header
? "center" : is_number(cell
) ? "right" : "left",
544 html_quote(cell
), ttag
);
549 snprintf(html
+ l
, sizeof(html
) - l
, "</tr>\n");
550 next_is_header
= is_header
&& strstr(buf
, "\t\t");
556 munge_action_line(const char *_buf
, cachemgr_request
* req
)
558 static char html
[2 * 1024];
559 char *buf
= xstrdup(_buf
);
561 const char *action
, *description
;
564 if ((p
= strchr(x
, '\n')))
566 action
= xstrtok(&x
, '\t');
567 description
= xstrtok(&x
, '\t');
569 description
= action
;
572 snprintf(html
, sizeof(html
), " <a href=\"%s\">%s</a>", menu_url(req
, action
), description
);
577 read_reply(int s
, cachemgr_request
* req
)
583 char *tmpfile
= tempnam(NULL
, "tmp0000");
584 FILE *fp
= fopen(tmpfile
, "w+");
587 FILE *fp
= fdopen(s
, "r");
589 /* interpretation states */
591 isStatusLine
, isHeaders
, isActions
, isBodyStart
, isBody
, isForward
, isEof
, isForwardEof
, isSuccess
, isError
592 } istate
= isStatusLine
;
594 const char *action
= req
->action
;
595 const char *statusStr
= NULL
;
598 if (0 == strlen(req
->action
))
600 else if (0 == strcasecmp(req
->action
, "menu"))
618 while ((reply
=recv(s
, buf
, sizeof(buf
), 0)) > 0)
619 fwrite(buf
, 1, reply
, fp
);
628 /* read reply interpreting one line at a time depending on state */
629 while (istate
< isEof
) {
630 if (!fgets(buf
, sizeof(buf
), fp
))
631 istate
= istate
== isForward
? isForwardEof
: isEof
;
636 /* get HTTP status */
637 /* uncomment the following if you want to debug headers */
638 /* fputs("\r\n\r\n", stdout); */
639 status
= parse_status_line(buf
, &statusStr
);
640 istate
= status
== 200 ? isHeaders
: isForward
;
641 /* if cache asks for authentication, we have to reset our info */
643 if (status
== 401 || status
== 407) {
645 status
= 403; /* Forbiden, see comments in case isForward: */
648 /* this is a way to pass HTTP status to the Web server */
650 printf("Status: %d %s", status
, statusStr
); /* statusStr has '\n' */
655 /* forward header field */
656 if (!strcmp(buf
, "\r\n")) { /* end of headers */
657 fputs("Content-Type: text/html\r\n", stdout
); /* add our type */
658 istate
= isBodyStart
;
661 if (strncasecmp(buf
, "Content-Type:", 13)) /* filter out their type */
667 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
669 printf("<HTML><HEAD><TITLE>CacheMgr@%s: %s</TITLE>\n",
670 req
->hostname
, action
);
672 printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}TABLE{background-color:#333333;border:0pt;padding:0pt}TH,TD{background-color:#ffffff;white-space:nowrap}--></STYLE>\n");
674 printf("</HEAD><BODY>\n");
677 printf("<H2><a href=\"%s\">Cache Manager</a> menu for %s:</H2>",
678 menu_url(req
, "authenticate"), req
->hostname
);
681 printf("<P><A HREF=\"%s\">%s</A>\n<HR noshade size=\"1px\">\n",
682 menu_url(req
, "menu"), "Cache Manager menu");
687 /* yes, fall through, we do not want to loose the first line */
690 if (strncmp(buf
, "action:", 7) == 0) {
692 fputs(munge_action_line(buf
+ 7, req
), stdout
);
698 printf("<HR noshade size=\"1px\">\n");
703 /* yes, fall through, we do not want to loose the first line */
706 /* interpret [and reformat] cache response */
709 fputs(munge_menu_line(buf
, req
), stdout
);
711 fputs(munge_other_line(buf
, req
), stdout
);
716 /* forward: no modifications allowed */
718 * Note: we currently do not know any way to get browser.reply to
719 * 401 to .cgi because web server filters out all auth info. Thus we
720 * disable authentication headers for now.
722 if (!strncasecmp(buf
, "WWW-Authenticate:", 17) || !strncasecmp(buf
, "Proxy-Authenticate:", 19)); /* skip */
733 printf("</table></PRE>\n");
742 /* indicate that we finished processing an "error" sequence */
748 printf("%s: internal bug: invalid state reached: %d", script_name
, istate
);
767 process_request(cachemgr_request
* req
)
770 char ipbuf
[MAX_IPSTRLEN
];
771 struct addrinfo
*AI
= NULL
;
776 static char buf
[2 * 1024];
779 auth_html(CACHEMGR_HOSTNAME
, CACHE_HTTP_PORT
, "");
783 if (req
->hostname
== NULL
) {
784 req
->hostname
= xstrdup(CACHEMGR_HOSTNAME
);
787 if (req
->port
== 0) {
788 req
->port
= CACHE_HTTP_PORT
;
791 if (req
->action
== NULL
) {
792 req
->action
= xstrdup("");
795 if (strcmp(req
->action
, "authenticate") == 0) {
796 auth_html(req
->hostname
, req
->port
, req
->user_name
);
800 if (!check_target_acl(req
->hostname
, req
->port
)) {
801 snprintf(buf
, 1024, "target %s:%d not allowed in cachemgr.conf\n", req
->hostname
, req
->port
);
806 S
= *gethostbyname(req
->hostname
);
808 if ( !S
.IsAnyAddr() ) {
810 } else if ((S
= req
->hostname
))
813 snprintf(buf
, 1024, "Unknown host: %s\n", req
->hostname
);
818 S
.SetPort(req
->port
);
823 if ((s
= socket( AI
->ai_family
, SOCK_STREAM
, 0)) < 0) {
825 if ((s
= socket(PF_INET
, SOCK_STREAM
, 0)) < 0) {
827 snprintf(buf
, 1024, "socket: %s\n", xstrerror());
832 if (connect(s
, AI
->ai_addr
, AI
->ai_addrlen
) < 0) {
833 snprintf(buf
, 1024, "connect %s: %s\n",
834 S
.ToURL(ipbuf
,MAX_IPSTRLEN
),
843 l
= snprintf(buf
, sizeof(buf
),
844 "GET cache_object://%s/%s%s%s HTTP/1.0\r\n"
845 "User-Agent: cachemgr.cgi/%s\r\n"
847 "%s" /* Authentication info or nothing */
851 req
->workers
? "?workers=" : (req
->processes
? "?processes=" : ""),
852 req
->workers
? req
->workers
: (req
->processes
? req
->processes
: ""),
854 make_auth_header(req
));
855 if (write(s
, buf
, l
) < 0) {
856 fprintf(stderr
,"ERROR: (%d) writing request: '%s'\n", errno
, buf
);
858 debug("wrote request: '%s'\n", buf
);
860 return read_reply(s
, req
);
864 main(int argc
, char *argv
[])
867 cachemgr_request
*req
;
873 atexit(Win32SockCleanup
);
874 _setmode( _fileno( stdin
), _O_BINARY
);
875 _setmode( _fileno( stdout
), _O_BINARY
);
878 if ((s
= strrchr(argv
[0], '\\')))
881 if ((s
= strrchr(argv
[0], '/')))
884 progname
= xstrdup(s
+ 1);
886 progname
= xstrdup(argv
[0]);
888 if ((s
= getenv("SCRIPT_NAME")) != NULL
)
889 script_name
= xstrdup(s
);
892 while (argc
> 1 && args
[1][0] == '-') {
893 // const char *value = "";
894 char option
= args
[1][1];
900 #if 0 // unused for now.
901 if (strlen(args
[1]) > 2) {
903 } else if (argc
> 2) {
916 req
= read_request();
918 return process_request(req
);
922 read_post_request(void)
928 if ((s
= getenv("REQUEST_METHOD")) == NULL
)
931 if (0 != strcasecmp(s
, "POST"))
934 if ((s
= getenv("CONTENT_LENGTH")) == NULL
)
937 if ((len
= atoi(s
)) <= 0)
940 buf
= (char *)xmalloc(len
+ 1);
942 if (fread(buf
, len
, 1, stdin
) == 0)
951 read_get_request(void)
955 if ((s
= getenv("QUERY_STRING")) == NULL
)
961 static cachemgr_request
*
966 cachemgr_request
*req
;
971 if ((buf
= read_post_request()) != NULL
)
973 else if ((buf
= read_get_request()) != NULL
)
980 if (strlen(buf
) == 0 || strlen(buf
) == 4000)
983 if (strlen(buf
) == 0)
990 req
= (cachemgr_request
*)xcalloc(1, sizeof(cachemgr_request
));
992 for (s
= strtok(buf
, "&"); s
!= NULL
; s
= strtok(NULL
, "&")) {
995 if ((q
= strchr(t
, '=')) == NULL
)
1000 rfc1738_unescape(t
);
1002 rfc1738_unescape(q
);
1004 if (0 == strcasecmp(t
, "server") && strlen(q
))
1005 req
->server
= xstrdup(q
);
1006 else if (0 == strcasecmp(t
, "host") && strlen(q
))
1007 req
->hostname
= xstrdup(q
);
1008 else if (0 == strcasecmp(t
, "port") && strlen(q
))
1009 req
->port
= atoi(q
);
1010 else if (0 == strcasecmp(t
, "user_name") && strlen(q
))
1011 req
->user_name
= xstrdup(q
);
1012 else if (0 == strcasecmp(t
, "passwd") && strlen(q
))
1013 req
->passwd
= xstrdup(q
);
1014 else if (0 == strcasecmp(t
, "auth") && strlen(q
))
1015 req
->pub_auth
= xstrdup(q
), decode_pub_auth(req
);
1016 else if (0 == strcasecmp(t
, "operation"))
1017 req
->action
= xstrdup(q
);
1018 else if (0 == strcasecmp(t
, "workers") && strlen(q
))
1019 req
->workers
= xstrdup(q
);
1020 else if (0 == strcasecmp(t
, "processes") && strlen(q
))
1021 req
->processes
= xstrdup(q
);
1024 if (req
->server
&& !req
->hostname
) {
1026 req
->hostname
= strtok(req
->server
, ":");
1028 if ((p
= strtok(NULL
, ":")))
1029 req
->port
= atoi(p
);
1033 debug("cmgr: got req: host: '%s' port: %d uname: '%s' passwd: '%s' auth: '%s' oper: '%s' workers: '%s' processes: '%s'\n",
1034 safe_str(req
->hostname
), req
->port
, safe_str(req
->user_name
), safe_str(req
->passwd
), safe_str(req
->pub_auth
), safe_str(req
->action
), safe_str(req
->workers
), safe_str(req
->processes
));
1039 /* Routines to support authentication */
1042 * Encodes auth info into a "public" form.
1043 * Currently no powerful encryption is used.
1046 make_pub_auth(cachemgr_request
* req
)
1048 static char buf
[1024];
1049 safe_free(req
->pub_auth
);
1050 debug("cmgr: encoding for pub...\n");
1052 if (!req
->passwd
|| !strlen(req
->passwd
))
1055 /* host | time | user | passwd */
1056 const int bufLen
= snprintf(buf
, sizeof(buf
), "%s|%d|%s|%s",
1059 req
->user_name
? req
->user_name
: "",
1061 debug("cmgr: pre-encoded for pub: %s\n", buf
);
1063 const int encodedLen
= base64_encode_len(bufLen
);
1064 req
->pub_auth
= (char *) xmalloc(encodedLen
);
1065 base64_encode_str(req
->pub_auth
, encodedLen
, buf
, bufLen
);
1066 debug("cmgr: encoded: '%s'\n", req
->pub_auth
);
1070 decode_pub_auth(cachemgr_request
* req
)
1073 const char *host_name
;
1074 const char *time_str
;
1075 const char *user_name
;
1078 debug("cmgr: decoding pub: '%s'\n", safe_str(req
->pub_auth
));
1079 safe_free(req
->passwd
);
1081 if (!req
->pub_auth
|| strlen(req
->pub_auth
) < 4 + strlen(safe_str(req
->hostname
)))
1084 const int decodedLen
= base64_decode_len(req
->pub_auth
);
1085 buf
= (char*)xmalloc(decodedLen
);
1086 base64_decode(buf
, decodedLen
, req
->pub_auth
);
1088 debug("cmgr: length ok\n");
1090 /* parse ( a lot of memory leaks, but that is cachemgr style :) */
1091 if ((host_name
= strtok(buf
, "|")) == NULL
)
1094 debug("cmgr: decoded host: '%s'\n", host_name
);
1096 if ((time_str
= strtok(NULL
, "|")) == NULL
)
1099 debug("cmgr: decoded time: '%s' (now: %d)\n", time_str
, (int) now
);
1101 if ((user_name
= strtok(NULL
, "|")) == NULL
)
1104 debug("cmgr: decoded uname: '%s'\n", user_name
);
1106 if ((passwd
= strtok(NULL
, "|")) == NULL
)
1109 debug("cmgr: decoded passwd: '%s'\n", passwd
);
1111 /* verify freshness and validity */
1112 if (atoi(time_str
) + passwd_ttl
< now
)
1115 if (strcasecmp(host_name
, req
->hostname
))
1118 debug("cmgr: verified auth. info.\n");
1121 xfree(req
->user_name
);
1123 req
->user_name
= xstrdup(user_name
);
1125 req
->passwd
= xstrdup(passwd
);
1131 reset_auth(cachemgr_request
* req
)
1133 safe_free(req
->passwd
);
1134 safe_free(req
->pub_auth
);
1138 make_auth_header(const cachemgr_request
* req
)
1140 static char buf
[1024];
1141 size_t stringLength
= 0;
1146 int bufLen
= snprintf(buf
, sizeof(buf
), "%s:%s",
1147 req
->user_name
? req
->user_name
: "",
1150 int encodedLen
= base64_encode_len(bufLen
);
1151 if (encodedLen
<= 0)
1154 char *str64
= static_cast<char*>(xmalloc(encodedLen
));
1155 base64_encode_str(str64
, encodedLen
, buf
, bufLen
);
1157 stringLength
+= snprintf(buf
, sizeof(buf
), "Authorization: Basic %s\r\n", str64
);
1159 assert(stringLength
< sizeof(buf
));
1161 snprintf(&buf
[stringLength
], sizeof(buf
) - stringLength
, "Proxy-Authorization: Basic %s\r\n", str64
);
1167 check_target_acl(const char *hostname
, int port
)
1169 char config_line
[BUFSIZ
];
1172 fp
= fopen("cachemgr.conf", "r");
1175 fp
= fopen(DEFAULT_CACHEMGR_CONFIG
, "r");
1178 #ifdef CACHEMGR_HOSTNAME_DEFINED
1180 if (strcmp(hostname
, CACHEMGR_HOSTNAME
) == 0 && port
== CACHE_HTTP_PORT
)
1185 if (strcmp(hostname
, "localhost") == 0)
1188 if (strcmp(hostname
, getfullhostname()) == 0)
1196 while (fgets(config_line
, BUFSIZ
, fp
)) {
1198 strtok(config_line
, " \r\n\t");
1200 if (config_line
[0] == '#')
1203 if (config_line
[0] == '\0')
1206 if ((token
= strtok(config_line
, ":")) == NULL
)
1211 if (fnmatch(token
, hostname
, 0) != 0)
1216 if (strcmp(token
, hostname
) != 0)
1221 if ((token
= strtok(NULL
, ":")) != NULL
) {
1224 if (strcmp(token
, "*") == 0)
1226 ; /* Wildcard port specification */
1227 else if (strcasecmp(token
, "any") == 0)
1229 ; /* Wildcard port specification */
1230 else if (sscanf(token
, "%d", &i
) != 1)
1235 } else if (port
!= CACHE_HTTP_PORT
)