Handle well-known account names.
[nssm.git] / service.cpp
index 91e726f..d01ece0 100644 (file)
@@ -1,8 +1,5 @@
 #include "nssm.h"\r
 \r
-/* This is explicitly a wide string. */\r
-#define NSSM_LOGON_AS_SERVICE_RIGHT L"SeServiceLogonRight"\r
-\r
 bool is_admin;\r
 bool use_critical_section;\r
 \r
@@ -475,7 +472,7 @@ int get_service_username(const TCHAR *service_name, const QUERY_SERVICE_CONFIG *
 \r
   if (! qsc) return 1;\r
 \r
-  if (str_equiv(qsc->lpServiceStartName, NSSM_LOCALSYSTEM_ACCOUNT)) return 0;\r
+  if (is_localsystem(qsc->lpServiceStartName)) return 0;\r
 \r
   size_t len = _tcslen(qsc->lpServiceStartName);\r
   *username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(TCHAR));\r
@@ -490,153 +487,6 @@ int get_service_username(const TCHAR *service_name, const QUERY_SERVICE_CONFIG *
   return 0;\r
 }\r
 \r
-int grant_logon_as_service(const TCHAR *username) {\r
-  if (! username) return 0;\r
-  if (str_equiv(username, NSSM_LOCALSYSTEM_ACCOUNT)) return 0;\r
-\r
-  /* Open Policy object. */\r
-  LSA_OBJECT_ATTRIBUTES attributes;\r
-  ZeroMemory(&attributes, sizeof(attributes));\r
-\r
-  LSA_HANDLE policy;\r
-\r
-  NTSTATUS status = LsaOpenPolicy(0, &attributes, POLICY_ALL_ACCESS, &policy);\r
-  if (status) {\r
-    print_message(stderr, NSSM_MESSAGE_LSAOPENPOLICY_FAILED, error_string(LsaNtStatusToWinError(status)));\r
-    return 1;\r
-  }\r
-\r
-  /* Look up SID for the account. */\r
-  LSA_UNICODE_STRING lsa_username;\r
-#ifdef UNICODE\r
-  lsa_username.Buffer = (wchar_t *) username;\r
-  lsa_username.Length = (unsigned short) _tcslen(username) * sizeof(TCHAR);\r
-  lsa_username.MaximumLength = lsa_username.Length + sizeof(TCHAR);\r
-#else\r
-  size_t buflen;\r
-  mbstowcs_s(&buflen, NULL, 0, username, _TRUNCATE);\r
-  lsa_username.MaximumLength = (unsigned short) buflen * sizeof(wchar_t);\r
-  lsa_username.Length = lsa_username.MaximumLength - sizeof(wchar_t);\r
-  lsa_username.Buffer = (wchar_t *) HeapAlloc(GetProcessHeap(), 0, lsa_username.MaximumLength);\r
-  if (lsa_username.Buffer) mbstowcs_s(&buflen, lsa_username.Buffer, lsa_username.MaximumLength, username, _TRUNCATE);\r
-  else {\r
-    LsaClose(policy);\r
-    print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("LSA_UNICODE_STRING"), _T("grant_logon_as_service()"));\r
-    return 2;\r
-  }\r
-#endif\r
-\r
-  LSA_REFERENCED_DOMAIN_LIST *translated_domains;\r
-  LSA_TRANSLATED_SID *translated_sid;\r
-  status = LsaLookupNames(policy, 1, &lsa_username, &translated_domains, &translated_sid);\r
-#ifndef UNICODE\r
-  HeapFree(GetProcessHeap(), 0, lsa_username.Buffer);\r
-#endif\r
-  if (status) {\r
-    LsaFreeMemory(translated_domains);\r
-    LsaFreeMemory(translated_sid);\r
-    LsaClose(policy);\r
-    print_message(stderr, NSSM_MESSAGE_LSALOOKUPNAMES_FAILED, username, error_string(LsaNtStatusToWinError(status)));\r
-    return 3;\r
-  }\r
-\r
-  if (translated_sid->Use != SidTypeUser) {\r
-    LsaFreeMemory(translated_domains);\r
-    LsaFreeMemory(translated_sid);\r
-    LsaClose(policy);\r
-    print_message(stderr, NSSM_GUI_INVALID_USERNAME, username);\r
-    return 4;\r
-  }\r
-\r
-  LSA_TRUST_INFORMATION *trust = &translated_domains->Domains[translated_sid->DomainIndex];\r
-  if (! trust || ! IsValidSid(trust->Sid)) {\r
-    LsaFreeMemory(translated_domains);\r
-    LsaFreeMemory(translated_sid);\r
-    LsaClose(policy);\r
-    print_message(stderr, NSSM_GUI_INVALID_USERNAME, username);\r
-    return 4;\r
-  }\r
-\r
-  /* GetSidSubAuthority*() return pointers! */\r
-  unsigned char *n = GetSidSubAuthorityCount(trust->Sid);\r
-\r
-  /* Convert translated SID to SID. */\r
-  SID *sid = (SID *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, GetSidLengthRequired(*n + 1));\r
-  if (! sid) {\r
-    LsaFreeMemory(translated_domains);\r
-    LsaFreeMemory(translated_sid);\r
-    LsaClose(policy);\r
-    print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("SID"), _T("grant_logon_as_service"));\r
-    return 4;\r
-  }\r
-\r
-  unsigned long error;\r
-  if (! InitializeSid(sid, GetSidIdentifierAuthority(trust->Sid), *n + 1)) {\r
-    error = GetLastError();\r
-    HeapFree(GetProcessHeap(), 0, sid);\r
-    LsaFreeMemory(translated_domains);\r
-    LsaFreeMemory(translated_sid);\r
-    LsaClose(policy);\r
-    print_message(stderr, NSSM_MESSAGE_INITIALIZESID_FAILED, username, error_string(error));\r
-    return 5;\r
-  }\r
-\r
-  for (unsigned char i = 0; i <= *n; i++) {\r
-    unsigned long *sub = GetSidSubAuthority(sid, i);\r
-    if (i < *n) *sub = *GetSidSubAuthority(trust->Sid, i);\r
-    else *sub = translated_sid->RelativeId;\r
-  }\r
-\r
-  LsaFreeMemory(translated_domains);\r
-  LsaFreeMemory(translated_sid);\r
-\r
-  /* Check if the SID has the "Log on as a service" right. */\r
-  LSA_UNICODE_STRING lsa_right;\r
-  lsa_right.Buffer = NSSM_LOGON_AS_SERVICE_RIGHT;\r
-  lsa_right.Length = (unsigned short) wcslen(lsa_right.Buffer) * sizeof(wchar_t);\r
-  lsa_right.MaximumLength = lsa_right.Length + sizeof(wchar_t);\r
-\r
-  LSA_UNICODE_STRING *rights;\r
-  unsigned long count = ~0;\r
-  status = LsaEnumerateAccountRights(policy, sid, &rights, &count);\r
-  if (status) {\r
-    /*\r
-      If the account has no rights set LsaEnumerateAccountRights() will return\r
-      STATUS_OBJECT_NAME_NOT_FOUND and set count to 0.\r
-    */\r
-    error = LsaNtStatusToWinError(status);\r
-    if (error != ERROR_FILE_NOT_FOUND) {\r
-      HeapFree(GetProcessHeap(), 0, sid);\r
-      LsaClose(policy);\r
-      print_message(stderr, NSSM_MESSAGE_LSAENUMERATEACCOUNTRIGHTS_FAILED, username, error_string(error));\r
-      return 4;\r
-    }\r
-  }\r
-\r
-  for (unsigned long i = 0; i < count; i++) {\r
-    if (rights[i].Length != lsa_right.Length) continue;\r
-    if (_wcsnicmp(rights[i].Buffer, lsa_right.Buffer, lsa_right.MaximumLength)) continue;\r
-    /* The SID has the right. */\r
-    HeapFree(GetProcessHeap(), 0, sid);\r
-    LsaFreeMemory(rights);\r
-    LsaClose(policy);\r
-    return 0;\r
-  }\r
-  LsaFreeMemory(rights);\r
-\r
-  /* Add the right. */\r
-  status = LsaAddAccountRights(policy, sid, &lsa_right, 1);\r
-  HeapFree(GetProcessHeap(), 0, sid);\r
-  LsaClose(policy);\r
-  if (status) {\r
-    print_message(stderr, NSSM_MESSAGE_LSAADDACCOUNTRIGHTS_FAILED, error_string(LsaNtStatusToWinError(status)));\r
-    return 5;\r
-  }\r
-\r
-  print_message(stdout, NSSM_MESSAGE_GRANTED_LOGON_AS_SERVICE, username);\r
-  return 0;\r
-}\r
-\r
 /* Set default values which aren't zero. */\r
 void set_nssm_service_defaults(nssm_service_t *service) {\r
   if (! service) return;\r
@@ -1084,9 +934,11 @@ int edit_service(nssm_service_t *service, bool editing) {
   }\r
   else if (editing) username = NSSM_LOCALSYSTEM_ACCOUNT;\r
 \r
-  if (grant_logon_as_service(username)) {\r
-    print_message(stderr, NSSM_MESSAGE_GRANT_LOGON_AS_SERVICE_FAILED, username);\r
-    return 5;\r
+  if (requires_password(username)) {\r
+    if (grant_logon_as_service(username)) {\r
+      print_message(stderr, NSSM_MESSAGE_GRANT_LOGON_AS_SERVICE_FAILED, username);\r
+      return 5;\r
+    }\r
   }\r
 \r
   if (! ChangeServiceConfig(service->handle, service->type, startup, SERVICE_NO_CHANGE, 0, 0, 0, 0, username, password, service->displayname)) {\r