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.

138 lines
4.1 KiB

  1. #include "stdafx.h"
  2. #include "password.h"
  3. #include <strsafe.h>
  4. // password categories
  5. enum {STRONG_PWD_UPPER=0,STRONG_PWD_LOWER,STRONG_PWD_NUM,STRONG_PWD_PUNC};
  6. #define STRONG_PWD_CATS (STRONG_PWD_PUNC + 1)
  7. #define NUM_LETTERS 26
  8. #define NUM_NUMBERS 10
  9. #define MIN_PWD_LEN 8
  10. // password must contain at least one each of:
  11. // uppercase, lowercase, punctuation and numbers
  12. DWORD CreateGoodPassword(BYTE *szPwd, DWORD dwLen)
  13. {
  14. if (dwLen-1 < MIN_PWD_LEN)
  15. {
  16. return ERROR_PASSWORD_RESTRICTION;
  17. }
  18. HCRYPTPROV hProv;
  19. DWORD dwErr = 0;
  20. if (CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT) == FALSE)
  21. {
  22. return GetLastError();
  23. }
  24. // zero it out and decrement the size to allow for trailing '\0'
  25. SecureZeroMemory(szPwd,dwLen);
  26. dwLen--;
  27. // generate a pwd pattern, each byte is in the range
  28. // (0..255) mod STRONG_PWD_CATS
  29. // this indicates which character pool to take a char from
  30. BYTE *pPwdPattern = new BYTE[dwLen];
  31. BOOL fFound[STRONG_PWD_CATS];
  32. do
  33. {
  34. // bug!bug! does CGR() ever fail?
  35. CryptGenRandom(hProv,dwLen,pPwdPattern);
  36. fFound[STRONG_PWD_UPPER] =
  37. fFound[STRONG_PWD_LOWER] =
  38. fFound[STRONG_PWD_PUNC] =
  39. fFound[STRONG_PWD_NUM] = FALSE;
  40. for (DWORD i=0; i < dwLen; i++)
  41. {
  42. fFound[pPwdPattern[i] % STRONG_PWD_CATS] = TRUE;
  43. }
  44. // check that each character category is in the pattern
  45. } while (!fFound[STRONG_PWD_UPPER] || !fFound[STRONG_PWD_LOWER] || !fFound[STRONG_PWD_PUNC] || !fFound[STRONG_PWD_NUM]);
  46. // populate password with random data
  47. // this, in conjunction with pPwdPattern, is
  48. // used to determine the actual data
  49. CryptGenRandom(hProv,dwLen,szPwd);
  50. for (DWORD i=0; i < dwLen; i++)
  51. {
  52. BYTE bChar = 0;
  53. // there is a bias in each character pool because of the % function
  54. switch (pPwdPattern[i] % STRONG_PWD_CATS)
  55. {
  56. case STRONG_PWD_UPPER : bChar = 'A' + szPwd[i] % NUM_LETTERS;
  57. break;
  58. case STRONG_PWD_LOWER : bChar = 'a' + szPwd[i] % NUM_LETTERS;
  59. break;
  60. case STRONG_PWD_NUM : bChar = '0' + szPwd[i] % NUM_NUMBERS;
  61. break;
  62. case STRONG_PWD_PUNC :
  63. default:
  64. char *szPunc="!@#$%^&*()_-+=[{]};:\'\"<>,./?\\|~`";
  65. DWORD dwLenPunc = lstrlenA(szPunc);
  66. bChar = szPunc[szPwd[i] % dwLenPunc];
  67. break;
  68. }
  69. szPwd[i] = bChar;
  70. }
  71. if (pPwdPattern)
  72. {
  73. delete [] pPwdPattern;
  74. }
  75. if (hProv != NULL)
  76. {
  77. CryptReleaseContext(hProv,0);
  78. }
  79. return dwErr;
  80. }
  81. // Creates a secure password
  82. // caller must LocalFree Return pointer
  83. // iSize = size of password to create
  84. LPTSTR CreatePassword(int iSize)
  85. {
  86. LPTSTR pszPassword = NULL;
  87. BYTE *szPwd = new BYTE[iSize];
  88. DWORD dwPwdLen = iSize;
  89. int i = 0;
  90. // use the new secure password generator
  91. // unfortunately this baby doesn't use unicode.
  92. // so we'll call it and then convert it to unicode afterwards.
  93. if (0 == CreateGoodPassword(szPwd,dwPwdLen))
  94. {
  95. #if defined(UNICODE) || defined(_UNICODE)
  96. // convert it to unicode and copy it back into our unicode buffer.
  97. // compute the length
  98. i = MultiByteToWideChar(CP_ACP, 0, (LPSTR) szPwd, -1, NULL, 0);
  99. if (i <= 0)
  100. {goto CreatePassword_Exit;}
  101. pszPassword = (LPTSTR) LocalAlloc(LPTR, i * sizeof(TCHAR));
  102. if (!pszPassword)
  103. {goto CreatePassword_Exit;}
  104. i = MultiByteToWideChar(CP_ACP, 0, (LPSTR) szPwd, -1, pszPassword, i);
  105. if (i <= 0)
  106. {
  107. LocalFree(pszPassword);
  108. pszPassword = NULL;
  109. goto CreatePassword_Exit;
  110. }
  111. // make sure ends with null
  112. pszPassword[i - 1] = 0;
  113. #else
  114. pszPassword = (LPSTR) LocalAlloc(GPTR, _tcslen((LPTSTR) szPwd) * sizeof(TCHAR));
  115. #endif
  116. }
  117. CreatePassword_Exit:
  118. if (szPwd){delete [] szPwd;szPwd=NULL;}
  119. return pszPassword;
  120. }