Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
16 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. digestui.cxx
  5. Abstract:
  6. Authentication UI for digest sspi package.
  7. Author:
  8. Adriaan Canter (adriaanc) 01-Aug-1998
  9. History
  10. Sudeep Bharati (sudeepb) 24-Sep-1998
  11. Added support for ms specific header additions for Trustmarks
  12. Added support for Passport specific header additions for custom text,
  13. Trustmarks support and Register me button. Passport specific support
  14. also adds some rules on the typed in username.
  15. Adriaan Canter (adriaanc) 16-Dec-1998
  16. Expunged all Passport code.
  17. --*/
  18. #include "include.hxx"
  19. #include "resource.h"
  20. #include "exdisp.h"
  21. HANDLE hDigest;
  22. // BUGBUG - DISABLE DROP DOWN IF NO CREDS.
  23. //--------------------------------------------------------------------
  24. // DigestErrorDlg
  25. //--------------------------------------------------------------------
  26. DWORD DigestErrorDlg(LPSTR szCtx, LPSTR szHost, LPSTR szRealm,
  27. LPSTR szUser, LPSTR szNonce, LPSTR szCNonce, CCredInfo *pInfoIn,
  28. CCredInfo **ppInfoOut, HWND hWnd)
  29. {
  30. INT nResult = 0;
  31. DWORD dwError = ERROR_SUCCESS;
  32. LPTSTR lpRes;
  33. DigestDlgParams DlgPrms;
  34. // Parameters to be passed to DigestAuthDialogProc.
  35. DlgPrms.szCtx = szCtx;
  36. DlgPrms.szHost = szHost;
  37. DlgPrms.szRealm = szRealm;
  38. DlgPrms.szUser = szUser;
  39. DlgPrms.szNonce = szNonce;
  40. DlgPrms.szCNonce = szCNonce;
  41. DlgPrms.pInfoIn = pInfoIn;
  42. LPARAM lpParam = (LPARAM) &DlgPrms;
  43. if (WaitForSingleObject (hDigest, INFINITE) != WAIT_OBJECT_0) {
  44. dwError = ERROR_NOT_READY;
  45. goto quit;
  46. }
  47. lpRes = MAKEINTRESOURCE(IDD_DIGEST);
  48. nResult = (INT)DialogBoxParam(g_hModule,
  49. lpRes,
  50. hWnd,
  51. DigestAuthDialogProc,
  52. (LPARAM) lpParam);
  53. if (nResult == FALSE || nResult == -1)
  54. {
  55. dwError = ERROR_CANCELLED;
  56. *ppInfoOut = NULL;
  57. goto quit;
  58. }
  59. // *ppInfoOut points to a CCredInfo created in the
  60. // DigestAuthDialog proc.
  61. *ppInfoOut = DlgPrms.pInfoOut;
  62. quit:
  63. // delete DlgPrms.szCtx; biaow: we should NOT delete here; the caller will take care of this
  64. return dwError;
  65. }
  66. //--------------------------------------------------------------------
  67. // DigestAuthDialogProc
  68. //--------------------------------------------------------------------
  69. INT_PTR CALLBACK DigestAuthDialogProc(HWND hwnd, UINT msg,
  70. WPARAM wparam, LPARAM lparam)
  71. {
  72. static CCredInfo *pList = NULL;
  73. static HWND hCtrlText,hCtrlVerify;
  74. PDigestDlgParams pDlgPrms;
  75. USHORT len;
  76. LPSTR p,q;
  77. CHAR szUser[MAX_USERNAME_LEN + 1];
  78. CHAR szPass[MAX_PASSWORD_LEN + 1];
  79. BOOL fCreated = FALSE;
  80. BOOL fPersisted = FALSE;
  81. BSTR bstr;
  82. CHAR szTextTemp [MAX_LOGIN_TEXT];
  83. CHAR szText [MAX_LOGIN_TEXT];
  84. switch (msg)
  85. {
  86. // Dialog is being initialized.
  87. case WM_INITDIALOG:
  88. {
  89. ReleaseMutex (hDigest);
  90. // pDlgPrms->pInfoIn can be NULL or point
  91. // to one or more CCredInfo structs.
  92. pDlgPrms = (DigestDlgParams *) lparam;
  93. DIGEST_ASSERT(pDlgPrms);
  94. SetWindowLongPtr(hwnd, DWLP_USER, lparam);
  95. SetForegroundWindow(hwnd);
  96. // Take Care of Host field
  97. hCtrlText = GetDlgItem (hwnd, IDD_LOGIN_TEXT1);
  98. len = (USHORT)GetWindowText (hCtrlText,szTextTemp,MAX_LOGIN_TEXT);
  99. if (len == 0) {
  100. DIGEST_ASSERT(FALSE);
  101. EndDialog (hwnd, FALSE);
  102. return TRUE;
  103. }
  104. if ((p = strchr (szTextTemp, '%')) == NULL) {
  105. DIGEST_ASSERT(FALSE);
  106. EndDialog (hwnd, FALSE);
  107. return TRUE;
  108. }
  109. *p++ = '\0';
  110. strcpy (szText, szTextTemp);
  111. if (pDlgPrms->szHost)
  112. strncat (szText,pDlgPrms->szHost, sizeof(szText) / sizeof(szText[0]) - (strlen(szText) + strlen(p) + 1));
  113. else {
  114. if (len = (USHORT)LoadString (g_hModule,IDS_STRING_UDOMAIN,
  115. szUser,MAX_USERNAME_LEN))
  116. strcat (szText,szUser);
  117. }
  118. strcat (szText, p);
  119. if (!SetWindowText (hCtrlText,szText)) {
  120. DIGEST_ASSERT(FALSE);
  121. EndDialog (hwnd, FALSE);
  122. return TRUE;
  123. }
  124. // Take care of Realm and Hint fields. Remember Passport has
  125. // hard coded text for this second line.
  126. hCtrlText = GetDlgItem (hwnd, IDD_LOGIN_TEXT2);
  127. len = (USHORT)GetWindowText (hCtrlText,szTextTemp,MAX_LOGIN_TEXT);
  128. if (len == 0) {
  129. DIGEST_ASSERT(FALSE);
  130. EndDialog (hwnd, FALSE);
  131. return TRUE;
  132. }
  133. if ((p = strchr (szTextTemp, '%')) == NULL) {
  134. DIGEST_ASSERT(FALSE);
  135. EndDialog (hwnd, FALSE);
  136. return TRUE;
  137. }
  138. *p++ = '\0';
  139. strcpy (szText, szTextTemp);
  140. if (pDlgPrms->szRealm)
  141. {
  142. DWORD dwAvailBuf = MAX_LOGIN_TEXT - strlen(szText);
  143. strncpy(szText + strlen(szText), pDlgPrms->szRealm, dwAvailBuf - 1);
  144. szText[MAX_LOGIN_TEXT - 1] = 0;
  145. // strcat (szText,pDlgPrms->szRealm);
  146. }
  147. else {
  148. if (len = (USHORT)LoadString (g_hModule,IDS_STRING_UREALM,
  149. szUser,MAX_USERNAME_LEN))
  150. strcat (szText,szUser);
  151. }
  152. strcat (szText,p);
  153. if (!SetWindowText (hCtrlText,szText)) {
  154. DIGEST_ASSERT(FALSE);
  155. EndDialog (hwnd, FALSE);
  156. return TRUE;
  157. }
  158. // Determine if credential persistence is available.
  159. if (g_dwCredPersistAvail == CRED_PERSIST_UNKNOWN)
  160. g_dwCredPersistAvail = InetInitCredentialPersist();
  161. // If credential persist not available, hide checkbox.
  162. if (g_dwCredPersistAvail == CRED_PERSIST_NOT_AVAIL)
  163. ShowWindow(GetDlgItem(hwnd, IDC_SAVE_PASSWORD), SW_HIDE);
  164. // Find any persisted credential.
  165. if (g_dwCredPersistAvail
  166. && ((InetGetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
  167. szUser, szPass) == ERROR_SUCCESS)))
  168. {
  169. // Retrieved a set of credentials. If a username was passed
  170. // in check to see that the persisted username matches.
  171. if (!pDlgPrms->szUser || !strcmp(pDlgPrms->szUser, szUser))
  172. {
  173. // No username passed in or usernames match.
  174. // Create a CCredInfo and insert it into head of list.
  175. pList = new CCredInfo(pDlgPrms->szHost, pDlgPrms->szRealm, szUser, szPass,
  176. pDlgPrms->szNonce, pDlgPrms->szCNonce);
  177. if (!pList || pList->dwStatus != ERROR_SUCCESS)
  178. {
  179. DIGEST_ASSERT(FALSE);
  180. return FALSE;
  181. }
  182. // Insert it at the beginning of the list.
  183. pList->pNext = pDlgPrms->pInfoIn;
  184. if (pDlgPrms->pInfoIn)
  185. pDlgPrms->pInfoIn->pPrev = pList;
  186. fPersisted = TRUE;
  187. fCreated = TRUE;
  188. }
  189. }
  190. // If we did not retrieve a persisted credential, check to see
  191. // if we need to create a dummy credential.
  192. if (!fPersisted)
  193. {
  194. // Create a dummy credential if a username was passed in
  195. // but a credential was not retrieved from memory.
  196. if (pDlgPrms->szUser && !pDlgPrms->pInfoIn)
  197. {
  198. pList = new CCredInfo(pDlgPrms->szHost, pDlgPrms->szRealm, pDlgPrms->szUser, NULL,
  199. pDlgPrms->szNonce, pDlgPrms->szCNonce);
  200. fCreated = TRUE;
  201. }
  202. else
  203. {
  204. // Otherwise, just point to the creds
  205. // retrieved from memory.
  206. pList = pDlgPrms->pInfoIn;
  207. }
  208. }
  209. else
  210. {
  211. // A persisted credential was created and inserted
  212. // into the beginning of the list. The list may
  213. // contain a CCredInfo with a matching user.
  214. // remove any (at most one) duplicate entry.
  215. CCredInfo *pCur;
  216. pCur = pList->pNext;
  217. while (pCur)
  218. {
  219. if (!strcmp(pCur->szUser, pList->szUser))
  220. {
  221. pCur->pPrev->pNext = pCur->pNext;
  222. if (pCur->pNext)
  223. pCur->pNext->pPrev = pCur->pPrev;
  224. break;
  225. }
  226. pCur = pCur->pNext;
  227. }
  228. }
  229. // The list is now in the correct format:
  230. // 1) pList may be NULL
  231. // 2) pList may have a dummy credential for username with no password.
  232. // 3) pList may have one credential for username with password.
  233. // 4) pList may have one or more credentials for different usernames.
  234. // Limit drop-down if no items in list.
  235. if (!pList)
  236. {
  237. SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_ADDSTRING, 0, (LPARAM) (LPCSTR) "");
  238. }
  239. // Populate the combo box with the list contents.
  240. CCredInfo *pCur;
  241. pCur = pList;
  242. while (pCur)
  243. {
  244. SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_ADDSTRING, 0, (LPARAM) (LPCSTR) pCur->szUser);
  245. pCur = pCur->pNext;
  246. }
  247. // If the first item in the combo box was created (user given or persisted)
  248. // set it as the default and set it's password in the password control.
  249. // Indicate if credentials are from persisted store.
  250. // Default to 0th item.
  251. SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_SETCURSEL, 0, 0);
  252. // Set password field if extant.
  253. if (pList)
  254. {
  255. LPSTR szPassTmp = pList->GetPass();
  256. SetWindowText (GetDlgItem(hwnd,IDC_PASSWORD_FIELD), szPassTmp ? szPassTmp : "");
  257. if (szPassTmp)
  258. {
  259. SecureZeroMemory(szPassTmp, strlen(szPassTmp));
  260. delete [] szPassTmp;
  261. }
  262. }
  263. // Indicate if credentials from persisted store.
  264. if (fPersisted)
  265. CheckDlgButton(hwnd, IDC_SAVE_PASSWORD, BST_CHECKED);
  266. SetFocus(GetDlgItem(hwnd, IDC_COMBO1));
  267. // Return FALSE since we are always setting the keyboard focus.
  268. return FALSE;
  269. }
  270. // WM comands from action on dialog.
  271. case WM_COMMAND:
  272. {
  273. WORD wID = LOWORD(wparam);
  274. WORD wNotificationCode = HIWORD(wparam);
  275. HWND hWndCtrl = (HWND) lparam;
  276. pDlgPrms = (DigestDlgParams*) GetWindowLongPtr(hwnd, DWLP_USER);
  277. DIGEST_ASSERT(pDlgPrms);
  278. // User has selected something on the combo-box.
  279. switch(wNotificationCode)
  280. {
  281. // User has selected a drop-down item.
  282. case CBN_SELCHANGE:
  283. {
  284. // Get the index of the selected item.
  285. DWORD nIndex;
  286. nIndex = (DWORD)SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_GETCURSEL, 0, 0);
  287. if (nIndex == -1)
  288. {
  289. SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_SETCURSEL, 0, 0);
  290. return FALSE;
  291. }
  292. // Point to the indexed CCredInfo entry
  293. CCredInfo *pCur;
  294. pCur = pList;
  295. for (DWORD i = 0; i < nIndex ; i++)
  296. pCur = pCur->pNext;
  297. // Set password of the indexed CCredInfo struct.
  298. {
  299. LPSTR szPassTmp = pCur ? pCur->GetPass() : NULL;
  300. SetWindowText (GetDlgItem(hwnd,IDC_PASSWORD_FIELD), szPassTmp ? szPassTmp : "");
  301. if (szPassTmp)
  302. {
  303. SecureZeroMemory(szPassTmp, strlen(szPassTmp));
  304. delete [] szPassTmp;
  305. }
  306. }
  307. // User may have selected username with persisted credentials.
  308. if (g_dwCredPersistAvail)
  309. {
  310. // If selected CCredInfo has a user with persisted credentials
  311. if ((InetGetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
  312. szUser, szPass) == ERROR_SUCCESS)
  313. && !strcmp(pCur->szUser, szUser))
  314. {
  315. // Indicate that this user has persisted creds for the realm.
  316. CheckDlgButton(hwnd, IDC_SAVE_PASSWORD, BST_CHECKED);
  317. }
  318. else
  319. {
  320. // Otherwise Indicate that this user does not have persisted
  321. // creds for the realm.
  322. CheckDlgButton(hwnd, IDC_SAVE_PASSWORD, BST_UNCHECKED);
  323. }
  324. }
  325. }
  326. return FALSE;
  327. }
  328. // User has clicked OK or Cancel button.
  329. switch (wID)
  330. {
  331. case IDOK:
  332. {
  333. CCredInfo *pOut;
  334. // User has clicked on OK button.
  335. // Get the username and password into the output CCredInfo.
  336. GetWindowText(GetDlgItem(hwnd,IDC_COMBO1), szUser, MAX_USERNAME_LEN);
  337. GetWindowText(GetDlgItem(hwnd,IDC_PASSWORD_FIELD), szPass, MAX_PASSWORD_LEN);
  338. // If save box checked, persist credentials.
  339. if (IsDlgButtonChecked(hwnd, IDC_SAVE_PASSWORD) == BST_CHECKED)
  340. {
  341. InetSetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
  342. szUser, szPass);
  343. }
  344. else
  345. {
  346. // Otherwise the button is not checked. Check to see if we should
  347. // remove the credentials from persisted store.
  348. if (g_dwCredPersistAvail)
  349. {
  350. // If current and original credentials are for same user,
  351. // remove the credentials.
  352. CHAR szUserPersist[MAX_USERNAME_LEN], szPassPersist[MAX_PASSWORD_LEN];
  353. if ((InetGetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
  354. szUserPersist, szPassPersist) == ERROR_SUCCESS)
  355. && !strcmp(szUser, szUserPersist))
  356. {
  357. InetRemoveCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm);
  358. }
  359. }
  360. }
  361. // Allocate a new CCredInfo struct to return.
  362. pOut = new CCredInfo(pDlgPrms->szHost, pDlgPrms->szRealm, szUser, szPass,
  363. pDlgPrms->szNonce, pDlgPrms->szCNonce);
  364. if (!pOut)
  365. {
  366. DIGEST_ASSERT(FALSE);
  367. }
  368. pDlgPrms->pInfoOut = pOut;
  369. EndDialog(hwnd, TRUE);
  370. break;
  371. }
  372. case IDCANCEL:
  373. {
  374. // User has canceled dialog - no action.
  375. EndDialog(hwnd, FALSE);
  376. break;
  377. }
  378. }
  379. return FALSE;
  380. }
  381. }
  382. return FALSE;
  383. }