-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;