}
int ret = 0;
- if (translated_sid->Use == SidTypeWellKnownGroup && requires_password(*sid)) {
+ if (translated_sid->Use == SidTypeWellKnownGroup && ! well_known_sid(*sid)) {
print_message(stderr, NSSM_GUI_INVALID_USERNAME, username);
ret = 8;
}
}
/*
- Find the canonical name for a well-known account name.
- MUST ONLY BE USED for well-known account names.
- Must call LocalFree() on result.
+ Get well-known alias for LocalSystem and friends.
+ Returns a pointer to a static string. DO NOT try to free it.
*/
-TCHAR *canonical_username(const TCHAR *username) {
- SID *user_sid;
- TCHAR *canon;
- size_t len;
-
- if (is_localsystem(username)) {
- len = (_tcslen(NSSM_LOCALSYSTEM_ACCOUNT) + 1) * sizeof(TCHAR);
- canon = (TCHAR *) LocalAlloc(LPTR, len);
- if (! canon) {
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, NSSM_LOCALSYSTEM_ACCOUNT, _T("canonical_username"));
- return 0;
- }
- memmove(canon, NSSM_LOCALSYSTEM_ACCOUNT, len);
- _tprintf(_T("it's localsystem = %s!\n"), canon);
- return canon;
- }
-
- if (! imports.CreateWellKnownSid) return 0;
-
- if (username_sid(username, &user_sid)) return 0;
-
- /*
- LsaLookupSids will return the canonical username but the result won't
- include the NT Authority part. Thus we must look that up as well.
- */
- unsigned long ntsidsize = SECURITY_MAX_SID_SIZE;
- SID *ntauth_sid = (SID *) HeapAlloc(GetProcessHeap(), 0, ntsidsize);
- if (! ntauth_sid) {
- HeapFree(GetProcessHeap(), 0, user_sid);
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("NT Authority"), _T("canonical_username"));
- return 0;
- }
-
- if (! imports.CreateWellKnownSid(WinNtAuthoritySid, NULL, ntauth_sid, &ntsidsize)) {
- HeapFree(GetProcessHeap(), 0, ntauth_sid);
- print_message(stderr, NSSM_MESSAGE_CREATEWELLKNOWNSID_FAILED, _T("WinNtAuthoritySid"));
- return 0;
- }
-
- LSA_HANDLE policy;
- if (open_lsa_policy(&policy)) return 0;
-
- LSA_REFERENCED_DOMAIN_LIST *translated_domains;
- LSA_TRANSLATED_NAME *translated_names;
-
- unsigned long n = 2;
- PSID *sids = (PSID *) HeapAlloc(GetProcessHeap(), 0, n * sizeof(PSID));
- sids[0] = user_sid;
- sids[1] = ntauth_sid;
-
- NTSTATUS status = LsaLookupSids(policy, n, (PSID *) sids, &translated_domains, &translated_names);
- HeapFree(GetProcessHeap(), 0, user_sid);
- HeapFree(GetProcessHeap(), 0, ntauth_sid);
- HeapFree(GetProcessHeap(), 0, sids);
- LsaClose(policy);
- if (status) {
- print_message(stderr, NSSM_MESSAGE_LSALOOKUPSIDS_FAILED);
- return 0;
- }
-
- /* Look up the account name. */
- LSA_TRANSLATED_NAME *translated_name = &(translated_names[0]);
- if (translated_name->Use != SidTypeWellKnownGroup) {
- print_message(stderr, NSSM_GUI_INVALID_USERNAME);
- LsaFreeMemory(translated_domains);
- LsaFreeMemory(translated_names);
- return 0;
- }
-
- LSA_UNICODE_STRING *lsa_group = &translated_name->Name;
-
- /* Look up NT Authority. */
- translated_name = &(translated_names[1]);
- if (translated_name->Use != SidTypeDomain) {
- print_message(stderr, NSSM_GUI_INVALID_USERNAME);
- LsaFreeMemory(translated_domains);
- LsaFreeMemory(translated_names);
- return 0;
- }
-
- /* In theory these pointers should all be valid if we got this far... */
- LSA_TRUST_INFORMATION *trust = &translated_domains->Domains[translated_name->DomainIndex];
- LSA_UNICODE_STRING *lsa_domain = &trust->Name;
-
- TCHAR *domain, *group;
- unsigned long lsa_domain_len = lsa_domain->Length;
- unsigned long lsa_group_len = lsa_group->Length;
- len = lsa_domain_len + lsa_group_len + 2;
-
-#ifdef UNICODE
- domain = lsa_domain->Buffer;
- group = lsa_group->Buffer;
-#else
- size_t buflen;
-
- wcstombs_s(&buflen, NULL, 0, lsa_domain->Buffer, _TRUNCATE);
- domain = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, buflen);
- if (! domain) {
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("domain"), _T("canonical_username"));
- LsaFreeMemory(translated_domains);
- LsaFreeMemory(translated_names);
- return 0;
- }
- wcstombs_s(&buflen, (char *) domain, buflen, lsa_domain->Buffer, _TRUNCATE);
-
- wcstombs_s(&buflen, NULL, 0, lsa_group->Buffer, _TRUNCATE);
- group = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, buflen);
- if (! group) {
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("group"), _T("canonical_username"));
- LsaFreeMemory(translated_domains);
- LsaFreeMemory(translated_names);
- return 0;
- }
- wcstombs_s(&buflen, (char *) group, buflen, lsa_group->Buffer, _TRUNCATE);
-#endif
-
- canon = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR));
- if (! canon) {
- LsaFreeMemory(translated_domains);
- LsaFreeMemory(translated_names);
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("canonical_username"));
- return 0;
- }
-
- _sntprintf_s(canon, len, _TRUNCATE, _T("%s\\%s"), domain, group);
-
-#ifndef UNICODE
- HeapFree(GetProcessHeap(), 0, domain);
- HeapFree(GetProcessHeap(), 0, group);
-#endif
-
- LsaFreeMemory(translated_domains);
- LsaFreeMemory(translated_names);
-
- return canon;
-}
-
-/* Does the SID type require a password? */
-int requires_password(SID *sid) {
- if (! imports.IsWellKnownSid) return -1;
- if (imports.IsWellKnownSid(sid, WinLocalSystemSid)) return 0;
- if (imports.IsWellKnownSid(sid, WinLocalServiceSid)) return 0;
- if (imports.IsWellKnownSid(sid, WinNetworkServiceSid)) return 0;;
- return 1;
+const TCHAR *well_known_sid(SID *sid) {
+ if (! imports.IsWellKnownSid) return 0;
+ if (imports.IsWellKnownSid(sid, WinLocalSystemSid)) return NSSM_LOCALSYSTEM_ACCOUNT;
+ if (imports.IsWellKnownSid(sid, WinLocalServiceSid)) return NSSM_LOCALSERVICE_ACCOUNT;
+ if (imports.IsWellKnownSid(sid, WinNetworkServiceSid)) return NSSM_NETWORKSERVICE_ACCOUNT;
+ return 0;
}
-/* Does the username require a password? */
-int requires_password(const TCHAR *username) {
- if (str_equiv(username, NSSM_LOCALSYSTEM_ACCOUNT)) return 0;
-
+const TCHAR *well_known_username(const TCHAR *username) {
+ if (str_equiv(username, NSSM_LOCALSYSTEM_ACCOUNT)) return NSSM_LOCALSYSTEM_ACCOUNT;
SID *sid;
int r = username_sid(username, &sid);
if (username_sid(username, &sid)) return 0;
- int ret = 0;
- ret = requires_password(sid);
-
+ const TCHAR *well_known = well_known_sid(sid);
FreeSid(sid);
- return ret;
+ return well_known;
}
int grant_logon_as_service(const TCHAR *username) {
if (! username) return 0;
- if (! requires_password(username)) return 0;
/* Open Policy object. */
LSA_OBJECT_ATTRIBUTES attributes;
return 2;
}
+ /*
+ Shouldn't happen because it should have been checked before callling this function.
+ */
+ if (well_known_sid(sid)) {
+ LsaClose(policy);
+ return 3;
+ }
+
/* Check if the SID has the "Log on as a service" right. */
LSA_UNICODE_STRING lsa_right;
lsa_right.Buffer = NSSM_LOGON_AS_SERVICE_RIGHT;
Special case for well-known accounts.\r
Ignore the password if we're editing and the username hasn't changed.\r
*/\r
- if (! requires_password(service->username)) {\r
- if (is_localsystem(service->username)) {
+ const TCHAR *well_known = well_known_username(service->username);
+ if (well_known) {\r
+ if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) {
HeapFree(GetProcessHeap(), 0, service->username);\r
service->username = 0;\r
service->usernamelen = 0;\r
}
else {
- TCHAR *canon = canonical_username(service->username);
- HeapFree(GetProcessHeap(), 0, service->username);\r
- service->username = 0;\r
- service->usernamelen = 0;\r
- if (canon) {
- service->usernamelen = _tcslen(canon) + 1;
- service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
- if (! service->username) {
- LocalFree(canon);
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()"));
- return 6;
- }
- memmove(service->username, canon, service->usernamelen * sizeof(TCHAR));
- LocalFree(canon);
+ service->usernamelen = _tcslen(well_known) + 1;
+ service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
+ if (! service->username) {
+ print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()"));
+ return 6;
}
- else return 6;
+ memmove(service->username, well_known, service->usernamelen * sizeof(TCHAR));
}
}\r
else {\r
bool localsystem = false;
TCHAR *username = NSSM_LOCALSYSTEM_ACCOUNT;
TCHAR *password = 0;
- TCHAR *canon = 0;
if (additional) {
username = (TCHAR *) additional;
if (value && value->string) password = value->string;
}
else if (value && value->string) username = value->string;
- if (requires_password(username)) {
- if (! password) {
- /* We need a password if the account requires it. */
- print_message(stderr, NSSM_MESSAGE_MISSING_PASSWORD, name);
- return -1;
- }
+ const TCHAR *well_known = well_known_username(username);
+ size_t passwordsize = 0;
+ if (well_known) {
+ if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) localsystem = true;
+ username = (TCHAR *) well_known;
+ password = _T("");
}
- else {
- password = 0;
- if (is_localsystem(username)) {
- localsystem = true;
- username = NSSM_LOCALSYSTEM_ACCOUNT;
- }
- else {
- canon = canonical_username(username);
- if (canon) username = canon;
- }
+ else if (! password) {
+ /* We need a password if the account requires it. */
+ print_message(stderr, NSSM_MESSAGE_MISSING_PASSWORD, name);
+ return -1;
}
+ else passwordsize = _tcslen(password) * sizeof(TCHAR);
/*
ChangeServiceConfig() will fail to set the username if the service is set
if (! localsystem) {
QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle);
if (! qsc) {
- if (password) SecureZeroMemory(password, _tcslen(password) * sizeof(TCHAR));
- if (canon) LocalFree(canon);
+ if (passwordsize) SecureZeroMemory(password, passwordsize);
return -1;
}
HeapFree(GetProcessHeap(), 0, qsc);
}
- if (password) {
+ if (! well_known) {
if (grant_logon_as_service(username)) {
- if (password) SecureZeroMemory(password, _tcslen(password) * sizeof(TCHAR));
- if (canon) LocalFree(canon);
+ if (passwordsize) SecureZeroMemory(password, passwordsize);
print_message(stderr, NSSM_MESSAGE_GRANT_LOGON_AS_SERVICE_FAILED, username);
return -1;
}
}
if (! ChangeServiceConfig(service_handle, type, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, 0, username, password, 0)) {
- if (password) SecureZeroMemory(password, _tcslen(password) * sizeof(TCHAR));
- if (canon) LocalFree(canon);
+ if (passwordsize) SecureZeroMemory(password, passwordsize);
print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError()));
return -1;
}
- if (password) SecureZeroMemory(password, _tcslen(password) * sizeof(TCHAR));
- if (canon) LocalFree(canon);
+ if (passwordsize) SecureZeroMemory(password, passwordsize);
+
if (localsystem) return 0;
return 1;