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.

805 lines
16 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. secutil.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. DNS secure update API.
  8. Author:
  9. Jim Gilroy (jamesg) January, 1998
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. // security headers
  14. //#define SECURITY_WIN32
  15. //#include "sspi.h"
  16. //#include "issperr.h"
  17. //#include "rpc.h"
  18. //#include "rpcndr.h"
  19. //#include "ntdsapi.h"
  20. //
  21. // Security utilities
  22. //
  23. DNS_STATUS
  24. Dns_CreateSecurityDescriptor(
  25. OUT PSECURITY_DESCRIPTOR * ppSD,
  26. IN DWORD AclCount,
  27. IN PSID * SidPtrArray,
  28. IN DWORD * AccessMaskArray
  29. )
  30. /*++
  31. Routine Description:
  32. Build security descriptor.
  33. Arguments:
  34. ppSD -- addr to receive SD created
  35. AclCount -- number of ACLs to add
  36. SidPtrArray -- array of SIDs to create ACLs for
  37. AccessMaskArray -- array of access masks corresponding to SIDs
  38. Return Value:
  39. ERROR_SUCCESS if successful
  40. Error code on failure.
  41. --*/
  42. {
  43. DNS_STATUS status;
  44. DWORD i;
  45. DWORD lengthAcl;
  46. PSECURITY_DESCRIPTOR psd = NULL;
  47. PACL pacl;
  48. //
  49. // calculate space for SD
  50. //
  51. lengthAcl = sizeof(ACL);
  52. for ( i=0; i<AclCount; i++ )
  53. {
  54. if ( SidPtrArray[i] && AccessMaskArray[i] )
  55. {
  56. lengthAcl += GetLengthSid( SidPtrArray[i] ) + sizeof(ACCESS_ALLOWED_ACE);
  57. }
  58. ELSE
  59. {
  60. DNS_PRINT((
  61. "ERROR: SD building with SID (%p) and mask (%p)\n",
  62. SidPtrArray[i],
  63. AccessMaskArray[i] ));
  64. }
  65. }
  66. //
  67. // allocate SD
  68. //
  69. psd = (PSECURITY_DESCRIPTOR) ALLOCATE_HEAP(
  70. SECURITY_DESCRIPTOR_MIN_LENGTH + lengthAcl );
  71. if ( !psd )
  72. {
  73. status = DNS_ERROR_NO_MEMORY;
  74. goto Failed;
  75. }
  76. DNSDBG( INIT, (
  77. "Allocated SecurityDesc at %p of length %d\n",
  78. psd,
  79. SECURITY_DESCRIPTOR_MIN_LENGTH + lengthAcl ));
  80. //
  81. // build ACL, adding ACE with desired access for each SID
  82. //
  83. pacl = (PACL) ((PBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  84. if ( !InitializeAcl(
  85. pacl,
  86. lengthAcl,
  87. ACL_REVISION ) )
  88. {
  89. status = GetLastError();
  90. goto Failed;
  91. }
  92. for ( i=0; i<AclCount; i++ )
  93. {
  94. if ( SidPtrArray[i] && AccessMaskArray[i] )
  95. {
  96. if ( !AddAccessAllowedAce(
  97. pacl,
  98. ACL_REVISION,
  99. AccessMaskArray[i],
  100. SidPtrArray[i] ) )
  101. {
  102. status = GetLastError();
  103. DNSDBG( ANY, (
  104. "ERROR: failed adding ACE for SID %p, mask %p\n",
  105. SidPtrArray[i],
  106. AccessMaskArray[i] ));
  107. goto Failed;
  108. }
  109. }
  110. }
  111. //
  112. // setup SD with ACL
  113. //
  114. if ( !InitializeSecurityDescriptor(
  115. psd,
  116. SECURITY_DESCRIPTOR_REVISION ))
  117. {
  118. status = GetLastError();
  119. goto Failed;
  120. }
  121. if ( !SetSecurityDescriptorDacl(
  122. psd,
  123. TRUE, // ACL present
  124. pacl,
  125. FALSE // explicit ACL, not defaulted
  126. ))
  127. {
  128. status = GetLastError();
  129. goto Failed;
  130. }
  131. *ppSD = psd;
  132. return( ERROR_SUCCESS );
  133. Failed:
  134. ASSERT( status != ERROR_SUCCESS );
  135. *ppSD = NULL;
  136. FREE_HEAP( psd );
  137. return( status );
  138. }
  139. //
  140. // Credential utilities
  141. //
  142. PSEC_WINNT_AUTH_IDENTITY_W
  143. Dns_AllocateAndInitializeCredentialsW(
  144. IN PSEC_WINNT_AUTH_IDENTITY_W pAuthIn
  145. )
  146. /*++
  147. Description:
  148. Allocates auth identity info and initializes pAuthIn info
  149. Parameters:
  150. pAuthIn -- auth identity info
  151. Return:
  152. Ptr to newly create credentials.
  153. NULL on failure.
  154. --*/
  155. {
  156. PSEC_WINNT_AUTH_IDENTITY_W pauthCopy = NULL;
  157. DNSDBG( SECURITY, (
  158. "Call Dns_AllocateAndInitializeCredentialsW\n" ));
  159. if ( !pAuthIn )
  160. {
  161. return NULL;
  162. }
  163. ASSERT( pAuthIn->Flags == SEC_WINNT_AUTH_IDENTITY_UNICODE );
  164. //
  165. // allocate credentials struct
  166. // - zero for simple cleanup on subfield alloc failures
  167. //
  168. pauthCopy = ALLOCATE_HEAP_ZERO( sizeof(SEC_WINNT_AUTH_IDENTITY_W) );
  169. if ( !pauthCopy )
  170. {
  171. return NULL;
  172. }
  173. //
  174. // copy subfields
  175. //
  176. // user
  177. pauthCopy->UserLength = pAuthIn->UserLength;
  178. if ( pAuthIn->UserLength )
  179. {
  180. ASSERT( pAuthIn->UserLength == wcslen(pAuthIn->User) );
  181. pauthCopy->User = ALLOCATE_HEAP( (pAuthIn->UserLength + 1) * sizeof(WCHAR) );
  182. if ( ! pauthCopy->User )
  183. {
  184. goto Failed;
  185. }
  186. wcscpy( pauthCopy->User, pAuthIn->User );
  187. }
  188. // password
  189. // - must allow zero length password
  190. pauthCopy->PasswordLength = pAuthIn->PasswordLength;
  191. if ( pAuthIn->PasswordLength || pAuthIn->Password )
  192. {
  193. ASSERT( pAuthIn->PasswordLength == wcslen(pAuthIn->Password) );
  194. pauthCopy->Password = ALLOCATE_HEAP( (pAuthIn->PasswordLength + 1) * sizeof(WCHAR) );
  195. if ( ! pauthCopy->Password )
  196. {
  197. goto Failed;
  198. }
  199. wcscpy( pauthCopy->Password, pAuthIn->Password );
  200. }
  201. // domain
  202. pauthCopy->DomainLength = pAuthIn->DomainLength;
  203. if ( pAuthIn->DomainLength )
  204. {
  205. ASSERT( pAuthIn->DomainLength == wcslen(pAuthIn->Domain) );
  206. pauthCopy->Domain = ALLOCATE_HEAP( (pAuthIn->DomainLength + 1) * sizeof(WCHAR) );
  207. if ( ! pauthCopy->Domain )
  208. {
  209. goto Failed;
  210. }
  211. wcscpy( pauthCopy->Domain, pAuthIn->Domain );
  212. }
  213. pauthCopy->Flags = pAuthIn->Flags;
  214. DNSDBG( SECURITY, (
  215. "Exit Dns_AllocateAndInitializeCredentialsW()\n" ));
  216. return pauthCopy;
  217. Failed:
  218. // allocation failure
  219. // - cleanup what was allocated and get out
  220. Dns_FreeAuthIdentityCredentials( pauthCopy );
  221. return( NULL );
  222. }
  223. PSEC_WINNT_AUTH_IDENTITY_A
  224. Dns_AllocateAndInitializeCredentialsA(
  225. IN PSEC_WINNT_AUTH_IDENTITY_A pAuthIn
  226. )
  227. /*++
  228. Description:
  229. Allocates auth identity info and initializes pAuthIn info
  230. Note: it is more work to convert to unicode and call previous
  231. function than to call this one
  232. Parameters:
  233. pAuthIn -- auth identity info
  234. Return:
  235. Ptr to newly create credentials.
  236. NULL on failure.
  237. --*/
  238. {
  239. PSEC_WINNT_AUTH_IDENTITY_A pauthCopy = NULL;
  240. DNSDBG( SECURITY, (
  241. "Call Dns_AllocateAndInitializeCredentialsA\n" ));
  242. //
  243. // allocate credentials struct
  244. // - zero for simple cleanup on subfield alloc failures
  245. //
  246. if ( !pAuthIn )
  247. {
  248. return NULL;
  249. }
  250. ASSERT( pAuthIn->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI );
  251. //
  252. // allocate credentials struct
  253. // - zero for simple cleanup on subfield alloc failures
  254. //
  255. pauthCopy = ALLOCATE_HEAP_ZERO( sizeof(SEC_WINNT_AUTH_IDENTITY_A) );
  256. if ( !pauthCopy )
  257. {
  258. return NULL;
  259. }
  260. //
  261. // copy subfields
  262. //
  263. // user
  264. pauthCopy->UserLength = pAuthIn->UserLength;
  265. if ( pAuthIn->UserLength )
  266. {
  267. ASSERT( pAuthIn->UserLength == strlen(pAuthIn->User) );
  268. pauthCopy->User = ALLOCATE_HEAP( (pAuthIn->UserLength + 1) * sizeof(CHAR) );
  269. if ( ! pauthCopy->User )
  270. {
  271. goto Failed;
  272. }
  273. strcpy( pauthCopy->User, pAuthIn->User );
  274. }
  275. // password
  276. // - must allow zero length password
  277. pauthCopy->PasswordLength = pAuthIn->PasswordLength;
  278. if ( pAuthIn->PasswordLength || pAuthIn->Password )
  279. {
  280. ASSERT( pAuthIn->PasswordLength == strlen(pAuthIn->Password) );
  281. pauthCopy->Password = ALLOCATE_HEAP( (pAuthIn->PasswordLength + 1) * sizeof(CHAR) );
  282. if ( ! pauthCopy->Password )
  283. {
  284. goto Failed;
  285. }
  286. strcpy( pauthCopy->Password, pAuthIn->Password );
  287. }
  288. // domain
  289. pauthCopy->DomainLength = pAuthIn->DomainLength;
  290. if ( pAuthIn->DomainLength )
  291. {
  292. ASSERT( pAuthIn->DomainLength == strlen(pAuthIn->Domain) );
  293. pauthCopy->Domain = ALLOCATE_HEAP( (pAuthIn->DomainLength + 1) * sizeof(CHAR) );
  294. if ( ! pauthCopy->Domain )
  295. {
  296. goto Failed;
  297. }
  298. strcpy( pauthCopy->Domain, pAuthIn->Domain );
  299. }
  300. pauthCopy->Flags = pAuthIn->Flags;
  301. DNSDBG( SECURITY, (
  302. "Exit Dns_AllocateAndInitializeCredentialsA()\n" ));
  303. return pauthCopy;
  304. Failed:
  305. // allocation failure
  306. // - cleanup what was allocated and get out
  307. Dns_FreeAuthIdentityCredentials( pauthCopy );
  308. return( NULL );
  309. }
  310. VOID
  311. Dns_FreeAuthIdentityCredentials(
  312. IN OUT PVOID pAuthIn
  313. )
  314. /*++
  315. Routine Description (Dns_FreeAuthIdentityCredentials):
  316. Free's structure given
  317. Arguments:
  318. pAuthIn -- in param to free
  319. Return Value:
  320. None
  321. --*/
  322. {
  323. register PSEC_WINNT_AUTH_IDENTITY_W pauthId;
  324. pauthId = (PSEC_WINNT_AUTH_IDENTITY_W) pAuthIn;
  325. if ( !pauthId )
  326. {
  327. return;
  328. }
  329. //
  330. // assuming _W and _A structs are equivalent except
  331. // for string types
  332. //
  333. ASSERT( sizeof( SEC_WINNT_AUTH_IDENTITY_W ) ==
  334. sizeof( SEC_WINNT_AUTH_IDENTITY_A ) );
  335. if ( pauthId->User )
  336. {
  337. FREE_HEAP ( pauthId->User );
  338. }
  339. if ( pauthId->Password )
  340. {
  341. FREE_HEAP ( pauthId->Password );
  342. }
  343. if ( pauthId->Domain )
  344. {
  345. FREE_HEAP ( pauthId->Domain );
  346. }
  347. FREE_HEAP ( pauthId );
  348. }
  349. PSEC_WINNT_AUTH_IDENTITY_W
  350. Dns_AllocateCredentials(
  351. IN PWSTR pwsUserName,
  352. IN PWSTR pwsDomain,
  353. IN PWSTR pwsPassword
  354. )
  355. /*++
  356. Description:
  357. Allocates auth identity info and initializes pAuthIn info
  358. Parameters:
  359. pwsUserName -- user name
  360. pwsDomain -- domain name
  361. pwsPassword -- password
  362. Return:
  363. Ptr to newly create credentials.
  364. NULL on failure.
  365. --*/
  366. {
  367. PSEC_WINNT_AUTH_IDENTITY_W pauth = NULL;
  368. DWORD length;
  369. PWSTR pstr;
  370. DNSDBG( SECURITY, (
  371. "Enter Dns_AllocateCredentials()\n"
  372. "\tuser = %S\n"
  373. "\tdomain = %S\n"
  374. "\tpassword = %S\n",
  375. pwsUserName,
  376. pwsDomain,
  377. pwsPassword ));
  378. //
  379. // allocate credentials struct
  380. // - zero for simple cleanup on subfield alloc failures
  381. //
  382. pauth = ALLOCATE_HEAP_ZERO( sizeof(SEC_WINNT_AUTH_IDENTITY_W) );
  383. if ( !pauth )
  384. {
  385. return NULL;
  386. }
  387. // copy user
  388. length = wcslen( pwsUserName );
  389. pstr = ALLOCATE_HEAP( (length + 1) * sizeof(WCHAR) );
  390. if ( ! pstr )
  391. {
  392. goto Failed;
  393. }
  394. wcscpy( pstr, pwsUserName );
  395. pauth->User = pstr;
  396. pauth->UserLength = length;
  397. // copy domain
  398. length = wcslen( pwsDomain );
  399. pstr = ALLOCATE_HEAP( (length + 1) * sizeof(WCHAR) );
  400. if ( ! pstr )
  401. {
  402. goto Failed;
  403. }
  404. wcscpy( pstr, pwsDomain );
  405. pauth->Domain = pstr;
  406. pauth->DomainLength = length;
  407. // copy password
  408. length = wcslen( pwsPassword );
  409. pstr = ALLOCATE_HEAP( (length + 1) * sizeof(WCHAR) );
  410. if ( ! pstr )
  411. {
  412. goto Failed;
  413. }
  414. wcscpy( pstr, pwsPassword );
  415. pauth->Password = pstr;
  416. pauth->PasswordLength = length;
  417. // set to unicode
  418. pauth->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  419. DNSDBG( SECURITY, (
  420. "Exit Dns_AllocateCredentialsW( %p )\n",
  421. pauth ));
  422. return pauth;
  423. Failed:
  424. // allocation failure
  425. // - cleanup what was allocated and get out
  426. Dns_FreeAuthIdentityCredentials( pauth );
  427. return( NULL );
  428. }
  429. //
  430. // DNS Credential utilities (unused)
  431. //
  432. DNS_STATUS
  433. Dns_ImpersonateUser(
  434. IN PDNS_CREDENTIALS pCreds
  435. )
  436. /*++
  437. Routine Description:
  438. Impersonate a user.
  439. Arguments:
  440. pCreds -- credentials of user to impersonate
  441. Return Value:
  442. ERROR_SUCCESS if successful
  443. Error code on failure.
  444. --*/
  445. {
  446. DNS_STATUS status = NO_ERROR;
  447. HANDLE htoken;
  448. //
  449. // attempt logon
  450. //
  451. if ( ! LogonUserW(
  452. pCreds->pUserName,
  453. pCreds->pDomain,
  454. pCreds->pPassword,
  455. LOGON32_LOGON_SERVICE,
  456. LOGON32_PROVIDER_WINNT50,
  457. &htoken ) )
  458. {
  459. status = GetLastError();
  460. if ( status == NO_ERROR )
  461. {
  462. status = ERROR_CANNOT_IMPERSONATE;
  463. DNS_ASSERT( FALSE );
  464. }
  465. DNSDBG( SECURITY, (
  466. "LogonUser() failed => %d\n"
  467. "\tuser = %S\n"
  468. "\tdomain = %S\n"
  469. "\tpassword = %S\n",
  470. status,
  471. pCreds->pUserName,
  472. pCreds->pDomain,
  473. pCreds->pPassword
  474. ));
  475. return status;
  476. }
  477. //
  478. // impersonate
  479. //
  480. if ( !ImpersonateLoggedOnUser( htoken ) )
  481. {
  482. status = GetLastError();
  483. if ( status == NO_ERROR )
  484. {
  485. status = ERROR_CANNOT_IMPERSONATE;
  486. DNS_ASSERT( FALSE );
  487. }
  488. DNSDBG( SECURITY, (
  489. "ImpersonateLoggedOnUser() failed = %d\n",
  490. status ));
  491. }
  492. CloseHandle( htoken );
  493. DNSDBG( SECURITY, (
  494. "%s\n"
  495. "\tuser = %S\n"
  496. "\tdomain = %S\n"
  497. "\tpassword = %S\n",
  498. (status == NO_ERROR)
  499. ? "Successfully IMPERSONATING!"
  500. : "Failed IMPERSONATION!",
  501. pCreds->pUserName,
  502. pCreds->pDomain,
  503. pCreds->pPassword ));
  504. return status;
  505. }
  506. VOID
  507. Dns_FreeCredentials(
  508. IN PDNS_CREDENTIALS pCreds
  509. )
  510. /*++
  511. Routine Description:
  512. Free DNS credentials.
  513. Arguments:
  514. pCreds -- credentials to free
  515. Return Value:
  516. None
  517. --*/
  518. {
  519. //
  520. // free subfields, then credentials
  521. //
  522. if ( !pCreds )
  523. {
  524. return;
  525. }
  526. if ( pCreds->pUserName )
  527. {
  528. FREE_HEAP( pCreds->pUserName );
  529. }
  530. if ( pCreds->pDomain )
  531. {
  532. FREE_HEAP( pCreds->pDomain );
  533. }
  534. if ( pCreds->pPassword )
  535. {
  536. FREE_HEAP( pCreds->pPassword );
  537. }
  538. FREE_HEAP( pCreds );
  539. }
  540. PDNS_CREDENTIALS
  541. Dns_CopyCredentials(
  542. IN PDNS_CREDENTIALS pCreds
  543. )
  544. /*++
  545. Routine Description:
  546. Create copy of DNS credentials.
  547. Arguments:
  548. pCreds -- credentials of user to copy
  549. Return Value:
  550. Ptr to allocated copy of credentials.
  551. --*/
  552. {
  553. PDNS_CREDENTIALS pnewCreds = NULL;
  554. PWSTR pfield;
  555. //
  556. // allocate credentials
  557. // - copy of subfields
  558. //
  559. pnewCreds = (PDNS_CREDENTIALS) ALLOCATE_HEAP_ZERO( sizeof(*pnewCreds) );
  560. if ( !pnewCreds )
  561. {
  562. return( NULL );
  563. }
  564. pfield = (PWSTR) Dns_CreateStringCopy_W( pCreds->pUserName );
  565. if ( !pfield )
  566. {
  567. goto Failed;
  568. }
  569. pnewCreds->pUserName = pfield;
  570. pfield = (PWSTR) Dns_CreateStringCopy_W( pCreds->pDomain );
  571. if ( !pfield )
  572. {
  573. goto Failed;
  574. }
  575. pnewCreds->pDomain = pfield;
  576. pfield = (PWSTR) Dns_CreateStringCopy_W( pCreds->pPassword );
  577. if ( !pfield )
  578. {
  579. goto Failed;
  580. }
  581. pnewCreds->pPassword = pfield;
  582. return( pnewCreds );
  583. Failed:
  584. Dns_FreeCredentials( pnewCreds );
  585. return( NULL );
  586. }
  587. //
  588. // End secutil.c
  589. //