Source code of Windows XP (NT5)
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.

314 lines
8.0 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1998, Microsoft Corporation
  4. //
  5. // File: account.cxx
  6. //
  7. // Contents: Code to read and set the passwords for services. Adopted from
  8. // the code used by the service control manager to do the same.
  9. //
  10. // Classes:
  11. //
  12. // Functions: SCMgrGetPassword
  13. // ScGetPassword
  14. // ScOpenPolicy
  15. // ScFormSecretName
  16. // MapNTStatus
  17. //
  18. // History: January 16, 1998 Milans Created
  19. //
  20. //-----------------------------------------------------------------------------
  21. #include "smtpinc.h"
  22. #include "ntrtl.h"
  23. #include "nturtl.h"
  24. #include "ntlsa.h"
  25. #include "account.h"
  26. DWORD ScGetPassword(
  27. LPSTR szServiceName,
  28. LPSTR *pszPassword);
  29. DWORD ScOpenPolicy(
  30. ACCESS_MASK DesiredAccess,
  31. LSA_HANDLE *PolicyHandle);
  32. DWORD
  33. ScFormSecretName(
  34. LPSTR szServiceName,
  35. LPWSTR *pwszSecretName);
  36. DWORD
  37. MapNTStatus(
  38. NTSTATUS ntstatus);
  39. //+----------------------------------------------------------------------------
  40. //
  41. // Function: SCMgrGetPassword
  42. //
  43. // Synopsis: Reads the password configured for a given service.
  44. //
  45. // Arguments: [szServiceName] -- Name of service.
  46. // [cbPassword] -- Size in bytes of pszPassword buffer.
  47. // [pszPassword] -- The buffer in which to return the password.
  48. //
  49. // Returns: [ERROR_SUCCESS] -- Successfully returning password.
  50. // [ERROR_MORE_DATA] -- Password too big for passed in buffer.
  51. // [ERROR_INVALID_SREVICE_ACCOUNT] -- Unable to find password for
  52. // specified service.
  53. // [ERROR_ACCESS_DENIED] -- Priviledge violation reading password
  54. //
  55. //-----------------------------------------------------------------------------
  56. DWORD SCMgrGetPassword(
  57. LPSTR szServiceName,
  58. DWORD cbPassword,
  59. LPSTR pszPassword)
  60. {
  61. DWORD dwErr = ERROR_SUCCESS;
  62. LPSTR pszAllocatedPassword;
  63. pszAllocatedPassword = NULL;
  64. dwErr = ScGetPassword(szServiceName, &pszAllocatedPassword);
  65. if (dwErr == ERROR_SUCCESS) {
  66. if (strlen(pszAllocatedPassword) < cbPassword)
  67. strcpy(pszPassword, pszAllocatedPassword);
  68. else
  69. dwErr = ERROR_MORE_DATA;
  70. delete [] pszAllocatedPassword;
  71. }
  72. return( dwErr );
  73. }
  74. //+----------------------------------------------------------------------------
  75. //
  76. // Function: ScGetPassword
  77. //
  78. // Synopsis: Retrieves the configured password for a given service
  79. //
  80. // Arguments: [szServiceName] -- Name of service for which the configured
  81. // password is to be retrieved.
  82. // [pszPassword] -- On successful return, a string is allocated
  83. // using new and the password returned in it. Caller should
  84. // free using delete.
  85. //
  86. // Returns: [ERROR_SUCCESS] -- Successfully returning password.
  87. // [ERROR_INVALID_SERVICE_ACCOUNT] -- Service name not found.
  88. // [ERROR_ACCESS_DENIED] -- No access to password registry
  89. //
  90. //-----------------------------------------------------------------------------
  91. DWORD ScGetPassword(
  92. LPSTR szServiceName,
  93. LPSTR *pszPassword)
  94. {
  95. DWORD dwErr;
  96. NTSTATUS ntstatus;
  97. LSA_HANDLE PolicyHandle;
  98. LPWSTR LsaSecretName;
  99. UNICODE_STRING SecretNameString;
  100. PUNICODE_STRING NewPasswordString;
  101. //
  102. // Open a handle to the local security policy.
  103. //
  104. if (ScOpenPolicy(
  105. POLICY_CREATE_SECRET,
  106. &PolicyHandle
  107. ) != NO_ERROR) {
  108. return ERROR_INVALID_SERVICE_ACCOUNT;
  109. }
  110. //
  111. // Form the secret name under which the service password is stored
  112. //
  113. if ((dwErr = ScFormSecretName(
  114. szServiceName,
  115. &LsaSecretName
  116. )) != ERROR_SUCCESS) {
  117. (void) LsaClose(PolicyHandle);
  118. return dwErr;
  119. }
  120. RtlInitUnicodeString(&SecretNameString, LsaSecretName);
  121. ntstatus = LsaRetrievePrivateData(
  122. PolicyHandle,
  123. &SecretNameString,
  124. &NewPasswordString
  125. );
  126. if (NT_SUCCESS(ntstatus)) {
  127. *pszPassword = new CHAR[ NewPasswordString->Length + 1 ];
  128. if (*pszPassword != NULL) {
  129. wcstombs(
  130. *pszPassword,
  131. NewPasswordString->Buffer,
  132. NewPasswordString->Length/sizeof(WCHAR));
  133. (*pszPassword)[NewPasswordString->Length/sizeof(WCHAR)] = 0;
  134. dwErr = ERROR_SUCCESS;
  135. } else {
  136. dwErr = E_OUTOFMEMORY;
  137. }
  138. } else {
  139. dwErr = MapNTStatus( ntstatus );
  140. }
  141. delete [] LsaSecretName;
  142. (void) LsaClose(PolicyHandle);
  143. return dwErr;
  144. }
  145. //+----------------------------------------------------------------------------
  146. //
  147. // Function: ScOpenPolicy
  148. //
  149. // Synopsis: Opens the local security policy by calling LsaOpenPolicy.
  150. //
  151. // Arguments: [DesiredAccess] -- Desired access to Policy.
  152. // [PolicyHandle] -- The policy handle is returned here.
  153. //
  154. // Returns: [ERROR_SUCCESS] -- Successful return.
  155. // [ERROR_ACCESS_DENIED] -- No access to lsa policy.
  156. //
  157. //-----------------------------------------------------------------------------
  158. DWORD ScOpenPolicy(
  159. ACCESS_MASK DesiredAccess,
  160. LSA_HANDLE *PolicyHandle)
  161. {
  162. NTSTATUS ntstatus;
  163. OBJECT_ATTRIBUTES ObjAttributes;
  164. //
  165. // Open a handle to the local security policy. Initialize the
  166. // objects attributes structure first.
  167. //
  168. InitializeObjectAttributes(
  169. &ObjAttributes,
  170. NULL,
  171. 0L,
  172. NULL,
  173. NULL
  174. );
  175. ntstatus = LsaOpenPolicy(
  176. NULL,
  177. &ObjAttributes,
  178. DesiredAccess,
  179. PolicyHandle
  180. );
  181. return( MapNTStatus( ntstatus ) );
  182. }
  183. //+----------------------------------------------------------------------------
  184. //
  185. // Function: ScFormSecretName
  186. //
  187. // Synopsis: Forms the secret name used to store the password for the
  188. // service.
  189. //
  190. // Arguments: [szServiceName] -- The service name for which the
  191. // corresponding secret name is required.
  192. // [pwszSecretName] -- On successful return, a newly allocated
  193. // buffer, containing the UNICODE secret name, is returned
  194. // here. Caller should free using delete.
  195. //
  196. // Returns: [ERROR_SUCCESS] -- If successful
  197. // [E_OUTOFMEMORY] -- If unable to allocate space for
  198. // pwszSecretName.
  199. //
  200. //-----------------------------------------------------------------------------
  201. #define SC_SECRET_PREFIX "_SC_"
  202. #define SC_SECRET_PREFIX_W L"_SC_"
  203. DWORD
  204. ScFormSecretName(
  205. LPSTR szServiceName,
  206. LPWSTR *pwszSecretName)
  207. {
  208. DWORD cLen, cServiceNameLen;
  209. cServiceNameLen = strlen(szServiceName);
  210. cLen = sizeof( SC_SECRET_PREFIX ) + cServiceNameLen + 1;
  211. *pwszSecretName = new WCHAR[ cLen ];
  212. if (*pwszSecretName != NULL) {
  213. wcscpy( *pwszSecretName, SC_SECRET_PREFIX_W );
  214. mbstowcs(
  215. &(*pwszSecretName)[sizeof(SC_SECRET_PREFIX) - 1],
  216. szServiceName,
  217. cServiceNameLen + 1);
  218. return( ERROR_SUCCESS );
  219. } else {
  220. return( E_OUTOFMEMORY );
  221. }
  222. }
  223. //+----------------------------------------------------------------------------
  224. //
  225. // Function: MapNTStatus
  226. //
  227. // Synopsis: Simple function to map some registry related NT statuses to
  228. // Win32 errors.
  229. //
  230. // Arguments: [ntstatus] -- The NT Status to map
  231. //
  232. // Returns: Win32 error corresponding to ntstatus
  233. //
  234. //-----------------------------------------------------------------------------
  235. DWORD
  236. MapNTStatus(
  237. NTSTATUS ntstatus)
  238. {
  239. DWORD dwErr;
  240. switch (ntstatus) {
  241. case STATUS_SUCCESS:
  242. dwErr = ERROR_SUCCESS;
  243. break;
  244. case STATUS_ACCESS_DENIED:
  245. dwErr = ERROR_ACCESS_DENIED;
  246. break;
  247. default:
  248. dwErr = ERROR_INVALID_SERVICE_ACCOUNT;
  249. break;
  250. }
  251. return( dwErr );
  252. }