]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - tools/cachemgr.cc
SourceFormat Enforcement
[thirdparty/squid.git] / tools / cachemgr.cc
index e8c7060b2a29036c6a3bea00f3d22ef997db81d2..2c3e25cf60894db3e1b317a0a71cb4b5ba03274b 100644 (file)
@@ -1,36 +1,12 @@
 /*
- * DEBUG: section --    CGI Cache Manager
- * AUTHOR: Duane Wessels
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
-#include "config.h"
+#include "squid.h"
 #include "base64.h"
 #include "getfullhostname.h"
 #include "html_quote.h"
 #include "rfc1738.h"
 #include "util.h"
 
+#include <cctype>
+#include <cerrno>
+#include <csignal>
+#include <cstring>
+#include <ctime>
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
 #if HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
 #if HAVE_PWD_H
 #include <pwd.h>
 #endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_TIME_H
-#include <time.h>
-#endif
 #if HAVE_SYS_PARAM_H
 #include <sys/param.h>
 #endif
 #if HAVE_LIBC_H
 #include <libc.h>
 #endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
 #if HAVE_STRINGS_H
 #include <strings.h>
 #endif
@@ -119,7 +82,6 @@ extern "C" {
 }
 #endif
 
-
 #ifndef DEFAULT_CACHEMGR_CONFIG
 #define DEFAULT_CACHEMGR_CONFIG "/etc/squid/cachemgr.conf"
 #endif
@@ -139,7 +101,7 @@ typedef struct {
 /*
  * Static variables and constants
  */
-static const time_t passwd_ttl = 60 * 60 * 3;  /* in sec */
+static const time_t passwd_ttl = 60 * 60 * 3;   /* in sec */
 static const char *script_name = "/cgi-bin/cachemgr.cgi";
 static const char *progname = NULL;
 static time_t now;
@@ -165,7 +127,7 @@ static const char *make_auth_header(const cachemgr_request * req);
 
 static int check_target_acl(const char *hostname, int port);
 
-#if _SQUID_MSWIN_
+#if _SQUID_WINDOWS_
 static int s_iInitCount = 0;
 
 int Win32SockInit(void)
@@ -175,7 +137,7 @@ int Win32SockInit(void)
     int err;
 
     if (s_iInitCount > 0) {
-        s_iInitCount++;
+        ++s_iInitCount;
         return (0);
     } else if (s_iInitCount < 0)
         return (s_iInitCount);
@@ -197,7 +159,7 @@ int Win32SockInit(void)
         return (s_iInitCount);
     }
 
-    s_iInitCount++;
+    ++s_iInitCount;
     return (s_iInitCount);
 }
 
@@ -245,7 +207,7 @@ xstrtok(char **str, char del)
             tok[--len] = '\0';
 
         while (xisspace(*tok))
-            tok++;
+            ++tok;
 
         return tok;
     } else
@@ -274,13 +236,40 @@ auth_html(const char *host, int port, const char *user_name)
     if (!host || !strlen(host))
         host = "";
 
+    fp = fopen("cachemgr.conf", "r");
+
+    if (fp == NULL)
+        fp = fopen(DEFAULT_CACHEMGR_CONFIG, "r");
+
+    if (fp == NULL)
+        printf("X-Error: message=\"Unable to open config %s\"", DEFAULT_CACHEMGR_CONFIG);
+
     printf("Content-Type: text/html\r\n\r\n");
 
     printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
 
     printf("<HTML><HEAD><TITLE>Cache Manager Interface</TITLE>\n");
 
