1
0

winpgntc.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Pageant client code.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. #include "putty.h"
  8. #include "pageant.h" /* for AGENT_MAX_MSGLEN */
  9. #ifndef NO_SECURITY
  10. #include "winsecur.h"
  11. #endif
  12. #define AGENT_COPYDATA_ID 0x804e50ba /* random goop */
  13. int agent_exists(void)
  14. {
  15. HWND hwnd;
  16. hwnd = FindWindow("Pageant", "Pageant");
  17. if (!hwnd)
  18. return FALSE;
  19. else
  20. return TRUE;
  21. }
  22. void agent_cancel_query(agent_pending_query *q)
  23. {
  24. assert(0 && "Windows agent queries are never asynchronous!");
  25. }
  26. agent_pending_query *agent_query(
  27. void *in, int inlen, void **out, int *outlen,
  28. void (*callback)(void *, void *, int), void *callback_ctx)
  29. {
  30. HWND hwnd;
  31. char *mapname;
  32. HANDLE filemap;
  33. unsigned char *p, *ret;
  34. int id, retlen;
  35. COPYDATASTRUCT cds;
  36. SECURITY_ATTRIBUTES sa, *psa;
  37. PSECURITY_DESCRIPTOR psd = NULL;
  38. PSID usersid = NULL;
  39. *out = NULL;
  40. *outlen = 0;
  41. hwnd = FindWindow("Pageant", "Pageant");
  42. if (!hwnd)
  43. return NULL; /* *out == NULL, so failure */
  44. mapname = dupprintf("PageantRequest%08x", (unsigned)GetCurrentThreadId());
  45. psa = NULL;
  46. #ifndef NO_SECURITY
  47. if (got_advapi()) {
  48. /*
  49. * Make the file mapping we create for communication with
  50. * Pageant owned by the user SID rather than the default. This
  51. * should make communication between processes with slightly
  52. * different contexts more reliable: in particular, command
  53. * prompts launched as administrator should still be able to
  54. * run PSFTPs which refer back to the owning user's
  55. * unprivileged Pageant.
  56. */
  57. usersid = get_user_sid();
  58. if (usersid) {
  59. psd = (PSECURITY_DESCRIPTOR)
  60. LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  61. if (psd) {
  62. if (p_InitializeSecurityDescriptor
  63. (psd, SECURITY_DESCRIPTOR_REVISION) &&
  64. p_SetSecurityDescriptorOwner(psd, usersid, FALSE)) {
  65. sa.nLength = sizeof(sa);
  66. sa.bInheritHandle = TRUE;
  67. sa.lpSecurityDescriptor = psd;
  68. psa = &sa;
  69. } else {
  70. LocalFree(psd);
  71. psd = NULL;
  72. }
  73. }
  74. }
  75. }
  76. #endif /* NO_SECURITY */
  77. filemap = CreateFileMapping(INVALID_HANDLE_VALUE, psa, PAGE_READWRITE,
  78. 0, AGENT_MAX_MSGLEN, mapname);
  79. if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
  80. sfree(mapname);
  81. return NULL; /* *out == NULL, so failure */
  82. }
  83. p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
  84. memcpy(p, in, inlen);
  85. cds.dwData = AGENT_COPYDATA_ID;
  86. cds.cbData = 1 + strlen(mapname);
  87. cds.lpData = mapname;
  88. /*
  89. * The user either passed a null callback (indicating that the
  90. * query is required to be synchronous) or CreateThread failed.
  91. * Either way, we need a synchronous request.
  92. */
  93. id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
  94. if (id > 0) {
  95. unsigned int length_field = GET_32BIT(p);
  96. if (length_field > 0 && length_field <= AGENT_MAX_MSGLEN - 4) {
  97. retlen = length_field + 4;
  98. ret = snewn(retlen, unsigned char);
  99. memcpy(ret, p, retlen);
  100. *out = ret;
  101. *outlen = retlen;
  102. } else {
  103. /*
  104. * If we get here, we received an out-of-range length
  105. * field, either without space for a message type code or
  106. * overflowing the FileMapping.
  107. *
  108. * Treat this as if Pageant didn't answer at all - which
  109. * actually means we do nothing, and just don't fill in
  110. * out and outlen.
  111. */
  112. }
  113. }
  114. UnmapViewOfFile(p);
  115. CloseHandle(filemap);
  116. sfree(mapname);
  117. if (psd)
  118. LocalFree(psd);
  119. return NULL;
  120. }