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.

550 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994-2001 Microsoft Corporation
  3. Module Name :
  4. authent.cpp
  5. Abstract:
  6. WWW Authentication Dialog
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. --*/
  14. #include "stdafx.h"
  15. #include "resource.h"
  16. #include "common.h"
  17. #include "inetprop.h"
  18. #include "inetmgrapp.h"
  19. #include "supdlgs.h"
  20. #include "certmap.h"
  21. #include "authent.h"
  22. #define INITGUID
  23. #include <initguid.h>
  24. #include <dsclient.h>
  25. #include <wincrui.h>
  26. #include <Dsgetdc.h>
  27. #include <Lm.h>
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. #define HIDD_DOMAINACCTS 0x50334
  34. CAuthenticationDlg::CAuthenticationDlg(
  35. IN LPCTSTR lpstrServerName,
  36. IN DWORD dwInstance,
  37. IN CString & strBasicDomain,
  38. IN CString & strRealm,
  39. IN DWORD & dwAuthFlags,
  40. IN DWORD & dwAccessPermissions,
  41. IN CString & strUserName,
  42. IN CStrPassword & strPassword,
  43. IN BOOL & fPasswordSync,
  44. IN BOOL fAdminAccess,
  45. IN BOOL fHasDigest,
  46. IN CWnd * pParent OPTIONAL
  47. )
  48. /*++
  49. Routine Description:
  50. Authentication dialog constructor
  51. Arguments:
  52. LPCTSTR lpstrServerName : Server name
  53. DWORD dwInstance : Instance number
  54. CString & strBasicDomain : Basic domain name
  55. DWORD & dwAuthFlags : Authorization flags
  56. DWORD & dwAccessPermissions : Access permissions
  57. CString & strUserName : Anonymous user name
  58. CStrPassword & strPassword : Anonymous user pwd
  59. BOOL & fPasswordSync : Password sync setting
  60. BOOL fAdminAccess : TRUE if user has admin access
  61. BOOL fHasDigest : TRUE if machine supports digest auth.
  62. CWnd * pParent : Optional parent window
  63. Return Value:
  64. N/A
  65. --*/
  66. : CDialog(CAuthenticationDlg::IDD, pParent),
  67. m_strServerName(lpstrServerName),
  68. m_strBasicDomain(strBasicDomain),
  69. m_strRealm(strRealm),
  70. m_strUserName(strUserName),
  71. m_strPassword(strPassword),
  72. m_dwInstance(dwInstance),
  73. m_dwAuthFlags(dwAuthFlags),
  74. m_dwAccessPermissions(dwAccessPermissions),
  75. m_fAdminAccess(fAdminAccess),
  76. m_fHasDigest(fHasDigest),
  77. m_fPasswordSync(fPasswordSync),
  78. m_fPasswordSyncChanged(FALSE),
  79. m_fUserNameChanged(FALSE),
  80. m_fPasswordSyncMsgShown(FALSE),
  81. m_fChanged(FALSE),
  82. m_fInDomain(TRUE),
  83. m_fHasPassport(TRUE)
  84. {
  85. #if 0 // Class Wizard happy
  86. //{{AFX_DATA_INIT(CAuthenticationDlg)
  87. m_fClearText = FALSE;
  88. m_fDigest = FALSE;
  89. m_fChallengeResponse = FALSE;
  90. m_fAnonymous = FALSE;
  91. //}}AFX_DATA_INIT
  92. #endif // 0
  93. m_fClearText = IS_FLAG_SET(m_dwAuthFlags, MD_AUTH_BASIC);
  94. m_fDigest = IS_FLAG_SET(m_dwAuthFlags, MD_AUTH_MD5);
  95. m_fChallengeResponse = IS_FLAG_SET(m_dwAuthFlags, MD_AUTH_NT);
  96. m_fAnonymous = IS_FLAG_SET(m_dwAuthFlags, MD_AUTH_ANONYMOUS);
  97. m_fPassport = IS_FLAG_SET(m_dwAuthFlags, MD_AUTH_PASSPORT);
  98. }
  99. void
  100. CAuthenticationDlg::DoDataExchange(
  101. IN CDataExchange * pDX
  102. )
  103. {
  104. if (pDX->m_bSaveAndValidate && !m_fChanged)
  105. {
  106. return;
  107. }
  108. CDialog::DoDataExchange(pDX);
  109. //{{AFX_DATA_MAP(CAuthenticationDlg)
  110. DDX_Control(pDX, IDC_CHECK_ANONYMOUS, m_check_Anonymous);
  111. DDX_Check(pDX, IDC_CHECK_ANONYMOUS, m_fAnonymous);
  112. DDX_Control(pDX, IDC_EDIT_USERNAME, m_edit_UserName);
  113. DDX_Control(pDX, IDC_EDIT_PASSWORD, m_edit_Password);
  114. DDX_Check(pDX, IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, m_fPasswordSync);
  115. DDX_Control(pDX, IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, m_chk_PasswordSync);
  116. DDX_Check(pDX, IDC_CHECK_CLEAR_TEXT, m_fClearText);
  117. DDX_Check(pDX, IDC_CHECK_DIGEST, m_fDigest);
  118. DDX_Check(pDX, IDC_CHECK_NT_CHALLENGE_RESPONSE, m_fChallengeResponse);
  119. DDX_Check(pDX, IDC_PASSPORT, m_fPassport);
  120. DDX_Control(pDX, IDC_CHECK_NT_CHALLENGE_RESPONSE, m_check_ChallengeResponse);
  121. DDX_Control(pDX, IDC_CHECK_DIGEST, m_check_Digest);
  122. DDX_Control(pDX, IDC_CHECK_CLEAR_TEXT, m_check_ClearText);
  123. DDX_Control(pDX, IDC_BASDOM, m_edit_BasicDomain);
  124. DDX_Control(pDX, IDC_BASDOM_SELECT, m_btn_SelectDomain);
  125. DDX_Control(pDX, IDC_REALM, m_edit_Realm);
  126. DDX_Control(pDX, IDC_REALM_SELECT, m_btn_SelectRealm);
  127. DDX_Control(pDX, IDC_PASSPORT, m_chk_Passport);
  128. //}}AFX_DATA_MAP
  129. DDX_Text(pDX, IDC_EDIT_USERNAME, m_strUserName);
  130. DDV_MinMaxChars(pDX, m_strUserName, 1, UNLEN);
  131. DDX_Text(pDX, IDC_BASDOM, m_strBasicDomain);
  132. DDX_Text(pDX, IDC_REALM, m_strRealm);
  133. //
  134. // Some people have a tendency to add "\\" before
  135. // the computer name in user accounts. Fix this here.
  136. //
  137. m_strUserName.TrimLeft();
  138. while (*m_strUserName == '\\')
  139. {
  140. m_strUserName = m_strUserName.Mid(2);
  141. }
  142. //
  143. // Display the remote password sync message if
  144. // password sync is on, the account is not local,
  145. // password sync has changed or username has changed
  146. // and the message hasn't already be shown.
  147. //
  148. if (pDX->m_bSaveAndValidate)
  149. {
  150. BOOL bLocal;
  151. CString user, domain;
  152. CError err = CredUIParseUserName(
  153. m_strUserName,
  154. user.GetBuffer(CRED_MAX_USERNAME_LENGTH), CRED_MAX_USERNAME_LENGTH,
  155. domain.GetBuffer(MAX_PATH), MAX_PATH);
  156. user.ReleaseBuffer();
  157. domain.ReleaseBuffer();
  158. bLocal = domain.IsEmpty() || domain.CompareNoCase(m_strServerName) == 0;
  159. if (m_dwVersionMajor < 6)
  160. {
  161. if (m_fPasswordSync && !bLocal
  162. && (m_fPasswordSyncChanged || m_fUserNameChanged)
  163. && !m_fPasswordSyncMsgShown
  164. )
  165. {
  166. //
  167. // Don't show it again
  168. //
  169. m_fPasswordSyncMsgShown = TRUE;
  170. if (IDYES != ::AfxMessageBox(IDS_WRN_PWSYNC, MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION ))
  171. {
  172. pDX->Fail();
  173. }
  174. }
  175. }
  176. // See if we need to get the new password...
  177. if (m_fAnonymous)
  178. {
  179. // only save password/and ask for password confirmation
  180. // if anonymous is enabled.
  181. DDX_Password_SecuredString(pDX, IDC_EDIT_PASSWORD, m_strPassword, g_lpszDummyPassword);
  182. }
  183. // Convert to standard domain\user format
  184. if (!bLocal)
  185. {
  186. m_strUserName = domain;
  187. m_strUserName += _T('\\');
  188. m_strUserName += user;
  189. }
  190. }
  191. else
  192. {
  193. DDX_Password_SecuredString(pDX, IDC_EDIT_PASSWORD, m_strPassword, g_lpszDummyPassword);
  194. }
  195. if (!m_fPasswordSync)
  196. {
  197. DDV_MaxCharsBalloon_SecuredString(pDX, m_strPassword, PWLEN);
  198. }
  199. if (pDX->m_bSaveAndValidate)
  200. {
  201. m_fChanged = FALSE;
  202. }
  203. //CString csTempPassword;m_strPassword.CopyTo(csTempPassword);
  204. }
  205. //
  206. // Message Map
  207. //
  208. BEGIN_MESSAGE_MAP(CAuthenticationDlg, CDialog)
  209. //{{AFX_MSG_MAP(CAuthenticationDlg)
  210. ON_BN_CLICKED(IDC_CHECK_ANONYMOUS, OnCheckAnonymous)
  211. ON_BN_CLICKED(IDC_BUTTON_BROWSE_USERS, OnButtonBrowseUsers)
  212. ON_BN_CLICKED(IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, OnCheckEnablePwSynchronization)
  213. ON_EN_CHANGE(IDC_EDIT_USERNAME, OnChangeEditUsername)
  214. ON_BN_CLICKED(IDC_CHECK_CLEAR_TEXT, OnCheckClearText)
  215. ON_BN_CLICKED(IDC_CHECK_DIGEST, OnCheckDigest)
  216. ON_BN_CLICKED(IDC_CHECK_NT_CHALLENGE_RESPONSE, OnItemChanged)
  217. ON_BN_CLICKED(IDC_BASDOM_SELECT, OnButtonSelectDomain)
  218. ON_BN_CLICKED(IDC_REALM_SELECT, OnButtonSelectRealm)
  219. ON_BN_CLICKED(IDC_PASSPORT, OnCheckPassport)
  220. //}}AFX_MSG_MAP
  221. ON_EN_CHANGE(IDC_EDIT_PASSWORD, OnItemChanged)
  222. ON_EN_CHANGE(IDC_EDIT_DOMAIN_NAME, OnItemChanged)
  223. ON_EN_CHANGE(IDC_BASDOM, OnItemChanged)
  224. ON_EN_CHANGE(IDC_REALM, OnItemChanged)
  225. END_MESSAGE_MAP()
  226. void
  227. CAuthenticationDlg::OnItemChanged()
  228. {
  229. m_fChanged = TRUE;
  230. }
  231. void
  232. CAuthenticationDlg::SetControlStates()
  233. /*++
  234. Routine Description:
  235. Set control states depending on current data in the dialog
  236. --*/
  237. {
  238. m_edit_UserName.EnableWindow(m_fAnonymous);
  239. GetDlgItem(IDC_BUTTON_BROWSE_USERS)->EnableWindow(m_fAnonymous);
  240. m_chk_PasswordSync.EnableWindow(m_dwVersionMajor < 6 && m_fAnonymous);
  241. m_edit_Password.EnableWindow((m_dwVersionMajor >= 6 || !m_fPasswordSync) && m_fAnonymous);
  242. // Windows
  243. m_check_ChallengeResponse.EnableWindow(!m_fPassport);
  244. // Basic
  245. m_check_ClearText.EnableWindow(!m_fPassport);
  246. // Digest
  247. m_check_Digest.EnableWindow(m_fHasDigest && !m_fPassport);
  248. // disable both domain fields if nothing is selected
  249. GetDlgItem(IDC_STATIC_DOMAIN)->EnableWindow(FALSE);
  250. m_edit_BasicDomain.EnableWindow(FALSE);
  251. m_btn_SelectDomain.EnableWindow(FALSE);
  252. GetDlgItem(IDC_STATIC_REALM)->EnableWindow(FALSE);
  253. m_edit_Realm.EnableWindow(FALSE);
  254. m_btn_SelectRealm.EnableWindow(FALSE);
  255. if (m_fPassport)
  256. {
  257. GetDlgItem(IDC_STATIC_DOMAIN)->EnableWindow(TRUE);
  258. m_edit_BasicDomain.EnableWindow(TRUE);
  259. m_btn_SelectDomain.EnableWindow(m_fInDomain);
  260. }
  261. else
  262. {
  263. if (m_fDigest && !m_fClearText)
  264. {
  265. GetDlgItem(IDC_STATIC_REALM)->EnableWindow(TRUE);
  266. m_edit_Realm.EnableWindow(TRUE);
  267. m_btn_SelectRealm.EnableWindow(m_fInDomain);
  268. }
  269. else if (m_fClearText)
  270. {
  271. GetDlgItem(IDC_STATIC_REALM)->EnableWindow(TRUE);
  272. m_edit_Realm.EnableWindow(TRUE);
  273. m_btn_SelectRealm.EnableWindow(m_fInDomain);
  274. GetDlgItem(IDC_STATIC_DOMAIN)->EnableWindow(TRUE);
  275. m_edit_BasicDomain.EnableWindow(TRUE);
  276. m_btn_SelectDomain.EnableWindow(m_fInDomain);
  277. }
  278. }
  279. }
  280. BOOL
  281. CAuthenticationDlg::OnInitDialog()
  282. {
  283. CDialog::OnInitDialog();
  284. // Check if computer is joined to domain
  285. COMPUTER_NAME_FORMAT fmt = ComputerNamePhysicalDnsDomain;
  286. TCHAR buf[MAX_PATH];
  287. DWORD n = MAX_PATH;
  288. m_fInDomain = (GetComputerNameEx(fmt, buf, &n) && n > 0);
  289. SetControlStates();
  290. if (m_dwVersionMajor < 6)
  291. {
  292. // Show/Hide Passport stuff
  293. m_chk_Passport.EnableWindow(FALSE);
  294. }
  295. else
  296. {
  297. // Hide password syncronization
  298. GetDlgItem(IDC_CHECK_ENABLE_PW_SYNCHRONIZATION)->EnableWindow(FALSE);
  299. GetDlgItem(IDC_CHECK_ENABLE_PW_SYNCHRONIZATION)->ShowWindow(SW_HIDE);
  300. m_fPasswordSync = FALSE;
  301. m_fPasswordSyncChanged = FALSE;
  302. m_fPasswordSyncMsgShown = TRUE;
  303. }
  304. return TRUE;
  305. }
  306. void
  307. CAuthenticationDlg::OnButtonBrowseUsers()
  308. {
  309. CString str;
  310. if (GetIUsrAccount(m_strServerName, this, str))
  311. {
  312. //
  313. // If the name is non-local (determined by having
  314. // a slash in the name, password sync is disabled,
  315. // and a password should be entered.
  316. //
  317. m_edit_UserName.SetWindowText(str);
  318. CString user, domain;
  319. CError err = CredUIParseUserName(str,
  320. user.GetBuffer(CRED_MAX_USERNAME_LENGTH), CRED_MAX_USERNAME_LENGTH,
  321. domain.GetBuffer(MAX_PATH), MAX_PATH);
  322. user.ReleaseBuffer();
  323. domain.ReleaseBuffer();
  324. if (m_dwVersionMajor < 6)
  325. {
  326. m_fPasswordSync =
  327. domain.IsEmpty() || domain.CompareNoCase(m_strServerName) == 0;
  328. m_chk_PasswordSync.SetCheck(m_fPasswordSync);
  329. }
  330. if (!m_fPasswordSync)
  331. {
  332. m_edit_Password.SetWindowText(_T(""));
  333. m_edit_Password.SetFocus();
  334. }
  335. OnItemChanged();
  336. }
  337. }
  338. void CAuthenticationDlg::OnButtonSelectDomain()
  339. {
  340. HRESULT hr = BrowseDomain(m_strBasicDomain);
  341. if (SUCCEEDED(hr))
  342. {
  343. UpdateData(FALSE);
  344. OnItemChanged();
  345. }
  346. }
  347. void CAuthenticationDlg::OnButtonSelectRealm()
  348. {
  349. HRESULT hr = BrowseDomain(m_strRealm);
  350. if (SUCCEEDED(hr))
  351. {
  352. UpdateData(FALSE);
  353. OnItemChanged();
  354. }
  355. }
  356. HRESULT
  357. CAuthenticationDlg::BrowseDomain(CString& domain)
  358. {
  359. CString prev = domain;
  360. CComPtr<IDsBrowseDomainTree> spDsDomains;
  361. CError err = ::CoCreateInstance(CLSID_DsDomainTreeBrowser,
  362. NULL,
  363. CLSCTX_INPROC_SERVER,
  364. IID_IDsBrowseDomainTree,
  365. reinterpret_cast<void **>(&spDsDomains));
  366. if (err.Succeeded())
  367. {
  368. err = spDsDomains->SetComputer(m_strServerName, NULL, NULL); // use default credential
  369. if (err.Succeeded())
  370. {
  371. LPTSTR pDomainPath = NULL;
  372. err = spDsDomains->BrowseTo(m_hWnd, &pDomainPath,
  373. /*DBDTF_RETURNINOUTBOUND |*/ DBDTF_RETURNEXTERNAL | DBDTF_RETURNMIXEDDOMAINS);
  374. if (err.Succeeded() && pDomainPath != NULL)
  375. {
  376. domain = pDomainPath;
  377. if (domain.CompareNoCase(prev) != 0)
  378. {
  379. OnItemChanged();
  380. }
  381. CoTaskMemFree(pDomainPath);
  382. }
  383. // When user click on Cancel in this browser, it returns 80070001 (Incorrect function).
  384. // I am not quite sure what does it mean. We are filtering out the case when domain browser doesn't
  385. // work at all (in workgroup), so here we could safely skip error processing.
  386. // else
  387. // {
  388. // err.MessageBox();
  389. // }
  390. }
  391. }
  392. return err;
  393. }
  394. void
  395. CAuthenticationDlg::OnCheckEnablePwSynchronization()
  396. {
  397. m_fPasswordSyncChanged = TRUE;
  398. m_fPasswordSync = !m_fPasswordSync;
  399. OnItemChanged();
  400. SetControlStates();
  401. if (!m_fPasswordSync )
  402. {
  403. m_edit_Password.SetSel(0,-1);
  404. m_edit_Password.SetFocus();
  405. }
  406. }
  407. void
  408. CAuthenticationDlg::OnChangeEditUsername()
  409. {
  410. m_fUserNameChanged = TRUE;
  411. OnItemChanged();
  412. }
  413. void
  414. CAuthenticationDlg::OnCheckClearText()
  415. {
  416. if (m_check_ClearText.GetCheck() == 1)
  417. {
  418. CClearTxtDlg dlg;
  419. if (dlg.DoModal() != IDOK)
  420. {
  421. m_check_ClearText.SetCheck(0);
  422. return;
  423. }
  424. }
  425. m_fClearText = !m_fClearText;
  426. OnItemChanged();
  427. SetControlStates();
  428. }
  429. void
  430. CAuthenticationDlg::OnCheckDigest()
  431. {
  432. ASSERT(m_fHasDigest);
  433. if (m_check_Digest.GetCheck() == 1)
  434. {
  435. CString cap, msg;
  436. msg.LoadString(IDS_WRN_DIGEST);
  437. cap.LoadString(IDS_APP_NAME);
  438. if (IDNO == IisMessageBox(m_hWnd, IDS_WRN_DIGEST, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2, HIDD_DOMAINACCTS))
  439. {
  440. m_check_Digest.SetCheck(0);
  441. return;
  442. }
  443. }
  444. m_fDigest = !m_fDigest;
  445. OnItemChanged();
  446. SetControlStates();
  447. }
  448. void
  449. CAuthenticationDlg::OnCheckAnonymous()
  450. {
  451. m_fAnonymous = !m_fAnonymous;
  452. OnItemChanged();
  453. SetControlStates();
  454. }
  455. void
  456. CAuthenticationDlg::OnCheckPassport()
  457. {
  458. m_fPassport = !m_fPassport;
  459. OnItemChanged();
  460. SetControlStates();
  461. }
  462. void
  463. CAuthenticationDlg::OnOK()
  464. {
  465. if (UpdateData(TRUE))
  466. {
  467. SET_FLAG_IF(m_fPassport, m_dwAuthFlags, MD_AUTH_PASSPORT);
  468. SET_FLAG_IF(m_fClearText, m_dwAuthFlags, MD_AUTH_BASIC);
  469. SET_FLAG_IF(m_fChallengeResponse, m_dwAuthFlags, MD_AUTH_NT);
  470. SET_FLAG_IF(m_fAnonymous, m_dwAuthFlags, MD_AUTH_ANONYMOUS);
  471. SET_FLAG_IF(m_fDigest, m_dwAuthFlags, MD_AUTH_MD5);
  472. //
  473. // Provide warning if no authentication is selected
  474. //
  475. if (!m_dwAuthFlags
  476. && !m_dwAccessPermissions
  477. && !NoYesMessageBox(IDS_WRN_NO_AUTH)
  478. )
  479. {
  480. //
  481. // Don't dismiss the dialog
  482. //
  483. return;
  484. }
  485. CDialog::OnOK();
  486. }
  487. }