-    printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE></HEAD>\n");
+    printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n");
+
+    printf("<script type=\"text/javascript\">\n");
+    printf("function TS(t, s) {\n");
+    printf(" var x = new XMLHttpRequest();\n");
+    printf(" x.open('GET', 'http' + s + '://' + t + '/squid-internal-mgr/', true);\n");
+    printf(" x.onreadystatechange=function() {\n");
+    printf("  if (x.readyState==4) {\n");
+    printf("   if ((x.status>=200 && x.status <= 299) || x.status==401) {\n");
+    printf("    var v = x.getResponseHeader('Server');\n");
+    printf("    if (v.substring(0,8) == 'squid/3.' && (v[8]=='H' || parseInt(v.substring(8)) >= 2)) {\n");
+    printf("     var d = document.getElementById('H' + s + 'mgr');\n");
+    printf("     if (d.innerHTML == '') d.innerHTML = '<h2>HTTP' + (s=='s'?'S':'') + ' Managed Proxies</h2>';\n");
+    printf("     d.innerHTML = d.innerHTML + '<p>Host: <a href=\"http' + s + '://' + t + '/squid-internal-mgr/\">' + t + '</a></p>';\n");
+    printf(" }}}}\n");
+    printf(" x.send(null);\n");
+    printf("}\n");
+    printf("</script>\n");
+
+    printf("</HEAD>\n");
 
     printf("<BODY><H1>Cache Manager Interface</H1>\n");
 
@@ -290,16 +279,14 @@ auth_html(const char *host, int port, const char *user_name)
 
     printf("<HR noshade size=\"1px\">\n");
 
+    printf("<div id=\"Hsmgr\"></div>\n");
+    printf("<div id=\"Hmgr\"></div>\n");
+    printf("<div id=\"Cmgr\">\n");
+    printf("<h2>CGI Managed Proxies</h2>\n");
     printf("<FORM METHOD=\"POST\" ACTION=\"%s\">\n", script_name);
 
     printf("<TABLE BORDER=\"0\" CELLPADDING=\"10\" CELLSPACING=\"1\">\n");
 
-
-    fp = fopen("cachemgr.conf", "r");
-
-    if (fp == NULL)
-        fp = fopen(DEFAULT_CACHEMGR_CONFIG, "r");
-
     if (fp != NULL) {
         int servers = 0;
         char config_line[BUFSIZ];
@@ -326,17 +313,16 @@ auth_html(const char *host, int port, const char *user_name)
 
             if (comment)
                 while (*comment == ' ' || *comment == '\t')
-                    comment++;
+                    ++comment;
 
             if (!comment || !*comment)
                 comment = server;
 
-            if (!servers) {
-                printf("<TR><TH ALIGN=\"left\">Cache Server:</TH><TD><SELECT NAME=\"server\">\n");
-            }
+            if (!servers)
+                printf("<TR><TH ALIGN=\"left\">Cache Server:</TH><TD><SELECT id=\"server\" NAME=\"server\">\n");
 
             printf("<OPTION VALUE=\"%s\"%s>%s</OPTION>\n", server, (servers || *host) ? "" : " SELECTED", comment);
-            servers++;
+            ++servers;
         }
 
         if (servers) {
@@ -377,7 +363,14 @@ auth_html(const char *host, int port, const char *user_name)
 
     printf("<INPUT TYPE=\"submit\" VALUE=\"Continue...\">\n");
 
-    printf("</FORM>\n");
+    printf("</FORM></div>\n");
+
+    printf("<script type=\"text/javascript\">\n");
+    printf("var s = document.getElementById(\"server\");\n");
+    printf("for (var i = 0; i < s.childElementCount; i++) {\n");
+    printf(" TS(s.children[i].value, '');\n");
+    printf(" TS(s.children[i].value, 's');\n");
+    printf("}</script>\n");
 
     print_trailer();
 }
@@ -487,7 +480,7 @@ munge_menu_line(const char *buf, cachemgr_request * req)
 }
 
 static const char *
-munge_other_line(const char *buf, cachemgr_request * req)
+munge_other_line(const char *buf, cachemgr_request *)
 {
     static const char *ttags[] = {"td", "th"};
 
@@ -534,8 +527,8 @@ munge_other_line(const char *buf, cachemgr_request * req)
         const char *cell = xstrtok(&x, '\t');
 
         while (x && *x == '\t') {
-            column_span++;
-            x++;
+            ++column_span;
+            ++x;
         }
 
         l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s</%s>",
@@ -548,7 +541,7 @@ munge_other_line(const char *buf, cachemgr_request * req)
     /* record ends */
     snprintf(html + l, sizeof(html) - l, "</tr>\n");
     next_is_header = is_header && strstr(buf, "\t\t");
-    table_line_num++;
+    ++table_line_num;
     return html;
 }
 
