From d5f21615719ee41caf8841e0480dd5affdc9b707 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Mon, 14 Jul 2014 05:58:03 -0700 Subject: [PATCH] Validate -n service name parameter value Service name is used for path prefixes in SHM/UDS sockets, Windows service name, Unix/Linux/BSD daemon names, and file path segments. Restrict service names to a max 32 character alphanumeric value in order to accommodate as widely portable names as possible in all these cases. --- src/WinSvc.cc | 64 ++++++++++++++++++++++++++----------------------- src/cache_cf.cc | 2 +- src/globals.h | 3 ++- src/ipc/Port.cc | 4 ++-- src/main.cc | 19 +++++++++++---- src/stat.cc | 6 ++--- 6 files changed, 56 insertions(+), 42 deletions(-) diff --git a/src/WinSvc.cc b/src/WinSvc.cc index 976ee9a8ac..385f4d1e31 100644 --- a/src/WinSvc.cc +++ b/src/WinSvc.cc @@ -510,7 +510,7 @@ int WIN32_Subsystem_Init(int * argc, char *** argv) 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; @@ -671,12 +671,13 @@ 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) */ @@ -686,7 +687,7 @@ WIN32_RemoveService() 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"); @@ -711,7 +712,7 @@ WIN32_RemoveService() 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); } @@ -723,12 +724,13 @@ WIN32_RemoveService() 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); @@ -743,19 +745,20 @@ WIN32_InstallService() 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 */ @@ -766,8 +769,8 @@ WIN32_InstallService() 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 */ @@ -801,7 +804,7 @@ WIN32_InstallService() 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 { @@ -821,8 +824,8 @@ WIN32_sendSignal(int WIN32_signal) 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) */ @@ -875,11 +878,11 @@ WIN32_sendSignal(int WIN32_signal) /* 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. */ @@ -887,12 +890,12 @@ WIN32_sendSignal(int WIN32_signal) 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); @@ -931,10 +934,11 @@ int main(int argc, char **argv) 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", diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 8ac2e8468b..413379339f 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -358,7 +358,7 @@ SubstituteMacro(char*& line, int& len, const char* macroName, const char* substS 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)); } diff --git a/src/globals.h b/src/globals.h index 0305e47d1b..e90bb92efb 100644 --- a/src/globals.h +++ b/src/globals.h @@ -36,6 +36,7 @@ #include "hash.h" #include "IoStats.h" #include "rfc2181.h" +#include "SBuf.h" extern char *ConfigFile; /* NULL */ extern char *IcpOpcodeStr[]; @@ -52,7 +53,7 @@ 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[]; diff --git a/src/ipc/Port.cc b/src/ipc/Port.cc index 1d8029cc2f..409b1d97f6 100644 --- a/src/ipc/Port.cc +++ b/src/ipc/Port.cc @@ -46,7 +46,7 @@ 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)); @@ -60,7 +60,7 @@ 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"); } diff --git a/src/main.cc b/src/main.cc index f388a8fa51..e07028552d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -73,6 +73,7 @@ #include "MemPool.h" #include "mime.h" #include "neighbors.h" +#include "parser/Tokenizer.h" #include "pconn.h" #include "peer_sourcehash.h" #include "peer_userhash.h" @@ -506,10 +507,18 @@ mainParseOptions(int argc, char *argv[]) /** \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 || *optarg == '\0') { + const SBuf t(optarg); + ::Parser::Tokenizer tok(t); + const CharacterSet chr = CharacterSet::ALPHA+CharacterSet::DIGIT; + if (!tok.prefix(service_name, chr) || !tok.atEnd()) + fatalf("Expected alphanumeric service name for the -n option but got: " SQUIDSBUFPH, SQUIDSBUFPRINT(service_name)); + if (service_name.length() > 32) + fatalf("Service name (-n option) must be limited to 32 characters but got %u", service_name.length()); + opt_signal_service = true; + } else { + fatal("A service name is required for the -n option"); + } break; #if USE_WIN32_SERVICE @@ -561,7 +570,7 @@ mainParseOptions(int argc, char *argv[]) /** \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); diff --git a/src/stat.cc b/src/stat.cc index 0e66be8fd4..8eba5d91f4 100644 --- a/src/stat.cc +++ b/src/stat.cc @@ -625,13 +625,13 @@ DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry) #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", -- 2.47.3