From: Simon Tatham Date: Sun, 17 Nov 2013 14:05:29 +0000 (+0000) Subject: Move the dynamic loading of advapi into its own module. X-Git-Tag: 0.64~122 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=f6f78f835543099d4b5e342ba34f91104862803b;p=PuTTY.git Move the dynamic loading of advapi into its own module. There's now a winsecur.[ch], which centralises helper functions using the Windows security stuff in advapi.h (currently just get_user_sid), and also centralises the run-time loading of those functions and checking they're all there. [originally from svn r10082] --- diff --git a/Recipe b/Recipe index 36b753b4..4ef4048e 100644 --- a/Recipe +++ b/Recipe @@ -300,7 +300,7 @@ SSH = ssh sshcrc sshdes sshmd5 sshrsa sshrand sshsha sshblowf + sshdh sshcrcda sshpubk sshzlib sshdss x11fwd portfwd + sshaes sshsh256 sshsh512 sshbn wildcard pinger ssharcf + sshgssc pgssapi -WINSSH = SSH winnoise winpgntc wingss winhsock errsock +WINSSH = SSH winnoise winsecur winpgntc wingss winhsock errsock UXSSH = SSH uxnoise uxagentc uxgss # SFTP implementation (pscp, psftp). @@ -350,8 +350,8 @@ psftp : [C] psftp winsftp wincons WINSSH BE_SSH SFTP wildcard WINMISC + psftp.res winnojmp LIBS pageant : [G] winpgnt sshrsa sshpubk sshdes sshbn sshmd5 version tree234 - + misc sshaes sshsha winpgntc sshdss sshsh256 sshsh512 winutils - + winmisc winhelp conf pageant.res LIBS + + misc sshaes sshsha winsecur winpgntc sshdss sshsh256 sshsh512 + + winutils winmisc winhelp conf pageant.res LIBS puttygen : [G] winpgen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version + sshrand winnoise sshsha winstore misc winctrls sshrsa sshdss winmisc diff --git a/windows/winnpc.c b/windows/winnpc.c index 9b347dd3..90e2cbda 100644 --- a/windows/winnpc.c +++ b/windows/winnpc.c @@ -14,7 +14,7 @@ #if !defined NO_SECURITY -#include +#include "winsecur.h" Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug, int overlapped); @@ -27,9 +27,6 @@ Socket new_named_pipe_client(const char *pipename, Plug plug) char *err; Socket ret; - extern int advapi_initialised; - init_advapi(); /* for get_user_sid. FIXME: do better. */ - assert(strncmp(pipename, "\\\\.\\pipe\\", 9) == 0); assert(strchr(pipename + 9, '\\') == NULL); diff --git a/windows/winpgnt.c b/windows/winpgnt.c index 67911602..7e6a12fa 100644 --- a/windows/winpgnt.c +++ b/windows/winpgnt.c @@ -14,6 +14,7 @@ #include "ssh.h" #include "misc.h" #include "tree234.h" +#include "winsecur.h" #include @@ -2065,7 +2066,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* * Attempt to get the security API we need. */ - if (!init_advapi()) { + if (!got_advapi()) { MessageBox(NULL, "Unable to access security APIs. Pageant will\n" "not run, in case it causes a security breach.", diff --git a/windows/winpgntc.c b/windows/winpgntc.c index 7b8b5093..036ca759 100644 --- a/windows/winpgntc.c +++ b/windows/winpgntc.c @@ -8,7 +8,7 @@ #include "putty.h" #ifndef NO_SECURITY -#include +#include "winsecur.h" #endif #define AGENT_COPYDATA_ID 0x804e50ba /* random goop */ @@ -70,88 +70,6 @@ DWORD WINAPI agent_query_thread(LPVOID param) #endif -/* - * Dynamically load advapi32.dll for SID manipulation. In its absence, - * we degrade gracefully. - */ -#ifndef NO_SECURITY -int advapi_initialised = FALSE; -static HMODULE advapi; -DECL_WINDOWS_FUNCTION(static, BOOL, OpenProcessToken, - (HANDLE, DWORD, PHANDLE)); -DECL_WINDOWS_FUNCTION(static, BOOL, GetTokenInformation, - (HANDLE, TOKEN_INFORMATION_CLASS, - LPVOID, DWORD, PDWORD)); -DECL_WINDOWS_FUNCTION(static, BOOL, InitializeSecurityDescriptor, - (PSECURITY_DESCRIPTOR, DWORD)); -DECL_WINDOWS_FUNCTION(static, BOOL, SetSecurityDescriptorOwner, - (PSECURITY_DESCRIPTOR, PSID, BOOL)); -DECL_WINDOWS_FUNCTION(, DWORD, GetSecurityInfo, - (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, - PSID *, PSID *, PACL *, PACL *, - PSECURITY_DESCRIPTOR *)); -int init_advapi(void) -{ - advapi = load_system32_dll("advapi32.dll"); - return advapi && - GET_WINDOWS_FUNCTION(advapi, GetSecurityInfo) && - GET_WINDOWS_FUNCTION(advapi, OpenProcessToken) && - GET_WINDOWS_FUNCTION(advapi, GetTokenInformation) && - GET_WINDOWS_FUNCTION(advapi, InitializeSecurityDescriptor) && - GET_WINDOWS_FUNCTION(advapi, SetSecurityDescriptorOwner); -} - -PSID get_user_sid(void) -{ - HANDLE proc = NULL, tok = NULL; - TOKEN_USER *user = NULL; - DWORD toklen, sidlen; - PSID sid = NULL, ret = NULL; - - if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE, - GetCurrentProcessId())) == NULL) - goto cleanup; - - if (!p_OpenProcessToken(proc, TOKEN_QUERY, &tok)) - goto cleanup; - - if (!p_GetTokenInformation(tok, TokenUser, NULL, 0, &toklen) && - GetLastError() != ERROR_INSUFFICIENT_BUFFER) - goto cleanup; - - if ((user = (TOKEN_USER *)LocalAlloc(LPTR, toklen)) == NULL) - goto cleanup; - - if (!p_GetTokenInformation(tok, TokenUser, user, toklen, &toklen)) - goto cleanup; - - sidlen = GetLengthSid(user->User.Sid); - - sid = (PSID)smalloc(sidlen); - - if (!CopySid(sidlen, sid, user->User.Sid)) - goto cleanup; - - /* Success. Move sid into the return value slot, and null it out - * to stop the cleanup code freeing it. */ - ret = sid; - sid = NULL; - - cleanup: - if (proc != NULL) - CloseHandle(proc); - if (tok != NULL) - CloseHandle(tok); - if (user != NULL) - LocalFree(user); - if (sid != NULL) - sfree(sid); - - return ret; -} - -#endif - int agent_query(void *in, int inlen, void **out, int *outlen, void (*callback)(void *, void *, int), void *callback_ctx) { @@ -175,7 +93,7 @@ int agent_query(void *in, int inlen, void **out, int *outlen, psa = NULL; #ifndef NO_SECURITY - if (advapi_initialised || init_advapi()) { + if (got_advapi()) { /* * Make the file mapping we create for communication with * Pageant owned by the user SID rather than the default. This diff --git a/windows/winsecur.c b/windows/winsecur.c new file mode 100644 index 00000000..9271af5f --- /dev/null +++ b/windows/winsecur.c @@ -0,0 +1,86 @@ +/* + * winsecur.c: implementation of winsecur.h. + */ + +#include +#include + +#include "putty.h" + +#if !defined NO_SECURITY + +#define WINSECUR_GLOBAL +#include "winsecur.h" + +int got_advapi(void) +{ + static int attempted = FALSE; + static int successful; + static HMODULE advapi; + + if (!attempted) { + attempted = TRUE; + advapi = load_system32_dll("advapi32.dll"); + successful = advapi && + GET_WINDOWS_FUNCTION(advapi, GetSecurityInfo) && + GET_WINDOWS_FUNCTION(advapi, OpenProcessToken) && + GET_WINDOWS_FUNCTION(advapi, GetTokenInformation) && + GET_WINDOWS_FUNCTION(advapi, InitializeSecurityDescriptor) && + GET_WINDOWS_FUNCTION(advapi, SetSecurityDescriptorOwner); + } + return successful; +} + +PSID get_user_sid(void) +{ + HANDLE proc = NULL, tok = NULL; + TOKEN_USER *user = NULL; + DWORD toklen, sidlen; + PSID sid = NULL, ret = NULL; + + if (!got_advapi()) + goto cleanup; + + if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE, + GetCurrentProcessId())) == NULL) + goto cleanup; + + if (!p_OpenProcessToken(proc, TOKEN_QUERY, &tok)) + goto cleanup; + + if (!p_GetTokenInformation(tok, TokenUser, NULL, 0, &toklen) && + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto cleanup; + + if ((user = (TOKEN_USER *)LocalAlloc(LPTR, toklen)) == NULL) + goto cleanup; + + if (!p_GetTokenInformation(tok, TokenUser, user, toklen, &toklen)) + goto cleanup; + + sidlen = GetLengthSid(user->User.Sid); + + sid = (PSID)smalloc(sidlen); + + if (!CopySid(sidlen, sid, user->User.Sid)) + goto cleanup; + + /* Success. Move sid into the return value slot, and null it out + * to stop the cleanup code freeing it. */ + ret = sid; + sid = NULL; + + cleanup: + if (proc != NULL) + CloseHandle(proc); + if (tok != NULL) + CloseHandle(tok); + if (user != NULL) + LocalFree(user); + if (sid != NULL) + sfree(sid); + + return ret; +} + +#endif /* !defined NO_SECURITY */ diff --git a/windows/winsecur.h b/windows/winsecur.h new file mode 100644 index 00000000..9844afc8 --- /dev/null +++ b/windows/winsecur.h @@ -0,0 +1,32 @@ +/* + * winsecur.h: some miscellaneous security-related helper functions, + * defined in winsecur.c, that use the advapi32 library. Also + * centralises the machinery for dynamically loading that library. + */ + +#if !defined NO_SECURITY + +#include + +#ifndef WINSECUR_GLOBAL +#define WINSECUR_GLOBAL extern +#endif + +DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, OpenProcessToken, + (HANDLE, DWORD, PHANDLE)); +DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, GetTokenInformation, + (HANDLE, TOKEN_INFORMATION_CLASS, + LPVOID, DWORD, PDWORD)); +DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, InitializeSecurityDescriptor, + (PSECURITY_DESCRIPTOR, DWORD)); +DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, SetSecurityDescriptorOwner, + (PSECURITY_DESCRIPTOR, PSID, BOOL)); +DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, GetSecurityInfo, + (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, + PSID *, PSID *, PACL *, PACL *, + PSECURITY_DESCRIPTOR *)); + +int got_advapi(void); +PSID get_user_sid(void); + +#endif diff --git a/windows/winstuff.h b/windows/winstuff.h index 54a06c07..8f5e0dff 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -516,14 +516,6 @@ void agent_schedule_callback(void (*callback)(void *, void *, int), void *callback_ctx, void *data, int len); #define FLAG_SYNCAGENT 0x1000 -/* - * winpgntc.c also exports these two functions which are used by the - * server side of Pageant as well, to get the user SID for comparing - * with clients'. - */ -int init_advapi(void); /* initialises everything needed by get_user_sid */ -PSID get_user_sid(void); - /* * Exports from winser.c. */