@@ -564,12 +557,15 @@ munge_action_line(const char *_buf, cachemgr_request * req)
     if ((p = strchr(x, '\n')))
         *p = '\0';
     action = xstrtok(&x, '\t');
+    if (!action) {
+        xfree(buf);
+        return "";
+    }
     description = xstrtok(&x, '\t');
     if (!description)
         description = action;
-    if (!action)
-        return "";
     snprintf(html, sizeof(html), " <a href=\"%s\">%s</a>", menu_url(req, action), description);
+    xfree(buf);
     return html;
 }
 
@@ -577,7 +573,7 @@ static int
 read_reply(int s, cachemgr_request * req)
 {
     char buf[4 * 1024];
-#if _SQUID_MSWIN_
+#if _SQUID_WINDOWS_
 
     int reply;
     char *tmpfile = tempnam(NULL, "tmp0000");
@@ -601,7 +597,7 @@ read_reply(int s, cachemgr_request * req)
         parse_menu = 1;
 
     if (fp == NULL) {
-#if _SQUID_MSWIN_
+#if _SQUID_WINDOWS_
         perror(tmpfile);
         xfree(tmpfile);
 #else
@@ -613,7 +609,7 @@ read_reply(int s, cachemgr_request * req)
         return 1;
     }
 
-#if _SQUID_MSWIN_
+#if _SQUID_WINDOWS_
 
     while ((reply=recv(s, buf , sizeof(buf), 0)) > 0)
         fwrite(buf, 1, reply, fp);
@@ -642,23 +638,23 @@ read_reply(int s, cachemgr_request * req)
 
             if (status == 401 || status == 407) {
                 reset_auth(req);
-                status = 403;  /* Forbiden, see comments in case isForward: */
+                status = 403;   /* Forbiden, see comments in case isForward: */
             }
 
             /* this is a way to pass HTTP status to the Web server */
             if (statusStr)
-                printf("Status: %d %s", status, statusStr);    /* statusStr has '\n' */
+                printf("Status: %d %s", status, statusStr); /* statusStr has '\n' */
 
             break;
 
         case isHeaders:
             /* forward header field */
-            if (!strcmp(buf, "\r\n")) {                /* end of headers */
-                fputs("Content-Type: text/html\r\n", stdout);  /* add our type */
+            if (!strcmp(buf, "\r\n")) {     /* end of headers */
+                fputs("Content-Type: text/html\r\n", stdout);   /* add our type */
                 istate = isBodyStart;
             }
 
-            if (strncasecmp(buf, "Content-Type:", 13)) /* filter out their type */
+            if (strncasecmp(buf, "Content-Type:", 13))  /* filter out their type */
                 fputs(buf, stdout);
 
             break;
@@ -684,7 +680,7 @@ read_reply(int s, cachemgr_request * req)
             }
 
             istate = isActions;
-            /* yes, fall through, we do not want to loose the first line */
+        /* yes, fall through, we do not want to loose the first line */
 
         case isActions:
             if (strncmp(buf, "action:", 7) == 0) {
@@ -700,7 +696,7 @@ read_reply(int s, cachemgr_request * req)
             }
 
             istate = isBody;
-            /* yes, fall through, we do not want to loose the first line */
+        /* yes, fall through, we do not want to loose the first line */
 
         case isBody:
             /* interpret [and reformat] cache response */
@@ -719,7 +715,7 @@ read_reply(int s, cachemgr_request * req)
              * 401 to .cgi because web server filters out all auth info. Thus we
              * disable authentication headers for now.
              */
-            if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));   /* skip */
+            if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));    /* skip */
             else
                 fputs(buf, stdout);
 
@@ -752,7 +748,7 @@ read_reply(int s, cachemgr_request * req)
     }
 
     fclose(fp);
