X-Git-Url: http://git.iain.cx/?a=blobdiff_plain;f=account.cpp;h=5e6523f5383aa5cd4337ca77e359325ef0f0e751;hb=f5ce09a04c7575316ceb640533087e3ce9ae7de1;hp=9c2ff702cfd02934f0774628dae61afd8da0d8ed;hpb=cca8d28295ce27b7c996b47badc6a1e3a6a34e65;p=nssm.git diff --git a/account.cpp b/account.cpp index 9c2ff70..5e6523f 100644 --- a/account.cpp +++ b/account.cpp @@ -103,7 +103,7 @@ int username_sid(const TCHAR *username, SID **sid, LSA_HANDLE *policy) { } 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; } @@ -154,175 +154,31 @@ int is_localsystem(const TCHAR *username) { } /* - 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; @@ -340,6 +196,14 @@ int grant_logon_as_service(const TCHAR *username) { 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;