diff options
Diffstat (limited to 'src/ccapi/common/win/OldCC/util.cxx')
| -rw-r--r-- | src/ccapi/common/win/OldCC/util.cxx | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/src/ccapi/common/win/OldCC/util.cxx b/src/ccapi/common/win/OldCC/util.cxx new file mode 100644 index 0000000000000..dd4a2694ac6ba --- /dev/null +++ b/src/ccapi/common/win/OldCC/util.cxx @@ -0,0 +1,520 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include <windows.h> +#include <stdio.h> // for _snprintf +#include <malloc.h> +#include <stdlib.h> + +extern "C" { +#include "cci_debugging.h" +#include "ccutils.h" + } + +#include "util.h" +#include "secure.hxx" + + +void* malloc_alloc_p(size_t size) { + return malloc(size); + } + +void free_alloc_p(void *pptr) { + void **real_pptr = (void**)pptr; + if (*real_pptr) { + free(*real_pptr); + *real_pptr = 0; + } + } + +extern "C" DWORD alloc_textual_sid( + PSID pSid, // binary Sid + LPSTR *pTextualSid // buffer for Textual representaion of Sid + ) { + PSID_IDENTIFIER_AUTHORITY psia; + DWORD dwSubAuthorities; + DWORD dwSidRev = SID_REVISION; + DWORD dwCounter; + DWORD dwSidSize; + + *pTextualSid = 0; + + // + // test if Sid passed in is valid + // + if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER; + + // obtain SidIdentifierAuthority + psia = GetSidIdentifierAuthority(pSid); + + // obtain sidsubauthority count + dwSubAuthorities =* GetSidSubAuthorityCount(pSid); + + // + // compute buffer length + // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL + // + dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); + *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize); + if (!*pTextualSid) + return GetLastError(); + + LPSTR TextualSid = *pTextualSid; + + // + // prepare S-SID_REVISION- + // + wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev ); + + // + // prepare SidIdentifierAuthority + // + if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) + { + wsprintf(TextualSid + lstrlen(TextualSid), + TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), + (USHORT)psia->Value[0], + (USHORT)psia->Value[1], + (USHORT)psia->Value[2], + (USHORT)psia->Value[3], + (USHORT)psia->Value[4], + (USHORT)psia->Value[5]); + } + else + { + wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"), + (ULONG)(psia->Value[5] ) + + (ULONG)(psia->Value[4] << 8) + + (ULONG)(psia->Value[3] << 16) + + (ULONG)(psia->Value[2] << 24) ); + } + + // + // loop through SidSubAuthorities + // + for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) + { + wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"), + *GetSidSubAuthority(pSid, dwCounter) ); + } + return 0; +} + +DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) { + DWORD status = 0; + DWORD size = 0; + *pptu = 0; + + GetTokenInformation(hToken, TokenUser, *pptu, 0, &size); + if (size == 0) status = GetLastError(); + + if (!status) { + if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size)) + status = GetLastError(); + } + + if (status && *pptu) { + free_alloc_p(pptu); + } + return status; + } + +DWORD +alloc_username( + PSID Sid, + LPSTR* pname, + LPSTR* pdomain = 0 + ) +{ + DWORD status = 0; + DWORD name_len = 0; + DWORD domain_len = 0; + SID_NAME_USE snu; + LPSTR name = 0; + LPSTR domain = 0; + + *pname = 0; + if (pdomain) *pdomain = 0; + + LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu); + if ((name_len == 0) || (domain_len == 0)) status = GetLastError(); + + if (!status) { + if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError(); + } + + if (!status) { + if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError(); + } + + if (!status) { + if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError(); + } + + if (status) { + if (name) free_alloc_p(&name); + if (domain) free_alloc_p(&domain); + } + else { + if (pdomain) { + *pname = name; + *pdomain = domain; + } + else { + DWORD size = name_len + domain_len + 1; + *pname = (LPSTR)malloc_alloc_p(size); + if (!*pname) status = GetLastError(); + else _snprintf(*pname, size, "%s\\%s", name, domain); + } + } + return status; + } + +DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) { + TOKEN_STATISTICS ts; + DWORD len; + + if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len)) + return GetLastError(); + *pAuthId = ts.AuthenticationId; + return 0; + } + +DWORD +alloc_name_9x( + LPSTR* pname, + LPSTR postfix + ) +{ + char prefix[] = "krbcc"; + DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1; + + *pname = (LPSTR)malloc_alloc_p(len); + if (!*pname) return GetLastError(); + _snprintf(*pname, len, "%s.%s", prefix, postfix); + return 0; +} + +DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) { + DWORD status = 0; + HANDLE hToken = 0; + LUID auth_id; +#ifdef _DEBUG + PTOKEN_USER ptu = 0; + LPSTR name = 0; + LPSTR domain = 0; + LPSTR sid = 0; +#endif + char prefix[] = "krbcc"; + // Play it safe and say 3 characters are needed per 8 bits (byte). + // Note that 20 characters are needed for a 64-bit number in + // decimal (plus one for the string termination. + // and include room for sessionId. + char lid[3*sizeof(LUID)+1+5]; + DWORD sessionId; + DWORD len = 0; + + *pname = 0; + + status = SecureClient::Token(hToken); + + if (!status) { + status = get_authentication_id(hToken, &auth_id); + } + + if (!status) { + if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId)) + sessionId = 0; + } + +#ifdef _DEBUG + if (!status) {status = alloc_token_user(hToken, &ptu);} + if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);} + if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);} +#endif + + if (!status) { + _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId); + lid[sizeof(lid)-1] = 0; // be safe + + len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1; + *pname = (LPSTR)malloc_alloc_p(len); + if (!*pname) status = GetLastError(); + } + + // + // We used to allocate a name of the form: + // "prefix.domain.name.sid.lid.postfix" (usually under 80 + // characters, depending on username). However, XP thought this + // was "invalid" (too long?) for some reason. + // + // Therefore, we now use "prefix.lid.postfix" + // and for Terminal server we use "prefix.lid.sessionId.postfix" + // + + if (!status) { + _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix); + } + +#ifdef _DEBUG + if (sid) + free_alloc_p(&sid); + if (name) + free_alloc_p(&name); + if (domain) + free_alloc_p(&domain); + if (ptu) + free_alloc_p(&ptu); +#endif + if (hToken && hToken != INVALID_HANDLE_VALUE) + CloseHandle(hToken); + if (status && *pname) + free_alloc_p(pname); + return status; +} + +extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) { + return isNT ? alloc_name_NT(pname, postfix) : + alloc_name_9x(pname, postfix); + } + +extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) { + DWORD status = 0; + HANDLE hToken = 0; + PTOKEN_USER ptu = 0; + PSID pSid = 0; + PACL pAcl = 0; + DWORD size = 0; + SECURITY_DESCRIPTOR sd; + + *ppsd = 0; + + if (!status) {status = SecureClient::Token(hToken);} + + // Get SID: + if (!status) {status = alloc_token_user(hToken, &ptu);} + + if (!status) { + size = GetLengthSid(ptu->User.Sid); + pSid = (PSID) malloc_alloc_p(size); + if (!pSid) status = GetLastError(); + } + if (!status) { + if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError(); + } + + if (!status) { + // Prepare ACL: + size = sizeof(ACL); + // Add an ACE: + size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid); + pAcl = (PACL) malloc_alloc_p(size); + if (!pAcl) status = GetLastError(); + } + + if (!status) { + if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError(); + } + + if (!status) { + if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError(); + } + + if (!status) { + // Prepare SD itself: + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError(); + } + + if (!status) { + if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError(); + } + + if (!status) { + if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError(); + } + + if (!status) { + if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER; + } + + if (!status) { + // We now have a SD. Let's copy it. + { + // This should not succeed. Instead it should give us the size. + BOOL ok = MakeSelfRelativeSD(&sd, 0, &size); + } + if (size == 0) status = GetLastError(); + } + + if (!status) { + *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size); + if (!*ppsd) status = GetLastError(); + } + + if (!status) { + if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError(); + } + + if (ptu) free_alloc_p(&ptu); + if (pSid) free_alloc_p(&pSid); + if (pAcl) free_alloc_p(&pAcl); + if (hToken && hToken != INVALID_HANDLE_VALUE) CloseHandle(hToken); + if (status && *ppsd) free_alloc_p(ppsd); + return status; +} + +DWORD +alloc_module_file_name( + char* module, + char** pname + ) +{ + const DWORD max = 8192; + DWORD status = 0; + DWORD got = 0; + DWORD size = 512; // use low number to test... + HMODULE h = 0; + BOOL ok = FALSE; + char* name = 0; + + if (!pname) + return ERROR_INVALID_PARAMETER; + *pname = 0; + + h = GetModuleHandle(module); + + if (!h) return GetLastError(); + + // We assume size < max and size > 0 + while (!status && !ok) { + if (size > max) { + // XXX - Assert? + status = ERROR_INVALID_DATA; + continue; + } + if (name) free_alloc_p(&name); + name = (char*)malloc_alloc_p(size + 1); + if (!name) { + status = ERROR_NOT_ENOUGH_MEMORY; + continue; + } + name[size] = 0; + got = GetModuleFileName(h, name, size); + if (!got) { + status = GetLastError(); + // sanity check: + if (!status) { + // XXX - print nasty message...assert? + status = ERROR_INVALID_DATA; + } + continue; + } + // To know we're ok, we need to verify that what we got + // was bigger than GetModuleSize thought it got. + ok = got && (got < size) && !name[got]; + size *= 2; + } + if (status && name) + free_alloc_p(&name); + else + *pname = name; + return status; +} + +DWORD +alloc_module_dir_name( + char* module, + char** pname + ) +{ + DWORD status = alloc_module_file_name(module, pname); + if (!status) { + char* name = *pname; + char* p = name + strlen(name); + while ((p >= name) && (*p != '\\') && (*p != '/')) p--; + if (p < name) { + free_alloc_p(pname); + status = ERROR_INVALID_DATA; + } else { + *p = 0; + } + } + return status; +} + +DWORD +alloc_module_dir_name_with_file( + char* module, + char* file, + char** pname + ) +{ + DWORD status = alloc_module_dir_name(module, pname); + if (!status) { + char* name = *pname; + size_t name_size = strlen(name); + size_t size = name_size + 1 + strlen(file) + 1; + char* result = (char*)malloc_alloc_p(size); + if (!result) { + status = ERROR_NOT_ENOUGH_MEMORY; + free_alloc_p(pname); + } else { + strcpy(result, name); + result[name_size] = '\\'; + strcpy(result + name_size + 1, file); + free_alloc_p(pname); + *pname = result; + } + } + return status; +} + +DWORD alloc_cmdline_2_args(char* prog, + char* arg1, + char* arg2, + char** pname) { + DWORD status = 0; + size_t size = strlen(prog) + strlen(arg1) + strlen(arg2) + 4; + char* result = (char*)malloc_alloc_p(size); + if (!result) { + status = ERROR_NOT_ENOUGH_MEMORY; + } + else { + strcpy(result, prog); + strcat(result, " "); + strcat(result, arg1); + strcat(result, " "); + strcat(result, arg2); + *pname = result; + } + cci_debug_printf("%s made <%s>", __FUNCTION__, result); + return status; + } |
