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.

354 lines
11 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. ItgRasXp
  5. File Name:
  6. ItgRasXp.cpp
  7. Abstract:
  8. This is the entry point file for the ITG RAS Smartcard Support Applet. This app
  9. prompts the user for his domain\username and password credentials, and uses
  10. these to create a *Session credential that is used for NTLM authentication for
  11. servers on the network which do not use Kerberos.
  12. Author:
  13. Environment:
  14. Win32, C++
  15. Revision History:
  16. none
  17. Notes:
  18. --*/
  19. #include <nt.h>
  20. #include <ntrtl.h>
  21. #include <nturtl.h>
  22. #include <windows.h>
  23. #include <commdlg.h>
  24. #include <commctrl.h>
  25. #include <ole2.h>
  26. #include <stdio.h>
  27. #include <lmcons.h>
  28. #include <wincred.h>
  29. #include <wincrui.h>
  30. #define SECURITY_WIN32
  31. #include <security.h>
  32. #include "testaudit.h"
  33. #include "res.h"
  34. BOOL gfSuccess = FALSE;
  35. HINSTANCE ghInstance = NULL;
  36. #if 0
  37. #define TESTKEY L"Environment"
  38. #else
  39. #define TESTKEY L"Software\\Microsoft\\Connection Manager\\Worldwide Dial-Up RAS to MS Corp"
  40. #endif
  41. // see if name valid - check for common mistakes. At the moment, we merely insist that
  42. // the user fill in both username and password, and that the username contains the '\'
  43. // character, making it more likely that it is an approved domain\usernaem form.
  44. BOOL CheckUsername(WCHAR *pszUsername,WCHAR *pszPassword)
  45. {
  46. ASSERT(pszUsername);
  47. ASSERT(pszPassword);
  48. if ((0 == wcslen(pszUsername)) || (0 == wcslen(pszPassword)))
  49. {
  50. CHECKPOINT(2,"Username and password not both filled in.");
  51. MessageBox(NULL,L"Both username and password must be specified.",L"Error",MB_ICONHAND);
  52. return FALSE;
  53. }
  54. if (NULL == wcschr(pszUsername,L'\\'))
  55. {
  56. CHECKPOINT(3,"Username not domain\\username.");
  57. MessageBox(NULL,L"The username format must be \"domain\\username\".",L"Error",MB_ICONHAND);
  58. return FALSE;
  59. }
  60. else return TRUE;
  61. }
  62. // Attempt to use the credentials that the user entered and return FALSE if they do not
  63. // appear to be valid on the net. Show the user any errors that arise from trying to validate
  64. // his credentials. In the event that validation is impossible owing to a network error or some
  65. // other error not the fault of his credentials, save them anyway, though with a warning.
  66. #define DEFAULTSERVER L"\\\\products\\public"
  67. BOOL IsCredentialOK(WCHAR *pszUsername,WCHAR *pszPassword)
  68. {
  69. ASSERT(pszUsername);
  70. ASSERT(pszPassword);
  71. NETRESOURCE stNetResource;
  72. WCHAR szServer[MAX_PATH + 1]; // to hold test host string from registry
  73. BOOL fKeyFound = FALSE;
  74. DWORD dwErr = 0;
  75. DWORD dwSize = 0; // for return from open connection
  76. DWORD dwResult = 0; // for return from open connection
  77. HKEY hKey= NULL; // reg key rread
  78. DWORD dwType; // reg key read return
  79. DWORD dwDataSize = 0; // reg key read in/out
  80. memset(&stNetResource,0,sizeof(NETRESOURCE));
  81. // prepare the servername preset to the default
  82. wcsncpy(szServer,DEFAULTSERVER,MAX_PATH);
  83. // Look for server in registry HKCU. If found, use it to overwrite the default server
  84. if ((!fKeyFound) && (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,TESTKEY,0,KEY_READ,&hKey)))
  85. {
  86. if ((hKey) && (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) NULL,&dwDataSize)))
  87. {
  88. // key value exists and is of size dwDataSize
  89. WCHAR *pString = (WCHAR *) LocalAlloc(LMEM_FIXED,dwDataSize);
  90. ASSERT(pString);
  91. ASSERT(dwType == REG_SZ);
  92. if (pString)
  93. {
  94. if (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) pString,&dwDataSize))
  95. {
  96. CHECKPOINT(9,"Override server found in registry in HKCU");
  97. wcsncpy(szServer,pString,dwDataSize / sizeof(WCHAR));
  98. fKeyFound = TRUE;
  99. }
  100. LocalFree(pString);
  101. }
  102. }
  103. RegCloseKey(hKey);
  104. hKey = NULL;
  105. }
  106. // Look for server in registry HKLM.
  107. if ((!fKeyFound) && (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,TESTKEY,0,KEY_READ,&hKey)))
  108. {
  109. if ((hKey) && (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) NULL,&dwDataSize)))
  110. {
  111. // key value exists and is of size dwDataSize
  112. WCHAR *pString = (WCHAR *) LocalAlloc(LMEM_FIXED,dwDataSize);
  113. ASSERT(pString);
  114. ASSERT(dwType == REG_SZ);
  115. if (pString)
  116. {
  117. if (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) pString,&dwDataSize))
  118. {
  119. CHECKPOINT(8,"Override server found in registry in HKLM");
  120. wcsncpy(szServer,pString,dwDataSize / sizeof(WCHAR));
  121. fKeyFound = TRUE;
  122. }
  123. LocalFree(pString);
  124. }
  125. }
  126. RegCloseKey(hKey);
  127. hKey = NULL;
  128. }
  129. #if TESTAUDIT
  130. if (!fKeyFound) CHECKPOINT(10,"No override server found in registry");
  131. #endif
  132. stNetResource.dwType = RESOURCETYPE_DISK;
  133. stNetResource.lpLocalName = NULL;
  134. stNetResource.lpRemoteName = szServer;
  135. stNetResource.lpProvider = NULL;
  136. dwErr = WNetUseConnection( NULL,
  137. &stNetResource,
  138. pszPassword,
  139. pszUsername,
  140. 0,
  141. NULL, // lpAccessName
  142. &dwSize, // size of lpAccessName buffer
  143. &dwResult);
  144. if (dwErr == S_OK)
  145. {
  146. // On successful connection, tear down the connection and return success
  147. WNetCancelConnection2(szServer, 0, TRUE);
  148. return TRUE;
  149. }
  150. // Errors are handled by presenting a message box. If the server was found and rejected
  151. // the creds, don't save them - give the user a chance to correct. If the server was
  152. // unavailable, save the creds anyway, but warn the user that they were unvalidated.
  153. switch (dwErr)
  154. {
  155. case ERROR_ACCESS_DENIED:
  156. case ERROR_INVALID_PASSWORD:
  157. // announce that the password is no good
  158. CHECKPOINT(7,"Reached the server, but the creds were no good");
  159. MessageBox(NULL,L"The entered username and password are not correct",L"Error",MB_ICONHAND);
  160. break;
  161. case ERROR_NO_NET_OR_BAD_PATH:
  162. case ERROR_NO_NETWORK:
  163. case ERROR_EXTENDED_ERROR:
  164. case ERROR_BAD_NET_NAME:
  165. case ERROR_BAD_PROVIDER:
  166. default:
  167. CHECKPOINT(6,"Not able to validate - server unreachable");
  168. MessageBox(NULL,L"Your username and password will be saved for this session, though they could not be verified. They may be incorrect.",L"Error",MB_ICONHAND);
  169. return TRUE; // permit them to be saved anyway
  170. // announce that we cannot validate, and let them save it anyway
  171. break;
  172. }
  173. return FALSE;
  174. }
  175. // Store the user's entered credentials on the keyring as a session persisted *Session cred.
  176. // Call IsCredentialOK() before storing. If the credentials don't appear correct, present
  177. // a message box describing the error and leave the dialog up.
  178. BOOL WriteDomainCreds(WCHAR *pszUsername,WCHAR *pszPassword)
  179. {
  180. CREDENTIAL cred;
  181. if (!CheckUsername(pszUsername,pszPassword))
  182. {
  183. return FALSE;
  184. }
  185. if (!IsCredentialOK(pszUsername,pszPassword))
  186. {
  187. return FALSE;
  188. }
  189. memset(&cred,0,sizeof(CREDENTIAL));
  190. cred.TargetName = CRED_SESSION_WILDCARD_NAME_W;
  191. cred.UserName = pszUsername;
  192. cred.CredentialBlob = (LPBYTE) pszPassword;
  193. cred.CredentialBlobSize = (wcslen(pszPassword) * sizeof(WCHAR));
  194. cred.Type = CRED_TYPE_DOMAIN_PASSWORD;
  195. cred.Persist = CRED_PERSIST_SESSION;
  196. return CredWrite(&cred,0);
  197. }
  198. INT_PTR CALLBACK DialogProc(
  199. HWND hwnd,
  200. UINT msg,
  201. WPARAM wparam,
  202. LPARAM lparam)
  203. {
  204. INT_PTR ret;
  205. HWND hwndCred = NULL;
  206. switch (msg)
  207. {
  208. case WM_COMMAND:
  209. // Button clicks.
  210. switch(LOWORD(wparam))
  211. {
  212. case IDOK:
  213. if (HIWORD(wparam) == BN_CLICKED)
  214. {
  215. WCHAR szUser[UNLEN + 1];
  216. WCHAR szPass[PWLEN + 1];
  217. szUser[0] = 0;
  218. szPass[0] = 0;
  219. HWND hCc = GetDlgItem(hwnd,IDC_CRED);
  220. ASSERT(hCc);
  221. Credential_GetUserName(hCc,szUser,UNLEN);
  222. Credential_GetPassword(hCc,szPass,PWLEN);
  223. // Get contents of the cred control controls and write the session cred
  224. gfSuccess = WriteDomainCreds(szUser,szPass);
  225. SecureZeroMemory(szPass,sizeof(szPass));
  226. if (gfSuccess)
  227. {
  228. EndDialog(hwnd,IDOK);
  229. }
  230. }
  231. break;
  232. case IDCANCEL:
  233. if (HIWORD(wparam) == BN_CLICKED)
  234. {
  235. CHECKPOINT(5,"Leave the dialog by cancel.");
  236. // Exit doing nothing
  237. EndDialog(hwnd,IDCANCEL);
  238. }
  239. break;
  240. default:
  241. break;
  242. }
  243. break;
  244. default:
  245. break;
  246. }
  247. //return DefWindowProc(hwnd, msg, wparam, lparam);
  248. return FALSE;
  249. }
  250. int WINAPI WinMain (
  251. HINSTANCE hInstance,
  252. HINSTANCE hPrevInstance,
  253. LPSTR lpszCmdParam,
  254. int nCmdShow)
  255. {
  256. CHECKPOINTINIT;
  257. ghInstance = hInstance;
  258. //OleInitialize(NULL);
  259. INITCOMMONCONTROLSEX stICC;
  260. BOOL fICC;
  261. stICC.dwSize = sizeof(INITCOMMONCONTROLSEX);
  262. stICC.dwICC = ICC_WIN95_CLASSES | ICC_STANDARD_CLASSES;
  263. fICC = InitCommonControlsEx(&stICC);
  264. // Silent fail if there is no preexisting cert credential.
  265. CREDENTIAL *pCred = NULL;
  266. BOOL fOK = CredRead(L"*Session",CRED_TYPE_DOMAIN_CERTIFICATE,0,&pCred);
  267. CredFree(pCred);
  268. if (!fOK)
  269. {
  270. CHECKPOINT(1,"No preexisting certificate cred for *Session");
  271. CHECKPOINTFINISH;
  272. return 1;
  273. }
  274. // Gen up credui
  275. if (!CredUIInitControls())
  276. {
  277. return 1;
  278. }
  279. // show the ui
  280. INT_PTR iErr = DialogBoxParam(
  281. hInstance,
  282. MAKEINTRESOURCE(IDD_MAINDIALOG),
  283. GetForegroundWindow(),
  284. DialogProc,
  285. NULL);
  286. if (iErr != IDOK && iErr != IDCANCEL)
  287. {
  288. MessageBox(NULL,L"An error occurred saving credential information.",L"Error",MB_OK);
  289. CHECKPOINTFINISH;
  290. return 0;
  291. }
  292. else
  293. {
  294. CHECKPOINT(4,"Sucessfully saved a cred.");
  295. CHECKPOINTFINISH;
  296. return 1;
  297. }
  298. }