Update the service_name global to an SBuf and use Tokenizer to validate the -n argument is a pure alphanumeric.
Amos
=== modified file 'src/WinSvc.cc' --- src/WinSvc.cc 2014-01-24 01:57:15 +0000 +++ src/WinSvc.cc 2014-06-14 14:20:56 +0000 @@ -493,41 +493,41 @@ #if defined(_MSC_VER) /* Microsoft C Compiler ONLY */ newHandler = Squid_Win32InvalidParameterHandler; oldHandler = _set_invalid_parameter_handler(newHandler); _CrtSetReportMode(_CRT_ASSERT, 0); #endif #if USE_WIN32_SERVICE if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) { char path[512]; HKEY hndKey; if (signal(SIGABRT, WIN32_Abort) == SIG_ERR) return 1; /* Register the service Handler function */ - svcHandle = RegisterServiceCtrlHandler(service_name, WIN32_svcHandler); + svcHandle = RegisterServiceCtrlHandler(service_name.c_str(), WIN32_svcHandler); if (svcHandle == 0) return 1; /* Set Process work dir to directory cointaining squid.exe */ GetModuleFileName(NULL, path, 512); WIN32_module_name=xstrdup(path); path[strlen(path) - 10] = '\0'; if (SetCurrentDirectory(path) == 0) return 1; safe_free(ConfigFile); /* get config file from Windows Registry */ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) { DWORD Type = 0; DWORD Size = 0; @@ -654,192 +654,195 @@ status = GetLastError(); debugs(1, DBG_IMPORTANT, "SetServiceStatus error " << status); } debugs(1, DBG_IMPORTANT, "Leaving Squid service"); break; default: debugs(1, DBG_IMPORTANT, "Unrecognized opcode " << Opcode); } return; } void WIN32_RemoveService() { SC_HANDLE schService; SC_HANDLE schSCManager; - if (!service_name) - service_name = xstrdup(APP_SHORTNAME); + if (service_name.isEmpty()) + service_name = SBuf(APP_SHORTNAME); - strcat(REGKEY, service_name); + const char *service = service_name.c_str(); + strcat(REGKEY, service); - keys[4] = service_name; + keys[4] = service; schSCManager = OpenSCManager(NULL, /* machine (NULL == local) */ NULL, /* database (NULL == default) */ SC_MANAGER_ALL_ACCESS /* access required */ ); if (!schSCManager) fprintf(stderr, "OpenSCManager failed\n"); else { - schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS); + schService = OpenService(schSCManager, service, SERVICE_ALL_ACCESS); if (schService == NULL) fprintf(stderr, "OpenService failed\n"); /* Could not open the service */ else { /* try to stop the service */ if (ControlService(schService, _WIN_SQUID_SERVICE_CONTROL_STOP, &svcStatus)) { sleep(1); while (QueryServiceStatus(schService, &svcStatus)) { if (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) sleep(1); else break; } } /* now remove the service */ if (DeleteService(schService) == 0) fprintf(stderr, "DeleteService failed.\n"); else - printf("Service %s deleted successfully.\n", service_name); + printf("Service " SQUIDSBUFPH " deleted successfully.\n", SQUIDSBUFPRINT(service_name)); CloseServiceHandle(schService); } CloseServiceHandle(schSCManager); } } void WIN32_SetServiceCommandLine() { - if (!service_name) - service_name = xstrdup(APP_SHORTNAME); + if (service_name.isEmpty()) + service_name = SBuf(APP_SHORTNAME); - strcat(REGKEY, service_name); + const char *service = servie_name.c_str(); + strcat(REGKEY, service); - keys[4] = service_name; + keys[4] = service; /* Now store the Service Command Line in the registry */ WIN32_StoreKey(COMMANDLINE, REG_SZ, (unsigned char *) WIN32_Command_Line, strlen(WIN32_Command_Line) + 1); } void WIN32_InstallService() { SC_HANDLE schService; SC_HANDLE schSCManager; char ServicePath[512]; char szPath[512]; int lenpath; - if (!service_name) - service_name = xstrdup(APP_SHORTNAME); + if (service_name.isEmpty()) + service_name = SBuf(APP_SHORTNAME); - strcat(REGKEY, service_name); + const char *service = service_name.c_str(); + strcat(REGKEY, service); - keys[4] = service_name; + keys[4] = service; if ((lenpath = GetModuleFileName(NULL, ServicePath, 512)) == 0) { fprintf(stderr, "Can't get executable path\n"); exit(1); } - snprintf(szPath, sizeof(szPath), "%s %s:%s", ServicePath, _WIN_SQUID_SERVICE_OPTION, service_name); + snprintf(szPath, sizeof(szPath), "%s %s:" SQUIDSBUFPH, ServicePath, _WIN_SQUID_SERVICE_OPTION, SQUIDSBUFPRINT(service_name)); schSCManager = OpenSCManager(NULL, /* machine (NULL == local) */ NULL, /* database (NULL == default) */ SC_MANAGER_ALL_ACCESS /* access required */ ); if (!schSCManager) { fprintf(stderr, "OpenSCManager failed\n"); exit(1); } else { schService = CreateService(schSCManager, /* SCManager database */ - service_name, /* name of service */ - service_name, /* name to display */ + service, /* name of service */ + service, /* name to display */ SERVICE_ALL_ACCESS, /* desired access */ SERVICE_WIN32_OWN_PROCESS, /* service type */ SERVICE_AUTO_START, /* start type */ SERVICE_ERROR_NORMAL, /* error control type */ (const char *) szPath, /* service's binary */ NULL, /* no load ordering group */ NULL, /* no tag identifier */ "Tcpip\0AFD\0", /* dependencies */ NULL, /* LocalSystem account */ NULL); /* no password */ if (schService) { if (WIN32_OS_version > _WIN_OS_WINNT) { HMODULE ADVAPI32Handle; PFChangeServiceConfig2 ChangeServiceConfig2; DWORD dwInfoLevel = SERVICE_CONFIG_DESCRIPTION; ADVAPI32Handle = GetModuleHandle("advapi32"); ChangeServiceConfig2 = (PFChangeServiceConfig2) GetProcAddress(ADVAPI32Handle, CHANGESERVICECONFIG2); ChangeServiceConfig2(schService, dwInfoLevel, &Squid_ServiceDescription); dwInfoLevel = SERVICE_CONFIG_FAILURE_ACTIONS; ChangeServiceConfig2(schService, dwInfoLevel, &Squid_ServiceFailureActions); } CloseServiceHandle(schService); /* Now store the config file location in the registry */ if (!ConfigFile) ConfigFile = xstrdup(DefaultConfigFile); WIN32_StoreKey(CONFIGFILE, REG_SZ, (unsigned char *) ConfigFile, strlen(ConfigFile) + 1); printf("Squid Cache version %s for %s\n", version_string, CONFIG_HOST_TYPE); - printf("installed successfully as %s Windows System Service.\n", service_name); + printf("installed successfully as " SQUIDSBUFPH " Windows System Service.\n", SQUIDSBUFPRINT(service_name)); printf("To run, start it from the Services Applet of Control Panel.\n"); printf("Don't forget to edit squid.conf before starting it.\n\n"); } else { fprintf(stderr, "CreateService failed\n"); exit(1); } CloseServiceHandle(schSCManager); } } void WIN32_sendSignal(int WIN32_signal) { SERVICE_STATUS ssStatus; DWORD fdwAccess, fdwControl; SC_HANDLE schService; SC_HANDLE schSCManager; - if (!service_name) - service_name = xstrdup(APP_SHORTNAME); + if (service_name.isEmpty()) + service_name = SBuf(APP_SHORTNAME); schSCManager = OpenSCManager(NULL, /* machine (NULL == local) */ NULL, /* database (NULL == default) */ SC_MANAGER_ALL_ACCESS /* access required */ ); if (!schSCManager) { fprintf(stderr, "OpenSCManager failed\n"); exit(1); } /* The required service object access depends on the control. */ switch (WIN32_signal) { case 0: /* SIGNULL */ fdwAccess = SERVICE_INTERROGATE; fdwControl = _WIN_SQUID_SERVICE_CONTROL_INTERROGATE; break; case SIGUSR1: @@ -858,100 +861,101 @@ break; case SIGTERM: fdwAccess = SERVICE_STOP; fdwControl = _WIN_SQUID_SERVICE_CONTROL_STOP; break; case SIGINT: case SIGKILL: fdwAccess = SERVICE_USER_DEFINED_CONTROL; fdwControl = _WIN_SQUID_SERVICE_CONTROL_INTERRUPT; break; default: exit(1); } /* Open a handle to the service. */ schService = OpenService(schSCManager, /* SCManager database */ - service_name, /* name of service */ + service_name.c_str(), /* name of service */ fdwAccess); /* specify access */ if (schService == NULL) { - fprintf(stderr, "%s: ERROR: Could not open Service %s\n", APP_SHORTNAME, service_name); + fprintf(stderr, "%s: ERROR: Could not open Service " SQUIDSBUFPH "\n", APP_SHORTNAME, SQUIDSBUFPRINT(service_name)); exit(1); } else { /* Send a control value to the service. */ if (!ControlService(schService, /* handle of service */ fdwControl, /* control value to send */ &ssStatus)) { /* address of status info */ - fprintf(stderr, "%s: ERROR: Could not Control Service %s\n", - APP_SHORTNAME, service_name); + fprintf(stderr, "%s: ERROR: Could not Control Service " SQUIDSBUFPH "\n", + APP_SHORTNAME, SQUIDSBUFPRINT(service_name)); exit(1); } else { /* Print the service status. */ - printf("\nStatus of %s Service:\n", service_name); + printf("\nStatus of " SQUIDSBUFPH " Service:\n", SQUIDSBUFPRINT(service_name)); printf(" Service Type: 0x%lx\n", ssStatus.dwServiceType); printf(" Current State: 0x%lx\n", ssStatus.dwCurrentState); printf(" Controls Accepted: 0x%lx\n", ssStatus.dwControlsAccepted); printf(" Exit Code: %ld\n", ssStatus.dwWin32ExitCode); printf(" Service Specific Exit Code: %ld\n", ssStatus.dwServiceSpecificExitCode); printf(" Check Point: %ld\n", ssStatus.dwCheckPoint); printf(" Wait Hint: %ld\n", ssStatus.dwWaitHint); } CloseServiceHandle(schService); } CloseServiceHandle(schSCManager); } int main(int argc, char **argv) { SERVICE_TABLE_ENTRY DispatchTable[] = { {NULL, SquidWinSvcMain}, {NULL, NULL} }; char *c; char stderr_path[256]; SetErrorMode(SEM_NOGPFAULTERRORBOX); if ((argc == 2) && strstr(argv[1], _WIN_SQUID_SERVICE_OPTION)) { strcpy(stderr_path, argv[0]); strcat(stderr_path,".log"); freopen(stderr_path, "w", stderr); setmode(fileno(stderr), O_TEXT); WIN32_run_mode = _WIN_SQUID_RUN_MODE_SERVICE; if (!(c=strchr(argv[1],':'))) { fprintf(stderr, "Bad Service Parameter: %s\n", argv[1]); return 1; } - service_name = xstrdup(c+1); - DispatchTable[0].lpServiceName=service_name; - strcat(REGKEY, service_name); - keys[4] = service_name; + service_name = SBuf(c+1); + const char *service = service_name.c_str(); + DispatchTable[0].lpServiceName=service; + strcat(REGKEY, service); + keys[4] = service; if (!StartServiceCtrlDispatcher(DispatchTable)) { fprintf(stderr, "StartServiceCtrlDispatcher error = %ld\n", GetLastError()); return 1; } } else { WIN32_run_mode = _WIN_SQUID_RUN_MODE_INTERACTIVE; opt_no_daemon = 1; return SquidMain(argc, argv); } return 0; } #endif /* USE_WIN32_SERVICE */ static int Win32SockInit(void) { === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2014-06-02 06:23:12 +0000 +++ src/cache_cf.cc 2014-06-14 06:44:00 +0000 @@ -365,41 +365,41 @@ // copy new substring in place memcpy(str + substrIdx, newSubstr, newSubstrLen); len = strlen(str); } static void SubstituteMacro(char*& line, int& len, const char* macroName, const char* substStr) { assert(line != NULL); assert(macroName != NULL); assert(substStr != NULL); unsigned macroNameLen = strlen(macroName); while (const char* macroPos = strstr(line, macroName)) // we would replace all occurrences ReplaceSubstr(line, len, macroPos - line, macroNameLen, substStr); } static void ProcessMacros(char*& line, int& len) { - SubstituteMacro(line, len, "${service_name}", service_name); + SubstituteMacro(line, len, "${service_name}", service_name.c_str()); SubstituteMacro(line, len, "${process_name}", TheKidName); SubstituteMacro(line, len, "${process_number}", xitoa(KidIdentifier)); } static void trim_trailing_ws(char* str) { assert(str != NULL); unsigned i = strlen(str); while ((i > 0) && xisspace(str[i - 1])) --i; str[i] = '\0'; } static const char* FindStatement(const char* line, const char* statement) { assert(line != NULL); assert(statement != NULL); === modified file 'src/globals.h' --- src/globals.h 2014-03-23 02:56:12 +0000 +++ src/globals.h 2014-06-14 06:37:05 +0000 @@ -19,57 +19,58 @@ * * 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. * */ #ifndef SQUID_GLOBALS_H #define SQUID_GLOBALS_H #include "acl/AclDenyInfoList.h" #include "CacheDigest.h" #include "defines.h" #include "hash.h" #include "IoStats.h" #include "rfc2181.h" +#include "SBuf.h" extern char *ConfigFile; /* NULL */ extern char *IcpOpcodeStr[]; extern char tmp_error_buf[ERROR_BUF_SZ]; extern char ThisCache[RFC2181_MAXHOSTNAMELEN << 1]; extern char ThisCache2[RFC2181_MAXHOSTNAMELEN << 1]; extern char config_input_line[BUFSIZ]; /// During parsing, the name of the current squid.conf directive being parsed. extern const char *cfg_directive; /* NULL */ extern const char *DefaultConfigFile; /* DEFAULT_CONFIG_FILE */ extern const char *cfg_filename; /* NULL */ extern const char *dash_str; /* "-" */ extern const char *null_string; /* "" */ extern const char *version_string; /* VERSION */ extern const char *appname_string; /* PACKAGE */ extern char const *visible_appname_string; /* NULL */ -extern char *service_name; /* xstrdup(APP_SHORTNAME) */ +extern SBuf service_name; /* SBuf(APP_SHORTNAME) */ extern const char *fdTypeStr[]; extern const char *hier_strings[]; extern const char *memStatusStr[]; extern const char *pingStatusStr[]; extern const char *storeStatusStr[]; extern const char *swapStatusStr[]; extern int Biggest_FD; /* -1 */ extern int Number_FD; /* 0 */ extern int Opening_FD; /* 0 */ extern int NDnsServersAlloc; /* 0 */ extern int RESERVED_FD; extern int Squid_MaxFD; /* SQUID_MAXFD */ extern int config_lineno; /* 0 */ extern int opt_reuseaddr; /* 1 */ extern int neighbors_do_private_keys; /* 1 */ extern int opt_catch_signals; /* 1 */ extern int opt_foreground_rebuild; /* 0 */ extern char *opt_forwarded_for; /* NULL */ extern int opt_reload_hit_only; /* 0 */ === modified file 'src/ipc/Port.cc' --- src/ipc/Port.cc 2014-06-05 14:57:58 +0000 +++ src/ipc/Port.cc 2014-06-14 06:45:23 +0000 @@ -29,54 +29,54 @@ void Ipc::Port::doListen() { debugs(54, 6, HERE); buf.prepForReading(); typedef CommCbMemFunT<Port, CommIoCbParams> Dialer; AsyncCall::Pointer readHandler = JobCallback(54, 6, Dialer, this, Port::noteRead); comm_read(conn(), buf.raw(), buf.size(), readHandler); } bool Ipc::Port::doneAll() const { return false; // listen forever } String Ipc::Port::MakeAddr(const char* processLabel, int id) { assert(id >= 0); String addr = channelPathPfx; - addr.append(service_name); + addr.append(service_name.c_str()); addr.append(processLabel); addr.append('-'); addr.append(xitoa(id)); addr.append(".ipc"); return addr; } String Ipc::Port::CoordinatorAddr() { static String coordinatorAddr; if (!coordinatorAddr.size()) { coordinatorAddr= channelPathPfx; - coordinatorAddr.append(service_name); + coordinatorAddr.append(service_name.c_str()); coordinatorAddr.append(coordinatorAddrLabel); coordinatorAddr.append(".ipc"); } return coordinatorAddr; } void Ipc::Port::noteRead(const CommIoCbParams& params) { debugs(54, 6, HERE << params.conn << " flag " << params.flag << " [" << this << ']'); if (params.flag == Comm::OK) { assert(params.buf == buf.raw()); receive(buf); } // TODO: if there was a fatal error on our socket, close the socket before // trying to listen again and print a level-1 error message. doListen(); } === modified file 'src/main.cc' --- src/main.cc 2014-06-02 07:19:35 +0000 +++ src/main.cc 2014-06-15 05:23:25 +0000 @@ -56,40 +56,41 @@ #include "fqdncache.h" #include "fs/Module.h" #include "FwdState.h" #include "globals.h" #include "htcp.h" #include "HttpHeader.h" #include "HttpReply.h" #include "icmp/IcmpSquid.h" #include "icmp/net_db.h" #include "ICP.h" #include "ident/Ident.h" #include "ip/tools.h" #include "ipc/Coordinator.h" #include "ipc/Kids.h" #include "ipc/Strand.h" #include "ipcache.h" #include "Mem.h" #include "MemPool.h" #include "mime.h" #include "neighbors.h" +#include "parser/Tokenizer.h" #include "pconn.h" #include "peer_sourcehash.h" #include "peer_userhash.h" #include "PeerSelectState.h" #include "profiler/Profiler.h" #include "redirect.h" #include "refresh.h" #include "send-announce.h" #include "SquidConfig.h" #include "SquidDns.h" #include "SquidTime.h" #include "stat.h" #include "StatCounters.h" #include "Store.h" #include "store_log.h" #include "StoreFileSystem.h" #include "SwapDir.h" #include "tools.h" #include "unlinkd.h" #include "URL.h" @@ -489,44 +490,50 @@ break; case 'm': /** \par m * Set global malloc_debug_level to the value given following the option. * if none is given it toggles the xmalloc_trace option on/off */ if (optarg) { #if MALLOC_DBG malloc_debug_level = atoi(optarg); #else fatal("Need to add -DMALLOC_DBG when compiling to use -mX option"); #endif } break; case 'n': /** \par n * Set global option opt_signal_service (to true). * Stores the additional parameter given in global service_name */ - // XXX: verify that the new name has ONLY alphanumeric characters - xfree(service_name); - service_name = xstrdup(optarg); - opt_signal_service = true; + if (optarg) { + SBuf t(optarg); + ::Parser::Tokenizer tok(t); + const CharacterSet chr = CharacterSet::ALPHA+CharacterSet::DIGIT; + if (!tok.prefix(service_name, chr) || !tok.atEnd()) + fatal("Need to provide alphanumeric service name when using -n option"); + opt_signal_service = true; + } else { + fatal("Need to provide alphanumeric service name when using -n option"); + } break; #if USE_WIN32_SERVICE case 'r': /** \par r * Set global option opt_remove_service (to TRUE) */ opt_remove_service = TRUE; break; #endif case 'l': /** \par l * Stores the syslog facility name in global opt_syslog_facility * then performs actions for -s option. */ xfree(opt_syslog_facility); // ignore any previous options sent opt_syslog_facility = xstrdup(optarg); @@ -544,41 +551,41 @@ fatal("Logging to syslog not available on this platform"); /* NOTREACHED */ #endif case 'u': /** \par u * Store the ICP port number given in global option icpPortNumOverride * ensuring its a positive number. */ icpPortNumOverride = atoi(optarg); if (icpPortNumOverride < 0) icpPortNumOverride = 0; break; case 'v': /** \par v * Display squid version and build information. Then exit. */ printf("Squid Cache: Version %s\n" ,version_string); - printf("Service Name: %s\n", service_name); + printf("Service Name: " SQUIDSBUFPH "\n", SQUIDSBUFPRINT(service_name)); if (strlen(SQUID_BUILD_INFO)) printf("%s\n",SQUID_BUILD_INFO); printf( "configure options: %s\n", SQUID_CONFIGURE_OPTIONS); #if USE_WIN32_SERVICE printf("Compiled as Windows System Service.\n"); #endif exit(0); /* NOTREACHED */ case 'z': /** \par z * Set global option Debug::log_stderr and opt_create_swap_dirs */ Debug::log_stderr = 1; opt_create_swap_dirs = 1; break; === modified file 'src/stat.cc' --- src/stat.cc 2014-03-30 12:00:34 +0000 +++ src/stat.cc 2014-06-14 14:20:27 +0000 @@ -608,47 +608,47 @@ } stats.max_fd = Squid_MaxFD; stats.biggest_fd = Biggest_FD; stats.number_fd = Number_FD; stats.opening_fd = Opening_FD; stats.num_fd_free = fdNFree(); stats.reserved_fd = RESERVED_FD; } void DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry) { storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n", version_string); storeAppendPrintf(sentry, "Build Info: " SQUID_BUILD_INFO "\n"); #if _SQUID_WINDOWS_ if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) { - storeAppendPrintf(sentry,"\nRunning as %s Windows System Service on %s\n", - Service_name, WIN32_OS_string); + storeAppendPrintf(sentry,"\nRunning as " SQUIDSBUFPH " Windows System Service on %s\n", + SQUIDBUFPRINT(service_name), WIN32_OS_string); storeAppendPrintf(sentry,"Service command line is: %s\n", WIN32_Service_Command_Line); } else storeAppendPrintf(sentry,"Running on %s\n",WIN32_OS_string); #else - storeAppendPrintf(sentry,"Service Name: %s\n", service_name); + storeAppendPrintf(sentry,"Service Name: " SQUIDSBUFPH "\n", SQUIDSBUFPRINT(service_name)); #endif storeAppendPrintf(sentry, "Start Time:\t%s\n", mkrfc1123(stats.squid_start.tv_sec)); storeAppendPrintf(sentry, "Current Time:\t%s\n", mkrfc1123(stats.current_time.tv_sec)); storeAppendPrintf(sentry, "Connection information for %s:\n",APP_SHORTNAME); storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%.0f\n", stats.client_http_clients); storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%.0f\n", stats.client_http_requests); storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%.0f\n", stats.icp_pkts_recv); storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%.0f\n",