-#if _SQUID_MSWIN_
+#if _SQUID_WINDOWS_
 
     remove(tmpfile);
     xfree(tmpfile);
@@ -798,53 +794,55 @@ process_request(cachemgr_request * req)
     }
 
     if (!check_target_acl(req->hostname, req->port)) {
-        snprintf(buf, 1024, "target %s:%d not allowed in cachemgr.conf\n", req->hostname, req->port);
+        snprintf(buf, sizeof(buf), "target %s:%d not allowed in cachemgr.conf\n", req->hostname, req->port);
         error_html(buf);
         return 1;
     }
 
     S = *gethostbyname(req->hostname);
 
-    if ( !S.IsAnyAddr() ) {
+    if ( !S.isAnyAddr() ) {
         (void) 0;
     } else if ((S = req->hostname))
         (void) 0;
     else {
-        snprintf(buf, 1024, "Unknown host: %s\n", req->hostname);
+        snprintf(buf, sizeof(buf), "Unknown host: %s\n", req->hostname);
         error_html(buf);
         return 1;
     }
 
-    S.SetPort(req->port);
+    S.port(req->port);
 
-    S.GetAddrInfo(AI);
+    S.getAddrInfo(AI);
 
 #if USE_IPV6
     if ((s = socket( AI->ai_family, SOCK_STREAM, 0)) < 0) {
 #else
     if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
 #endif
-        snprintf(buf, 1024, "socket: %s\n", xstrerror());
+        snprintf(buf, sizeof(buf), "socket: %s\n", xstrerror());
         error_html(buf);
+        Ip::Address::FreeAddr(AI);
         return 1;
     }
 
     if (connect(s, AI->ai_addr, AI->ai_addrlen) < 0) {
-        snprintf(buf, 1024, "connect %s: %s\n",
-                 S.ToURL(ipbuf,MAX_IPSTRLEN),
+        snprintf(buf, sizeof(buf), "connect %s: %s\n",
+                 S.toUrl(ipbuf,MAX_IPSTRLEN),
                  xstrerror());
         error_html(buf);
-        S.FreeAddrInfo(AI);
+        Ip::Address::FreeAddr(AI);
+        close(s);
         return 1;
     }
 
-    S.FreeAddrInfo(AI);
+    Ip::Address::FreeAddr(AI);
 
     l = snprintf(buf, sizeof(buf),
                  "GET cache_object://%s/%s%s%s HTTP/1.0\r\n"
                  "User-Agent: cachemgr.cgi/%s\r\n"
                  "Accept: */*\r\n"
-                 "%s"                  /* Authentication info or nothing */
+                 "%s"           /* Authentication info or nothing */
                  "\r\n",
                  req->hostname,
                  req->action,
@@ -867,7 +865,7 @@ main(int argc, char *argv[])
     cachemgr_request *req;
 
     now = time(NULL);
-#if _SQUID_MSWIN_
+#if _SQUID_WINDOWS_
 
     Win32SockInit();
     atexit(Win32SockCleanup);
@@ -902,15 +900,15 @@ main(int argc, char *argv[])
                 value = args[1] + 2;
             } else if (argc > 2) {
                 value = args[2];
-                args++;
-                argc--;
+                ++args;
+                --argc;
             } else
                 value = "";
 #endif
             break;
         }
-        args++;
-        argc--;
+        ++args;
+        --argc;
     }
 
     req = read_request();
