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.

1203 lines
31 KiB

  1. /*
  2. File usrparms.c
  3. Callback routines exported to SAM for migrating and updating
  4. user parms.
  5. Paul Mayfield, 9/10/98
  6. */
  7. #include <nt.h>
  8. #include <ntrtl.h>
  9. #include <nturtl.h>
  10. #include <ntlsa.h>
  11. #include <ntsam.h>
  12. #include <samrpc.h>
  13. #include <samisrv.h>
  14. #include <windows.h>
  15. #include <lm.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <memory.h>
  19. #include <malloc.h>
  20. #include <raserror.h>
  21. #include <rasman.h>
  22. #include <rasppp.h>
  23. #include <mprapi.h>
  24. #include <mprapip.h>
  25. #include <usrparms.h> // for UP_CLIENT_DIAL
  26. #include <cleartxt.h> // for IASParmsGetUserPassword
  27. #include <rassfmhp.h> // for RasSfmHeap
  28. #include <oaidl.h>
  29. //
  30. // Flags that restrict the values generated for a given
  31. // set of ras user properties. See UPGenerateDsAttribs
  32. //
  33. #define UP_F_Dialin 0x1 // Generate dialup params
  34. #define UP_F_Callback 0x2 // Generate callback params
  35. #define UP_F_Upgrade 0x4 // Generate upgraded params
  36. //
  37. // Constants in the profiles
  38. //
  39. #define SDO_FRAMED 2
  40. #define SDO_FRAMED_CALLBACK 4
  41. // Names of user attributes that we set
  42. //
  43. static const WCHAR pszAttrDialin[] = L"msNPAllowDialin";
  44. static const WCHAR pszAttrServiceType[] = L"msRADIUSServiceType";
  45. static const WCHAR pszAttrCbNumber[] = L"msRADIUSCallbackNumber";
  46. static const WCHAR pszAttrSavedCbNumber[] = L"msRASSavedCallbackNumber";
  47. //
  48. // Will be equal to the number of times the common allocation
  49. // routine is called minus the number of times the common free
  50. // routine is called. Should be zero else leaking memory.
  51. //
  52. DWORD dwUpLeakCount = 0;
  53. //
  54. // Prototype of free func.
  55. //
  56. VOID WINAPI
  57. UserParmsFree(
  58. IN PVOID pvData);
  59. //
  60. // Common tracing for the UserParm functions.
  61. //
  62. DWORD UpTrace (LPSTR pszTrace, ...) {
  63. #if 0
  64. va_list arglist;
  65. char szBuffer[1024], szTemp[1024];
  66. va_start(arglist, pszTrace);
  67. vsprintf(szTemp, pszTrace, arglist);
  68. va_end(arglist);
  69. sprintf(szBuffer, "UserParms: %s\n", szTemp);
  70. OutputDebugStringA(szBuffer);
  71. #endif
  72. return NO_ERROR;
  73. }
  74. //
  75. // Allocation and free routines for UserParms functions
  76. //
  77. PVOID
  78. UpAlloc(
  79. IN DWORD dwSize,
  80. IN BOOL bZero)
  81. {
  82. dwUpLeakCount++;
  83. return RtlAllocateHeap(
  84. RasSfmHeap(),
  85. (bZero ? HEAP_ZERO_MEMORY : 0),
  86. dwSize
  87. );
  88. }
  89. //
  90. // Callback function called by NT5 SAM to free the blob
  91. // returned by UserParmsConvert.
  92. //
  93. VOID
  94. UpFree(
  95. IN PVOID pvData)
  96. {
  97. dwUpLeakCount--;
  98. if (pvData)
  99. RtlFreeHeap(
  100. RasSfmHeap(),
  101. 0,
  102. pvData
  103. );
  104. }
  105. //
  106. // Returns a heap-allocated copy of the given
  107. // string
  108. //
  109. PWCHAR
  110. UpStrDup(
  111. IN PCWSTR pszSrc)
  112. {
  113. PWCHAR pszRet = NULL;
  114. DWORD dwLen = wcslen(pszSrc);
  115. pszRet = (PWCHAR) UpAlloc((dwLen + 1) * sizeof(WCHAR), FALSE);
  116. if (pszRet)
  117. wcscpy(pszRet, pszSrc);
  118. return pszRet;
  119. }
  120. //
  121. // Returns a heap-allocated copy of the given unicode
  122. // string converted into multibyte.
  123. //
  124. PUCHAR
  125. UpWcstombsDup(
  126. IN PWCHAR pszSrc)
  127. {
  128. PUCHAR pszRet = NULL;
  129. DWORD dwSize = (wcslen(pszSrc) + 1) * sizeof(WCHAR);
  130. pszRet = (PUCHAR) UpAlloc(dwSize, TRUE);
  131. if (pszRet)
  132. wcstombs(pszRet, pszSrc, dwSize);
  133. return pszRet;
  134. }
  135. //
  136. // Returns a heap-allocated copy of the given
  137. // blob
  138. //
  139. PVOID
  140. UpBlobDup(
  141. IN PVOID pvSrc,
  142. IN ULONG ulLen)
  143. {
  144. PVOID pvRet = NULL;
  145. if (ulLen == 0)
  146. return NULL;
  147. pvRet = UpAlloc(ulLen + sizeof(WCHAR), TRUE);
  148. if (pvRet)
  149. {
  150. CopyMemory(pvRet, pvSrc, ulLen);
  151. }
  152. else
  153. {
  154. UpTrace("UpBlobDup: Failed to dupe %x %d.", pvSrc, ulLen);
  155. }
  156. return pvRet;
  157. }
  158. //
  159. // Allocates and initializes a dword attribute
  160. //
  161. NTSTATUS
  162. UpInitializeDwordAttr(
  163. IN SAM_USERPARMS_ATTR * pAttr,
  164. IN PWCHAR pszAttr,
  165. IN DWORD dwVal)
  166. {
  167. if (pszAttr == NULL)
  168. {
  169. return STATUS_NO_MEMORY;
  170. }
  171. // Initialize the name
  172. RtlInitUnicodeString (&(pAttr->AttributeIdentifier), pszAttr);
  173. pAttr->Syntax = Syntax_Attribute;
  174. // Alloc/Initailze the value structure
  175. pAttr->Values =
  176. (SAM_USERPARMS_ATTRVALS*)
  177. UpAlloc(sizeof(SAM_USERPARMS_ATTRVALS), TRUE);
  178. if (pAttr->Values == NULL)
  179. return STATUS_NO_MEMORY;
  180. // Alloc/Init the value
  181. pAttr->Values->value = UpAlloc(sizeof(DWORD), TRUE);
  182. if (pAttr->Values->value == NULL)
  183. return STATUS_NO_MEMORY;
  184. *((DWORD*)pAttr->Values->value) = dwVal;
  185. pAttr->Values->length = sizeof(DWORD);
  186. // Put in the value count
  187. pAttr->CountOfValues = 1;
  188. return STATUS_SUCCESS;
  189. }
  190. //
  191. // Allocates and initializes a dword attribute
  192. //
  193. NTSTATUS
  194. UpInitializeStringAttrA(
  195. OUT SAM_USERPARMS_ATTR * pAttr,
  196. IN PWCHAR pszAttr,
  197. IN PUCHAR pszVal)
  198. {
  199. if (pszAttr == NULL)
  200. {
  201. return STATUS_NO_MEMORY;
  202. }
  203. // Initialize the name
  204. RtlInitUnicodeString (&(pAttr->AttributeIdentifier), pszAttr);
  205. pAttr->Syntax = Syntax_Attribute;
  206. // Alloc/Initailze the value structure
  207. pAttr->Values =
  208. (SAM_USERPARMS_ATTRVALS*)
  209. UpAlloc(sizeof(SAM_USERPARMS_ATTRVALS), TRUE);
  210. if (pAttr->Values == NULL)
  211. return STATUS_NO_MEMORY;
  212. // Alloc/Init the value
  213. pAttr->Values->value = pszVal;
  214. if (pszVal)
  215. {
  216. pAttr->Values->length = (strlen(pszVal) + 1) * sizeof(CHAR);
  217. }
  218. else
  219. {
  220. pAttr->Values->length = 1 * sizeof(CHAR);
  221. }
  222. // Put in the value count
  223. pAttr->CountOfValues = 1;
  224. return STATUS_SUCCESS;
  225. }
  226. //
  227. // Allocates and initializes a cleartext password attribute
  228. //
  229. NTSTATUS
  230. UpInitializePasswordAttr(
  231. OUT SAM_USERPARMS_ATTR * pAttr,
  232. IN PWSTR pszPassword)
  233. {
  234. // Alloc/Initialize the value structure
  235. pAttr->Values =
  236. (SAM_USERPARMS_ATTRVALS*)
  237. UpAlloc(sizeof(SAM_USERPARMS_ATTRVALS), TRUE);
  238. if (pAttr->Values == NULL)
  239. return STATUS_NO_MEMORY;
  240. // Alloc/Init the value
  241. pAttr->Values->value = pszPassword;
  242. pAttr->Values->length = (wcslen(pszPassword) + 1) * sizeof(WCHAR);
  243. // Put in the value count
  244. pAttr->CountOfValues = 1;
  245. // Initialize the name and syntax.
  246. RtlInitUnicodeString(
  247. &pAttr->AttributeIdentifier,
  248. UpStrDup(L"CLEARTEXT")
  249. );
  250. pAttr->Syntax = Syntax_EncryptedAttribute;
  251. return STATUS_SUCCESS;
  252. }
  253. //
  254. // Allocates and initializes an attribute
  255. // to be deleted.
  256. //
  257. NTSTATUS
  258. UpInitializeDeletedAttr(
  259. OUT SAM_USERPARMS_ATTR * pAttr,
  260. IN PWCHAR pszAttr)
  261. {
  262. if (pszAttr == NULL)
  263. {
  264. return STATUS_NO_MEMORY;
  265. }
  266. // Initialize the name
  267. RtlInitUnicodeString (&(pAttr->AttributeIdentifier), pszAttr);
  268. pAttr->Syntax = Syntax_Attribute;
  269. // Value count of zero means delete
  270. //
  271. pAttr->CountOfValues = 0;
  272. return STATUS_SUCCESS;
  273. }
  274. //
  275. // Converts the given user parms blob into a set of
  276. // ras attributes
  277. //
  278. NTSTATUS
  279. UpUserParmsToRasUser0 (
  280. IN PVOID pvUserParms,
  281. OUT RAS_USER_0 * pRasUser0)
  282. {
  283. DWORD dwErr;
  284. // Initalize
  285. ZeroMemory(pRasUser0, sizeof(RAS_USER_0));
  286. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  287. pRasUser0->wszPhoneNumber[0] = UNICODE_NULL;
  288. // The the user parms are null, the defaults
  289. // will do.
  290. if (pvUserParms == NULL)
  291. {
  292. return STATUS_SUCCESS;
  293. }
  294. // Truncate user parms at sizeof USER_PARMS
  295. if (lstrlenW((PWCHAR)pvUserParms) >= sizeof(USER_PARMS))
  296. {
  297. // We slam in a null at sizeof(USER_PARMS)-1 which
  298. // corresponds to user_parms.up_Null
  299. ((PWCHAR)pvUserParms)[sizeof(USER_PARMS)-1] = L'\0';
  300. }
  301. // Get RAS info (and validate) from usr_parms
  302. dwErr = MprGetUsrParams(
  303. UP_CLIENT_DIAL,
  304. (LPWSTR) pvUserParms,
  305. (LPWSTR) pRasUser0);
  306. if (dwErr == NO_ERROR)
  307. {
  308. // Get RAS Privilege and callback number
  309. RasPrivilegeAndCallBackNumber(FALSE, pRasUser0);
  310. }
  311. return STATUS_SUCCESS;
  312. }
  313. /////////
  314. // Signature of the extraction function.
  315. /////////
  316. typedef HRESULT (WINAPI *IASPARMSQUERYUSERPROPERTY)(
  317. IN PCWSTR pszUserParms,
  318. IN PCWSTR pszName,
  319. OUT VARIANT *pvarValue
  320. );
  321. //////////
  322. // Uplevel per-user attributes that will be migrated.
  323. //////////
  324. CONST PCWSTR UPLEVEL_PARMS[] =
  325. {
  326. L"msNPAllowDialin",
  327. L"msNPCallingStationID",
  328. L"msRADIUSCallbackNumber",
  329. L"msRADIUSFramedIPAddress",
  330. L"msRADIUSFramedRoute",
  331. L"msRADIUSServiceType"
  332. };
  333. //////////
  334. // Number of per-user attributes.
  335. //////////
  336. #define NUM_UPLEVEL_PARMS (sizeof(UPLEVEL_PARMS)/sizeof(UPLEVEL_PARMS[0]))
  337. /////////
  338. // Converts a ULONG into a SAM_USERPARMS_ATTRVALS struct.
  339. /////////
  340. NTSTATUS
  341. NTAPI
  342. ConvertULongToAttrVal(
  343. IN ULONG ulValue,
  344. OUT PSAM_USERPARMS_ATTRVALS pAttrVal
  345. )
  346. {
  347. // Allocate memory to hold the ULONG.
  348. pAttrVal->value = UpAlloc(sizeof(ULONG), FALSE);
  349. if (pAttrVal->value == NULL) { return STATUS_NO_MEMORY; }
  350. // Copy in the value.
  351. *(PULONG)pAttrVal->value = ulValue;
  352. // Set the length.
  353. pAttrVal->length = sizeof(ULONG);
  354. return STATUS_SUCCESS;
  355. }
  356. //////////
  357. // Converts a single-valued VARIANT into a SAM_USERPARMS_ATTRVALS struct.
  358. //////////
  359. NTSTATUS
  360. NTAPI
  361. ConvertVariantToAttrVal(
  362. IN CONST VARIANT *pvarValue,
  363. OUT PSAM_USERPARMS_ATTRVALS pAttrVal
  364. )
  365. {
  366. NTSTATUS status;
  367. ULONG length;
  368. UNICODE_STRING wide;
  369. ANSI_STRING ansi;
  370. switch (V_VT(pvarValue))
  371. {
  372. case VT_EMPTY:
  373. {
  374. // VT_EMPTY means the attribute was deleted.
  375. pAttrVal->value = NULL;
  376. pAttrVal->length = 0;
  377. return STATUS_SUCCESS;
  378. }
  379. case VT_I2:
  380. return ConvertULongToAttrVal(V_I2(pvarValue), pAttrVal);
  381. case VT_I4:
  382. return ConvertULongToAttrVal(V_I4(pvarValue), pAttrVal);
  383. case VT_BSTR:
  384. {
  385. // Check the BSTR.
  386. if (V_BSTR(pvarValue) == NULL) { return STATUS_INVALID_PARAMETER; }
  387. // Initialize the source string.
  388. RtlInitUnicodeString(&wide, V_BSTR(pvarValue));
  389. // Initialize the destination buffer.
  390. ansi.Length = 0;
  391. ansi.MaximumLength = wide.MaximumLength / sizeof(WCHAR);
  392. ansi.Buffer = UpAlloc(ansi.MaximumLength, FALSE);
  393. if (ansi.Buffer == NULL) { return STATUS_NO_MEMORY; }
  394. // Convert from wide to ansi.
  395. status = RtlUnicodeStringToAnsiString(&ansi, &wide, FALSE);
  396. if (!NT_SUCCESS(status))
  397. {
  398. UpFree(ansi.Buffer);
  399. return status;
  400. }
  401. // Store the result.
  402. pAttrVal->value = ansi.Buffer;
  403. pAttrVal->length = ansi.Length + 1;
  404. return STATUS_SUCCESS;
  405. }
  406. case VT_BOOL:
  407. return ConvertULongToAttrVal((V_BOOL(pvarValue) ? 1 : 0), pAttrVal);
  408. case VT_I1:
  409. return ConvertULongToAttrVal(V_I1(pvarValue), pAttrVal);
  410. case VT_UI1:
  411. return ConvertULongToAttrVal(V_UI1(pvarValue), pAttrVal);
  412. case VT_UI2:
  413. return ConvertULongToAttrVal(V_UI2(pvarValue), pAttrVal);
  414. case VT_UI4:
  415. return ConvertULongToAttrVal(V_UI4(pvarValue), pAttrVal);
  416. case VT_ARRAY | VT_I1:
  417. case VT_ARRAY | VT_UI1:
  418. {
  419. // Check the SAFEARRAY.
  420. if (V_ARRAY(pvarValue) == NULL) { return STATUS_INVALID_PARAMETER; }
  421. // Allocate memory for the octet string.
  422. length = V_ARRAY(pvarValue)->rgsabound[0].cElements;
  423. pAttrVal->value = UpAlloc(length, FALSE);
  424. if (pAttrVal->value == NULL) { return STATUS_NO_MEMORY; }
  425. // Copy in the data.
  426. memcpy(pAttrVal->value, V_ARRAY(pvarValue)->pvData, length);
  427. // Set the length.
  428. pAttrVal->length = length;
  429. return STATUS_SUCCESS;
  430. }
  431. }
  432. // If we made it here it was an unsupported VARTYPE.
  433. return STATUS_INVALID_PARAMETER;
  434. }
  435. //////////
  436. // Frees the values array of a SAM_USERPARMS_ATTR struct.
  437. //////////
  438. VOID
  439. NTAPI
  440. FreeUserParmsAttrValues(
  441. IN PSAM_USERPARMS_ATTR pAttrs
  442. )
  443. {
  444. ULONG i;
  445. if (pAttrs)
  446. {
  447. for (i = 0; i < pAttrs->CountOfValues; ++i)
  448. {
  449. UpFree(pAttrs->Values[i].value);
  450. }
  451. UpFree(pAttrs->Values);
  452. }
  453. }
  454. //////////
  455. // Converts a VARIANT into a SAM_USERPARMS_ATTR struct.
  456. //////////
  457. NTSTATUS
  458. NTAPI
  459. ConvertVariantToUserParmsAttr(
  460. IN CONST VARIANT *pvarSrc,
  461. OUT PSAM_USERPARMS_ATTR pAttrs
  462. )
  463. {
  464. NTSTATUS status;
  465. ULONG nelem;
  466. CONST VARIANT *srcVal;
  467. SAM_USERPARMS_ATTRVALS *dstVal;
  468. // Get the array of values to be converted.
  469. if (V_VT(pvarSrc) != (VT_VARIANT | VT_ARRAY))
  470. {
  471. nelem = 1;
  472. srcVal = pvarSrc;
  473. }
  474. else
  475. {
  476. nelem = V_ARRAY(pvarSrc)->rgsabound[0].cElements;
  477. srcVal = (CONST VARIANT *)V_ARRAY(pvarSrc)->pvData;
  478. }
  479. // Initialize CountOfValues to zero. We'll use this to track how many
  480. // values have been successfully converted.
  481. pAttrs->CountOfValues = 0;
  482. // Allocate memory to hold the values.
  483. pAttrs->Values = UpAlloc(sizeof(SAM_USERPARMS_ATTRVALS) * nelem, TRUE);
  484. if (pAttrs->Values == NULL) { return STATUS_NO_MEMORY; }
  485. // Loop through each value to be converted.
  486. for (dstVal = pAttrs->Values; nelem > 0; ++srcVal, ++dstVal, --nelem)
  487. {
  488. status = ConvertVariantToAttrVal(srcVal, dstVal);
  489. if (!NT_SUCCESS(status))
  490. {
  491. // Clean-up the partial results.
  492. FreeUserParmsAttrValues(pAttrs);
  493. return status;
  494. }
  495. ++(pAttrs->CountOfValues);
  496. }
  497. return STATUS_SUCCESS;
  498. }
  499. //////////
  500. // Extracts the NT5 per-user attributes from a SAM UserParameters string and
  501. // converts them to a SAM_USERPARMS_ATTRBLOCK struct.
  502. //////////
  503. NTSTATUS
  504. NTAPI
  505. ConvertUserParmsToAttrBlock(
  506. IN PCWSTR lpUserParms,
  507. OUT PSAM_USERPARMS_ATTRBLOCK *ppAttrs
  508. )
  509. {
  510. static IASPARMSQUERYUSERPROPERTY IASParmsQueryUserProperty;
  511. NTSTATUS status;
  512. PSAM_USERPARMS_ATTR dst;
  513. PWSTR szPassword;
  514. ULONG i;
  515. HRESULT hr;
  516. VARIANT src;
  517. //////////
  518. // Make sure we have the extraction function loaded.
  519. //////////
  520. if (IASParmsQueryUserProperty == NULL)
  521. {
  522. IASParmsQueryUserProperty = (IASPARMSQUERYUSERPROPERTY)
  523. GetProcAddress(
  524. LoadLibraryW(
  525. L"IASSAM.DLL"
  526. ),
  527. "IASParmsQueryUserProperty"
  528. );
  529. if (!IASParmsQueryUserProperty) { return STATUS_PROCEDURE_NOT_FOUND; }
  530. }
  531. //////////
  532. // Allocate memory for the SAM_USERPARMS_ATTRBLOCK.
  533. //////////
  534. *ppAttrs = (PSAM_USERPARMS_ATTRBLOCK)
  535. UpAlloc(
  536. sizeof(SAM_USERPARMS_ATTRBLOCK),
  537. TRUE
  538. );
  539. if (*ppAttrs == NULL)
  540. {
  541. return STATUS_NO_MEMORY;
  542. }
  543. (*ppAttrs)->UserParmsAttr = (PSAM_USERPARMS_ATTR)
  544. UpAlloc(
  545. sizeof(SAM_USERPARMS_ATTR) *
  546. (NUM_UPLEVEL_PARMS + 1),
  547. TRUE
  548. );
  549. if ((*ppAttrs)->UserParmsAttr == NULL)
  550. {
  551. UpFree(*ppAttrs);
  552. return STATUS_NO_MEMORY;
  553. }
  554. //////////
  555. // Convert the cleartext password.
  556. //////////
  557. dst = (*ppAttrs)->UserParmsAttr;
  558. szPassword = NULL;
  559. IASParmsGetUserPassword(
  560. lpUserParms,
  561. &szPassword
  562. );
  563. if (szPassword)
  564. {
  565. status = UpInitializePasswordAttr(
  566. dst,
  567. UpStrDup(szPassword)
  568. );
  569. LocalFree(szPassword);
  570. if (NT_SUCCESS(status))
  571. {
  572. ++dst;
  573. }
  574. }
  575. //////////
  576. // Convert the dial-in parameters.
  577. //////////
  578. for (i = 0; i < NUM_UPLEVEL_PARMS; ++i)
  579. {
  580. // Try to extract the parameter from UserParms.
  581. hr = IASParmsQueryUserProperty(
  582. lpUserParms,
  583. UPLEVEL_PARMS[i],
  584. &src
  585. );
  586. if (FAILED(hr) || V_VT(&src) == VT_EMPTY) { continue; }
  587. // Convert to a SAM_USERPARMS_ATTRVALS array.
  588. status = ConvertVariantToUserParmsAttr(
  589. &src,
  590. dst
  591. );
  592. if (NT_SUCCESS(status))
  593. {
  594. // Fill in the AttributeIdentifier ...
  595. RtlInitUnicodeString(
  596. &dst->AttributeIdentifier,
  597. UpStrDup(UPLEVEL_PARMS[i])
  598. );
  599. // ... and the Syntax.
  600. dst->Syntax = Syntax_Attribute;
  601. // All went well, so advance to the next element in the array.
  602. ++dst;
  603. }
  604. // We're done with the VARIANT.
  605. VariantClear(&src);
  606. }
  607. (*ppAttrs)->attCount = (ULONG)(dst - (*ppAttrs)->UserParmsAttr);
  608. // If there weren't any attributes, then free the UserParmsAttr array.
  609. if ((*ppAttrs)->attCount == 0)
  610. {
  611. UpFree((*ppAttrs)->UserParmsAttr);
  612. (*ppAttrs)->UserParmsAttr = NULL;
  613. }
  614. return status;
  615. }
  616. //
  617. // Generate an appropriate set of ds attributes based on the
  618. // ras user information provided
  619. //
  620. NTSTATUS
  621. UpGenerateDsAttribs (
  622. IN DWORD dwFlags,
  623. IN RAS_USER_0 * pRasUser0,
  624. IN PWSTR szPassword,
  625. OUT PSAM_USERPARMS_ATTRBLOCK * ppAttrs)
  626. {
  627. PSAM_USERPARMS_ATTRBLOCK pRet = NULL;
  628. SAM_USERPARMS_ATTR * pCurAttr = NULL;
  629. PWCHAR pszDupPassword, pszCurAttr = NULL;
  630. DWORD dwCurVal = 0, dwDsParamCount;
  631. NTSTATUS ntStatus = STATUS_SUCCESS;
  632. UpTrace("UpGenerateDsAttribs: enter %x", dwFlags);
  633. do
  634. {
  635. // pmay: 330184
  636. //
  637. // If we're upgrading, then having NULL userparms or having
  638. // deny set explicitly should cause us to not add the msNPAllowDialin
  639. // value so that user will be managed by policy.
  640. //
  641. if (
  642. (dwFlags & UP_F_Upgrade) &&
  643. (!(pRasUser0->bfPrivilege & RASPRIV_DialinPrivilege))
  644. )
  645. {
  646. dwFlags &= ~UP_F_Dialin;
  647. }
  648. // Initialize the return value
  649. pRet = (PSAM_USERPARMS_ATTRBLOCK)
  650. UpAlloc(sizeof(SAM_USERPARMS_ATTRBLOCK), TRUE);
  651. if (pRet == NULL)
  652. {
  653. UpTrace("UpGenerateDsAttribs: alloc block failed");
  654. ntStatus = STATUS_NO_MEMORY;
  655. break;
  656. }
  657. // Calculate the total number of values
  658. dwDsParamCount = 0;
  659. if (dwFlags & UP_F_Dialin)
  660. {
  661. dwDsParamCount += 1;
  662. }
  663. if (dwFlags & UP_F_Callback)
  664. {
  665. dwDsParamCount += 3;
  666. }
  667. if (szPassword != NULL)
  668. {
  669. dwDsParamCount += 1;
  670. }
  671. //
  672. // Set the array to be big enough to accomodate 4 attributes:
  673. // 1. Dialin bit
  674. // 2. Callback Number or Saved Callback Number
  675. // 3. Deleted version of #2
  676. // 4. Service Type (for callback policy)
  677. //
  678. pCurAttr = (SAM_USERPARMS_ATTR*)
  679. UpAlloc(sizeof(SAM_USERPARMS_ATTR) * dwDsParamCount, TRUE);
  680. if (pCurAttr == NULL)
  681. {
  682. ntStatus = STATUS_NO_MEMORY;
  683. UpTrace("UpGenerateDsAttribs: alloc of %d values failed",
  684. dwDsParamCount);
  685. break;
  686. }
  687. pRet->attCount = dwDsParamCount;
  688. pRet->UserParmsAttr = pCurAttr;
  689. // Set any appropriate dialin parameters
  690. //
  691. if (dwFlags & UP_F_Dialin)
  692. {
  693. dwCurVal =
  694. (pRasUser0->bfPrivilege & RASPRIV_DialinPrivilege) ? 1 : 0;
  695. // Initialize the dialin setting
  696. ntStatus = UpInitializeDwordAttr(
  697. pCurAttr,
  698. UpStrDup((PWCHAR)pszAttrDialin),
  699. dwCurVal);
  700. if (ntStatus != STATUS_SUCCESS)
  701. {
  702. UpTrace("UpGenerateDsAttribs: fail dialin val %x", ntStatus);
  703. break;
  704. }
  705. pCurAttr++;
  706. }
  707. // Set any appropriate callback parameters
  708. //
  709. if (dwFlags & UP_F_Callback)
  710. {
  711. // The following logic was modified for SP1 of Win2K. The reason is that
  712. // the values being set did not conform to the rules outlined in the
  713. // comments to the UserParmsConvert function.
  714. //
  715. // Namely,
  716. // 1. the msRADIUSServiceType was being set to SDO_FRAMED instead of
  717. // <empty> when RASPRIV_NoCallback was set.
  718. //
  719. // 2. When RASPRIV_NoCallback was set, the msRADIUSCallbackNumber was
  720. // set and the msRASSavedCallbackNumber was deleted instead of the
  721. // vice-versa
  722. //
  723. // Initialize the service type
  724. if (pRasUser0->bfPrivilege & RASPRIV_NoCallback)
  725. {
  726. ntStatus = UpInitializeDeletedAttr(
  727. pCurAttr,
  728. UpStrDup((PWCHAR)pszAttrServiceType));
  729. }
  730. else
  731. {
  732. ntStatus = UpInitializeDwordAttr(
  733. pCurAttr,
  734. UpStrDup((PWCHAR)pszAttrServiceType),
  735. SDO_FRAMED_CALLBACK);
  736. }
  737. if (ntStatus != STATUS_SUCCESS)
  738. {
  739. UpTrace("UpGenerateDsAttribs: fail ST val %x", ntStatus);
  740. break;
  741. }
  742. pCurAttr++;
  743. // Initialize the callback number that will be committed
  744. pszCurAttr = (pRasUser0->bfPrivilege & RASPRIV_AdminSetCallback) ?
  745. (PWCHAR) pszAttrCbNumber :
  746. (PWCHAR) pszAttrSavedCbNumber;
  747. if (*(pRasUser0->wszPhoneNumber))
  748. {
  749. ntStatus = UpInitializeStringAttrA(
  750. pCurAttr,
  751. UpStrDup(pszCurAttr),
  752. UpWcstombsDup(pRasUser0->wszPhoneNumber));
  753. if (ntStatus != STATUS_SUCCESS)
  754. {
  755. UpTrace("UpGenerateDsAttribs: fail CB val %x", ntStatus);
  756. break;
  757. }
  758. }
  759. else
  760. {
  761. ntStatus = UpInitializeDeletedAttr(
  762. pCurAttr,
  763. UpStrDup(pszCurAttr));
  764. if (ntStatus != STATUS_SUCCESS)
  765. {
  766. UpTrace("UpGenerateDsAttribs: fail del CB val %x", ntStatus);
  767. break;
  768. }
  769. }
  770. pCurAttr++;
  771. // Remove the callback number that doesn't apply.
  772. pszCurAttr = (pszCurAttr == pszAttrCbNumber) ?
  773. (PWCHAR) pszAttrSavedCbNumber :
  774. (PWCHAR) pszAttrCbNumber;
  775. ntStatus = UpInitializeDeletedAttr(
  776. pCurAttr,
  777. UpStrDup(pszCurAttr));
  778. if (ntStatus != STATUS_SUCCESS)
  779. {
  780. UpTrace("UpGenerateDsAttribs: fail del SCB val %x", ntStatus);
  781. break;
  782. }
  783. pCurAttr++;
  784. }
  785. // Set the cleartext password if present
  786. //
  787. if (szPassword != NULL)
  788. {
  789. // Make a duplicate copy of the password
  790. if ((pszDupPassword = UpStrDup(szPassword)) == NULL)
  791. {
  792. ntStatus = STATUS_NO_MEMORY;
  793. break;
  794. }
  795. // Initialize the password attribute
  796. ntStatus = UpInitializePasswordAttr(
  797. pCurAttr,
  798. pszDupPassword);
  799. if (ntStatus != STATUS_SUCCESS)
  800. {
  801. UpTrace("UpGenerateDsAttribs: fail password val %x", ntStatus);
  802. break;
  803. }
  804. pCurAttr++;
  805. }
  806. } while (FALSE);
  807. // Cleanup
  808. {
  809. if (ntStatus != STATUS_SUCCESS)
  810. {
  811. UserParmsFree(pRet);
  812. *ppAttrs = NULL;
  813. }
  814. else
  815. {
  816. *ppAttrs = pRet;
  817. }
  818. }
  819. return ntStatus;
  820. }
  821. //
  822. // Callback function called by NT5 SAM whenever the user parms
  823. // of a particular user are modified. The job of this callout
  824. // is to take the new value of user parms and generate a set of
  825. // domain attributes that need to be set for the given user so
  826. // that per-user DS attributes and userparms are kept in sync.
  827. //
  828. // This callout will be invoked during dcpromo to upgrade user parms
  829. // and whenever userparms is modified (by downlevel api's and apps).
  830. //
  831. // Callback functions for NT5 SAM are registered in the following
  832. // registry key:
  833. //
  834. // HKLM\SYS\CCS\Control\LSA\NotificationPackages
  835. //
  836. // The following are the rules of the RAS LDAP parameters:
  837. //
  838. // msNPAllowDialin
  839. // - Empty = Use policy to determine dialin privilege
  840. // - 1 = Allow dialin
  841. // - 2 = Deny dialin
  842. //
  843. // msRADIUSServiceType
  844. // - Empty = NoCallback policy
  845. // - 4 = CallerCallback if msRADIUSCallbackNumber is empty
  846. // AdminCallback if msRADIUSCallbackNumber is not empty
  847. //
  848. // msRADIUSCallbackNumber
  849. // - Determines the callback policy depending on msRADIUSServiceType
  850. //
  851. // msRASSavedCallbackNumber
  852. // - Used to store the last known value of msRADIUSCallbackNumber when
  853. // switching from AdminCallback policy to some other policy.
  854. //
  855. NTSTATUS
  856. UserParmsConvert (
  857. IN ULONG ulFlags,
  858. IN PSID pDomainSid,
  859. IN ULONG ulObjectRid,
  860. IN ULONG ulOrigLen,
  861. IN PVOID pvOrigUserParms,
  862. IN ULONG ulNewLen,
  863. IN PVOID pvNewUserParms,
  864. OUT PSAM_USERPARMS_ATTRBLOCK * ppAttrs)
  865. {
  866. RAS_USER_0 RasUser00, *pOrigUser = &RasUser00;
  867. RAS_USER_0 RasUser01, *pNewUser = &RasUser01;
  868. NTSTATUS ntStatus = STATUS_SUCCESS;
  869. PVOID pvOrig = NULL, pvNew = NULL;
  870. DWORD dwFlags = 0, dwMask;
  871. PWSTR szPassword = NULL;
  872. UpTrace(
  873. "UPConvert: F=%x, Rid=%x, OLen=%d, OPar=%x, NLen=%d, NPar=%x",
  874. ulFlags, ulObjectRid, ulOrigLen, pvOrigUserParms,
  875. ulNewLen, pvNewUserParms);
  876. // Validate parameters
  877. if (ppAttrs == NULL)
  878. return STATUS_INVALID_PARAMETER;
  879. // Initialize the return value;
  880. *ppAttrs = NULL;
  881. // If the user parms passed to us are NULL,
  882. // then keep defaults.
  883. if ((pvNewUserParms == NULL) || (ulNewLen == 0))
  884. {
  885. return STATUS_SUCCESS;
  886. }
  887. do
  888. {
  889. // Allocate and initialize local copies of
  890. // the user parms
  891. pvOrig = UpBlobDup(pvOrigUserParms, ulOrigLen);
  892. pvNew = UpBlobDup(pvNewUserParms, ulNewLen);
  893. // If this is a NT5 standalone being promoted to a DC, then we
  894. // just convert the uplevel userparms 'as is'.
  895. if ((ulFlags & SAM_USERPARMS_DURING_UPGRADE) &&
  896. !SamINT4UpgradeInProgress())
  897. {
  898. ntStatus = ConvertUserParmsToAttrBlock(pvNew, ppAttrs);
  899. break;
  900. }
  901. // Get the new ras properties
  902. ntStatus = UpUserParmsToRasUser0(
  903. pvNew,
  904. pNewUser);
  905. if (ntStatus != STATUS_SUCCESS)
  906. {
  907. UpTrace("UPConvert: Conversion to RAS_USER_0 failed.(1)");
  908. break;
  909. }
  910. // If we're upgrading, then we should blindly
  911. // set whatever information is stored in the user.
  912. if (ulFlags & SAM_USERPARMS_DURING_UPGRADE)
  913. {
  914. IASParmsGetUserPassword(pvNewUserParms, &szPassword);
  915. ntStatus = UpGenerateDsAttribs(
  916. UP_F_Dialin | UP_F_Callback | UP_F_Upgrade,
  917. pNewUser,
  918. szPassword,
  919. ppAttrs);
  920. LocalFree(szPassword);
  921. if (ntStatus != STATUS_SUCCESS)
  922. {
  923. UpTrace("UPConvert: GenerateDsAttribs failed %x", ntStatus);
  924. }
  925. break;
  926. }
  927. // Get the ras properties of the old user parms
  928. ntStatus = UpUserParmsToRasUser0(
  929. pvOrig,
  930. pOrigUser);
  931. if (ntStatus != STATUS_SUCCESS)
  932. {
  933. UpTrace("UPConvert: Conversion to RAS_USER_0 failed.(2)");
  934. break;
  935. }
  936. // Find out if the dialin privilege should be updated
  937. dwFlags = 0;
  938. if (!!(pOrigUser->bfPrivilege & RASPRIV_DialinPrivilege) !=
  939. !!(pNewUser->bfPrivilege & RASPRIV_DialinPrivilege))
  940. {
  941. dwFlags |= UP_F_Dialin;
  942. }
  943. // pmay: 264409
  944. //
  945. // If we are adding null usrparms for the first time,
  946. // go ahead and add the dialin bit value to the ds.
  947. //
  948. if ((pvOrig == NULL) && (pvNew != NULL))
  949. {
  950. dwFlags |= UP_F_Dialin;
  951. }
  952. // Findout if any callback info should be updated
  953. dwMask = RASPRIV_NoCallback |
  954. RASPRIV_CallerSetCallback |
  955. RASPRIV_AdminSetCallback;
  956. if (((pOrigUser->bfPrivilege & dwMask) !=
  957. (pNewUser->bfPrivilege & dwMask)) ||
  958. (wcscmp(pOrigUser->wszPhoneNumber, pNewUser->wszPhoneNumber) != 0)
  959. )
  960. {
  961. dwFlags |= UP_F_Callback;
  962. }
  963. // If there were no changes, we're done.
  964. if (dwFlags == 0)
  965. {
  966. UpTrace("UPConvert: nothing to update.");
  967. ntStatus = STATUS_SUCCESS;
  968. break;
  969. }
  970. // Create the new attributes
  971. ntStatus = UpGenerateDsAttribs(dwFlags, pNewUser, NULL, ppAttrs);
  972. if (ntStatus != STATUS_SUCCESS)
  973. {
  974. UpTrace("UPConvert: UpGenerateDsAttribs failed %x.", ntStatus);
  975. break;
  976. }
  977. } while (FALSE);
  978. // Cleanup
  979. {
  980. if (pvOrig)
  981. {
  982. UpFree(pvOrig);
  983. }
  984. if (pvNew)
  985. {
  986. UpFree(pvNew);
  987. }
  988. }
  989. return ntStatus;
  990. }
  991. //
  992. // Callback function called by NT5 SAM to free the blob
  993. // returned by UserParmsConvert.
  994. //
  995. VOID
  996. UserParmsFree(
  997. IN PSAM_USERPARMS_ATTRBLOCK pData)
  998. {
  999. SAM_USERPARMS_ATTR * pCur = NULL;
  1000. DWORD i, j;
  1001. UpTrace("UserParmsFree: Entered. %x", pData);
  1002. // If no attributes were given, we're all done
  1003. if (pData == NULL)
  1004. return;
  1005. if (pData->UserParmsAttr)
  1006. {
  1007. // Loop through all the attributes, freeing them
  1008. // as you go.
  1009. for (i = 0; i < pData->attCount; i++)
  1010. {
  1011. // Keep track of the current attribute
  1012. pCur = &(pData->UserParmsAttr[i]);
  1013. // Free the copied attribute name
  1014. if (pCur->AttributeIdentifier.Buffer)
  1015. UpFree(pCur->AttributeIdentifier.Buffer);
  1016. // Free any associated values as well.
  1017. if (pCur->Values)
  1018. {
  1019. for (j = 0; j < pCur->CountOfValues; j++)
  1020. {
  1021. // Assume there's only one value since that's
  1022. // all we ever set. Free the value
  1023. if (pCur->Values[j].value)
  1024. UpFree(pCur->Values[j].value);
  1025. }
  1026. // Free the value structure
  1027. UpFree(pCur->Values);
  1028. }
  1029. }
  1030. // Free the array of attributes
  1031. UpFree (pData->UserParmsAttr);
  1032. }
  1033. // Finally, free the whole structure
  1034. UpFree (pData);
  1035. }