Browse Source

Handle virtual accounts when dumping service config.

If we are copying the service we need to build the virtual service
account name for the new service.
Iain Patterson 5 years ago
parent
commit
b76766ed76
4 changed files with 32 additions and 16 deletions
  1. 14 7
      account.cpp
  2. 1 0
      account.h
  3. 2 3
      gui.cpp
  4. 15 6
      settings.cpp

+ 14 - 7
account.cpp

@@ -234,19 +234,26 @@ int is_localsystem(const TCHAR *username) {
   return ret;
 }
 
+/* Build the virtual account name. */
+TCHAR *virtual_account(const TCHAR *service_name) {
+  size_t len = _tcslen(NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN) + _tcslen(service_name) + 2;
+  TCHAR *name = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR));
+  if (! name) {
+    print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("name"), _T("virtual_account"));
+    return 0;
+  }
+
+  _sntprintf_s(name, len, _TRUNCATE, _T("%s\\%s"), NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN, service_name);
+  return name;
+}
+
 /* Does the username represent a virtual account for the service? */
 int is_virtual_account(const TCHAR *service_name, const TCHAR *username) {
   if (! imports.IsWellKnownSid) return 0;
   if (! service_name) return 0;
   if (! username) return 0;
 
-  size_t len = _tcslen(NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN) + _tcslen(service_name) + 2;
-  TCHAR *canon = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR));
-  if (! canon) {
-    print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("is_virtual_account"));
-    return 0;
-  }
-  _sntprintf_s(canon, len, _TRUNCATE, _T("%s\\%s"), NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN, service_name);
+  TCHAR *canon = virtual_account(service_name);
   int ret = str_equiv(canon, username);
   HeapFree(GetProcessHeap(), 0, canon);
   return ret;

+ 1 - 0
account.h

@@ -19,6 +19,7 @@ int username_sid(const TCHAR *, SID **);
 int username_equiv(const TCHAR *, const TCHAR *);
 int canonicalise_username(const TCHAR *, TCHAR **);
 int is_localsystem(const TCHAR *);
+TCHAR *virtual_account(const TCHAR *);
 int is_virtual_account(const TCHAR *, const TCHAR *);
 const TCHAR *well_known_sid(SID *);
 const TCHAR *well_known_username(const TCHAR *);

+ 2 - 3
gui.cpp

@@ -465,13 +465,12 @@ int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service
   }
   else if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_VIRTUAL_SERVICE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
     if (service->username) HeapFree(GetProcessHeap(), 0, service->username);
-    service->usernamelen = _tcslen(NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN) + _tcslen(service->name) + 2;
-    service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
+    service->username = virtual_account(service->name);
     if (! service->username) {
       popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()"));
       return 6;
     }
-    _sntprintf_s(service->username, service->usernamelen, _TRUNCATE, _T("%s\\%s"), NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN, service->name);
+    service->usernamelen = _tcslen(service->username) + 1;
     service->password = 0;
     service->passwordlen = 0;
   }

+ 15 - 6
settings.cpp

@@ -1152,12 +1152,21 @@ int native_dump_objectname(const TCHAR *service_name, void *param, const TCHAR *
   int ret = native_get_objectname(service_name, param, name, default_value, value, additional);
   if (ret != 1) return ret;
 
-  /* Do we need to dump a dummy password? */
-  if (! well_known_username(value->string)) {
-    /* Parameters are the other way round. */
-    value_t inverted;
-    inverted.string = _T("****");
-    return setting_dump_string(service_name, (void *) REG_SZ, name, &inverted, value->string);
+  /* Properly checking for a virtual account requires the actual service name. */
+  if (! _tcsnicmp(NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN, value->string, _tcslen(NSSM_VIRTUAL_SERVICE_ACCOUNT_DOMAIN))) {
+    TCHAR *name = virtual_account(service_name);
+    if (! name) return -1;
+    HeapFree(GetProcessHeap(), 0, value->string);
+    value->string = name;
+  }
+  else {
+    /* Do we need to dump a dummy password? */
+    if (! well_known_username(value->string)) {
+      /* Parameters are the other way round. */
+      value_t inverted;
+      inverted.string = _T("****");
+      return setting_dump_string(service_name, (void *) REG_SZ, name, &inverted, value->string);
+    }
   }
   return setting_dump_string(service_name, (void *) REG_SZ, name, value, 0);
 }