@@ -922,8 +920,6 @@ static char *
 read_post_request(void)
 {
     char *s;
-    char *buf;
-    int len;
 
     if ((s = getenv("REQUEST_METHOD")) == NULL)
         return NULL;
@@ -934,15 +930,34 @@ read_post_request(void)
     if ((s = getenv("CONTENT_LENGTH")) == NULL)
         return NULL;
 
-    if ((len = atoi(s)) <= 0)
+    if (*s == '-') // negative length content huh?
         return NULL;
 
-    buf = (char *)xmalloc(len + 1);
+    uint64_t len;
 
-    if (fread(buf, len, 1, stdin) == 0)
+    char *endptr = s+ strlen(s);
+    if ((len = strtoll(s, &endptr, 10)) <= 0)
         return NULL;
 
-    buf[len] = '\0';
+    // limit the input to something reasonable.
+    // 4KB should be enough for the GET/POST data length, but may be extended.
+    size_t bufLen = (len < 4096 ? len : 4095);
+    char *buf = (char *)xmalloc(bufLen + 1);
+
+    size_t readLen = fread(buf, 1, bufLen, stdin);
+    if (readLen == 0) {
+        xfree(buf);
+        return NULL;
+    }
+    buf[readLen] = '\0';
+    len -= readLen;
+
+    // purge the remainder of the request entity
+    while (len > 0 && readLen) {
+        char temp[65535];
+        readLen = fread(temp, 1, 65535, stdin);
+        len -= readLen;
+    }
 
     return buf;
 }
@@ -975,7 +990,7 @@ read_request(void)
     else
         return NULL;
 
-#if _SQUID_MSWIN_
+#if _SQUID_WINDOWS_
 
     if (strlen(buf) == 0 || strlen(buf) == 4000)
 #else
@@ -995,30 +1010,32 @@ read_request(void)
         if ((q = strchr(t, '=')) == NULL)
             continue;
 
-        *q++ = '\0';
+        *q = '\0';
+        ++q;
 
         rfc1738_unescape(t);
 
         rfc1738_unescape(q);
 
-        if (0 == strcasecmp(t, "server") && strlen(q))
+        if (0 == strcmp(t, "server") && strlen(q))
             req->server = xstrdup(q);
-        else if (0 == strcasecmp(t, "host") && strlen(q))
+        else if (0 == strcmp(t, "host") && strlen(q))
             req->hostname = xstrdup(q);
-        else if (0 == strcasecmp(t, "port") && strlen(q))
+        else if (0 == strcmp(t, "port") && strlen(q))
             req->port = atoi(q);
-        else if (0 == strcasecmp(t, "user_name") && strlen(q))
+        else if (0 == strcmp(t, "user_name") && strlen(q))
             req->user_name = xstrdup(q);
-        else if (0 == strcasecmp(t, "passwd") && strlen(q))
+        else if (0 == strcmp(t, "passwd") && strlen(q))
             req->passwd = xstrdup(q);
-        else if (0 == strcasecmp(t, "auth") && strlen(q))
+        else if (0 == strcmp(t, "auth") && strlen(q))
             req->pub_auth = xstrdup(q), decode_pub_auth(req);
-        else if (0 == strcasecmp(t, "operation"))
+        else if (0 == strcmp(t, "operation"))
             req->action = xstrdup(q);
-        else if (0 == strcasecmp(t, "workers") && strlen(q))
+        else if (0 == strcmp(t, "workers") && strlen(q))
             req->workers = xstrdup(q);
-        else if (0 == strcasecmp(t, "processes") && strlen(q))
+        else if (0 == strcmp(t, "processes") && strlen(q))
             req->processes = xstrdup(q);
+        safe_free(t);
     }
 
     if (req->server && !req->hostname) {
@@ -1035,7 +1052,6 @@ read_request(void)
     return req;
 }
 
-
 /* Routines to support authentication */
 
 /*
@@ -1062,7 +1078,11 @@ make_pub_auth(cachemgr_request * req)
 
     const int encodedLen = base64_encode_len(bufLen);
     req->pub_auth = (char *) xmalloc(encodedLen);
-    base64_encode_str(req->pub_auth, encodedLen, buf, bufLen);
+    struct base64_encode_ctx ctx;
+    base64_encode_init(&ctx);
+    size_t blen = base64_encode_update(&ctx, reinterpret_cast<uint8_t*>(req->pub_auth), bufLen, reinterpret_cast<uint8_t*>(buf));
+    blen += base64_encode_final(&ctx, reinterpret_cast<uint8_t*>(req->pub_auth)+blen);
+    req->pub_auth[blen] = '\0';
     debug("cmgr: encoded: '%s'\n", req->pub_auth);
 }
 
@@ -1081,44 +1101,63 @@ decode_pub_auth(cachemgr_request * req)
     if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname)))
         return;
 
-    const int decodedLen = base64_decode_len(req->pub_auth);
+    size_t decodedLen = BASE64_DECODE_LENGTH(strlen(req->pub_auth));
     buf = (char*)xmalloc(decodedLen);
-    base64_decode(buf, decodedLen, req->pub_auth);
+    struct base64_decode_ctx ctx;
+    base64_decode_init(&ctx);
+    if (!base64_decode_update(&ctx, &decodedLen, reinterpret_cast<uint8_t*>(buf), strlen(req->pub_auth), reinterpret_cast<const uint8_t*>(req->pub_auth)) ||
+            !base64_decode_final(&ctx)) {
+        debug("cmgr: base64 decode failure. Incomplete auth token string.\n");
+        xfree(buf);
+        return;
+    }
 
     debug("cmgr: length ok\n");
 
     /* parse ( a lot of memory leaks, but that is cachemgr style :) */
-    if ((host_name = strtok(buf, "|")) == NULL)
+    if ((host_name = strtok(buf, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug("cmgr: decoded host: '%s'\n", host_name);
 
-    if ((time_str = strtok(NULL, "|")) == NULL)
+    if ((time_str = strtok(NULL, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug("cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now);
 
-    if ((user_name = strtok(NULL, "|")) == NULL)
+    if ((user_name = strtok(NULL, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug("cmgr: decoded uname: '%s'\n", user_name);
 
-    if ((passwd = strtok(NULL, "|")) == NULL)
+    if ((passwd = strtok(NULL, "|")) == NULL) {
+        xfree(buf);
         return;
+    }
 
     debug("cmgr: decoded passwd: '%s'\n", passwd);
 
     /* verify freshness and validity */
-    if (atoi(time_str) + passwd_ttl < now)
+    if (atoi(time_str) + passwd_ttl < now) {
+        xfree(buf);
         return;
+    }
 
-    if (strcasecmp(host_name, req->hostname))
+    if (strcasecmp(host_name, req->hostname)) {
+        xfree(buf);
         return;
+    }
 
     debug("cmgr: verified auth. info.\n");
 
     /* ok, accept */
-    xfree(req->user_name);
+    safe_free(req->user_name);
 
     req->user_name = xstrdup(user_name);
 
@@ -1151,15 +1190,20 @@ make_auth_header(const cachemgr_request * req)
     if (encodedLen <= 0)
         return "";
 
-    char *str64 = static_cast<char*>(xmalloc(encodedLen));
-    base64_encode_str(str64, encodedLen, buf, bufLen);
+    uint8_t *str64 = static_cast<uint8_t*>(xmalloc(encodedLen));
+    struct base64_encode_ctx ctx;
+    base64_encode_init(&ctx);
+    size_t blen = base64_encode_update(&ctx, str64, bufLen, reinterpret_cast<uint8_t*>(buf));
+    blen += base64_encode_final(&ctx, str64+blen);
+    str64[blen] = '\0';
 
-    stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64);
+    stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %.*s\r\n", (int)blen, str64);
 
     assert(stringLength < sizeof(buf));
 
-    snprintf(&buf[stringLength], sizeof(buf) - stringLength, "Proxy-Authorization: Basic %s\r\n", str64);
+    snprintf(&buf[stringLength], sizeof(buf) - stringLength, "Proxy-Authorization: Basic %.*s\r\n", (int)blen, str64);
 
+    xfree(str64);
     return buf;
 }
 
@@ -1224,7 +1268,7 @@ check_target_acl(const char *hostname, int port)
             if (strcmp(token, "*") == 0)
 
                 ;   /* Wildcard port specification */
-            else if (strcasecmp(token, "any") == 0)
+            else if (strcmp(token, "any") == 0)
 
                 ;   /* Wildcard port specification */
             else if (sscanf(token, "%d", &i) != 1)
@@ -1243,3 +1287,4 @@ check_target_acl(const char *hostname, int port)
     fclose(fp);
     return ret;
 }
+