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.

1042 lines
28 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. credapi.c
  5. Abstract:
  6. This module contains routines common between the netapi32.dll and LSA server side of
  7. the credential manager.
  8. Author:
  9. Cliff Van Dyke (CliffV) Oct 30, 2000
  10. Revision History:
  11. --*/
  12. #ifndef LSA_SERVER_COMPILED
  13. #include <lsacomp.h>
  14. #include <lmcons.h>
  15. #include "credp.h"
  16. #include <windns.h>
  17. #include <netlibnt.h>
  18. #include <names.h>
  19. #endif // LSA_SERVER_COMPILED
  20. //
  21. // Macros
  22. //
  23. #define CredpIsDomainCredential( _Type ) ( \
  24. (_Type) == CRED_TYPE_DOMAIN_PASSWORD || \
  25. (_Type) == CRED_TYPE_DOMAIN_CERTIFICATE || \
  26. (_Type) == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD )
  27. BOOLEAN
  28. CredpValidateDnsString(
  29. IN OUT LPWSTR String OPTIONAL,
  30. IN BOOLEAN NullOk,
  31. IN DNS_NAME_FORMAT DnsNameFormat,
  32. OUT PULONG StringSize
  33. )
  34. /*++
  35. Routine Description:
  36. This routine validates a passed in string. The string must be a valid DNS name.
  37. Any trailing . is truncated.
  38. Arguments:
  39. String - String to validate
  40. Any trailing . is truncated.
  41. This field is only modified if the routine returns TRUE.
  42. NullOk - if TRUE, a NULL string or zero length string is OK.
  43. DnsNameFormat - Expected format of the name.
  44. StringSize - Returns the length of the string (in bytes) including the
  45. trailing zero character.
  46. This field is only updated if the routine returns TRUE.
  47. Return Values:
  48. TRUE - String is valid.
  49. FALSE - String is not valid.
  50. --*/
  51. {
  52. ULONG TempStringLen;
  53. if ( String == NULL ) {
  54. if ( !NullOk ) {
  55. return FALSE;
  56. }
  57. *StringSize = 0;
  58. return TRUE;
  59. }
  60. TempStringLen = wcslen( String );
  61. if ( TempStringLen == 0 ) {
  62. if ( !NullOk ) {
  63. return FALSE;
  64. }
  65. } else {
  66. //
  67. // Remove the trailing .
  68. //
  69. if ( String[TempStringLen-1] == L'.' ) {
  70. TempStringLen -= 1;
  71. //
  72. // Ensure the string isn't empty now.
  73. //
  74. if ( TempStringLen == 0 ) {
  75. if ( !NullOk ) {
  76. return FALSE;
  77. }
  78. //
  79. // Ensure there aren't multiple trailing .'s
  80. //
  81. } else {
  82. if ( String[TempStringLen-1] == L'.' ) {
  83. return FALSE;
  84. }
  85. }
  86. }
  87. //
  88. // Have DNS finish the validation
  89. //
  90. if ( TempStringLen != 0 ) {
  91. DWORD WinStatus;
  92. WinStatus = DnsValidateName_W( String, DnsNameFormat );
  93. if ( WinStatus != NO_ERROR &&
  94. WinStatus != DNS_ERROR_NON_RFC_NAME ) {
  95. //
  96. // The RFC says hostnames cannot have numeric leftmost labels.
  97. // However, Win 2K servers have such hostnames.
  98. // So, allow them here forever more.
  99. //
  100. if ( DnsNameFormat == DnsNameHostnameFull &&
  101. WinStatus == DNS_ERROR_NUMERIC_NAME ) {
  102. /* Drop through */
  103. } else {
  104. return FALSE;
  105. }
  106. }
  107. }
  108. }
  109. if ( TempStringLen > DNS_MAX_NAME_LENGTH ) {
  110. return FALSE;
  111. }
  112. String[TempStringLen] = L'\0';
  113. *StringSize = (TempStringLen + 1) * sizeof(WCHAR);
  114. return TRUE;
  115. }
  116. BOOLEAN
  117. CredpValidateString(
  118. IN LPWSTR String OPTIONAL,
  119. IN ULONG MaximumLength,
  120. IN BOOLEAN NullOk,
  121. OUT PULONG StringSize
  122. )
  123. /*++
  124. Routine Description:
  125. This routine validates a passed in string.
  126. Arguments:
  127. String - String to validate
  128. MaximumLength - Maximum length of the string (in characters).
  129. NullOk - if TRUE, a NULL string or zero length string is OK.
  130. StringSize - Returns the length of the string (in bytes) including the
  131. trailing zero character.
  132. Return Values:
  133. TRUE - String is valid.
  134. FALSE - String is not valid.
  135. --*/
  136. {
  137. ULONG TempStringLen;
  138. if ( String == NULL ) {
  139. if ( !NullOk ) {
  140. return FALSE;
  141. }
  142. *StringSize = 0;
  143. return TRUE;
  144. }
  145. TempStringLen = wcslen( String );
  146. if ( TempStringLen == 0 ) {
  147. if ( !NullOk ) {
  148. return FALSE;
  149. }
  150. *StringSize = 0;
  151. return TRUE;
  152. }
  153. if ( TempStringLen > MaximumLength ) {
  154. return FALSE;
  155. }
  156. *StringSize = (TempStringLen + 1) * sizeof(WCHAR);
  157. return TRUE;
  158. }
  159. NTSTATUS
  160. CredpValidateUserName(
  161. IN LPWSTR UserName,
  162. IN ULONG Type,
  163. OUT LPWSTR *CanonicalUserName
  164. )
  165. /*++
  166. Routine Description:
  167. This routine validates a passed in user name.
  168. For a password credential, a user name must have one of the following two syntaxes:
  169. <DomainName>\<UserName>
  170. <UserName>@<DnsDomainName>
  171. The name is considered to have the first syntax if the string contains an \.
  172. A string containing a @ is ambiguous since <UserName> may contain an @.
  173. For the second syntax, the last @ in the string is used since <UserName> may
  174. contain an @ but <DnsDomainName> cannot.
  175. For a certificate credential, the user name must be a marshalled cert reference
  176. Arguments:
  177. UserName - Name of user to validate.
  178. Type - Specifies the Type of the credential.
  179. One of the CRED_TYPE_* values should be specified.
  180. CanonicalUserName - Returns a pointer to a buffer containing the user name in canonical form.
  181. Return Values:
  182. The following status codes may be returned:
  183. STATUS_INVALID_ACCOUNT_NAME - The user name is not valid.
  184. --*/
  185. {
  186. NTSTATUS Status;
  187. LPWSTR SlashPointer;
  188. LPWSTR AtPointer;
  189. LPWSTR LocalUserName = NULL;
  190. ULONG UserNameSize;
  191. ULONG LocalStringSize;
  192. //
  193. // Check the string length
  194. //
  195. if ( !CredpValidateString( UserName,
  196. CRED_MAX_USERNAME_LENGTH,
  197. FALSE,
  198. &UserNameSize ) ) {
  199. Status = STATUS_INVALID_ACCOUNT_NAME;
  200. goto Cleanup;
  201. }
  202. //
  203. // Grab a local writable copy of the string.
  204. //
  205. LocalUserName = (LPWSTR) LocalAlloc( 0, UserNameSize );
  206. if ( LocalUserName == NULL ) {
  207. Status = STATUS_NO_MEMORY;
  208. goto Cleanup;
  209. }
  210. RtlCopyMemory( LocalUserName, UserName, UserNameSize );
  211. //
  212. // Domain credentials need further validation.
  213. //
  214. if ( CredpIsDomainCredential( Type ) ) {
  215. //
  216. // Cert credentials have a marshalled cert reference as the UserName
  217. //
  218. if ( Type == CRED_TYPE_DOMAIN_CERTIFICATE ) {
  219. DWORD WinStatus;
  220. CRED_MARSHAL_TYPE CredType;
  221. PVOID UnmarshalledUsername;
  222. if ( !CredUnmarshalCredentialW( LocalUserName, &CredType, &UnmarshalledUsername ) ) {
  223. WinStatus = GetLastError();
  224. if ( WinStatus == ERROR_INVALID_PARAMETER ) {
  225. Status = STATUS_INVALID_ACCOUNT_NAME;
  226. } else {
  227. Status = NetpApiStatusToNtStatus(WinStatus);
  228. }
  229. goto Cleanup;
  230. }
  231. CredFree( UnmarshalledUsername );
  232. if ( CredType != CertCredential ) {
  233. Status = STATUS_INVALID_ACCOUNT_NAME;
  234. goto Cleanup;
  235. }
  236. //
  237. // Password credentials have UPN or domain\account user names
  238. //
  239. } else {
  240. //
  241. // Classify the input account name.
  242. //
  243. // The name is considered to be <DomainName>\<UserName> if the string
  244. // contains an \.
  245. //
  246. SlashPointer = wcsrchr( LocalUserName, L'\\' );
  247. if ( SlashPointer != NULL ) {
  248. LPWSTR LocalUserNameEnd;
  249. LPWSTR AfterSlashPointer;
  250. //
  251. // Skip the backslash
  252. //
  253. *SlashPointer = L'\0';
  254. AfterSlashPointer = SlashPointer + 1;
  255. //
  256. // Ensure the string to the left of the \ is a valid domain name
  257. //
  258. // (Do DNS name first to allow the name to be canonicalized.)
  259. LocalStringSize = (ULONG)(SlashPointer-LocalUserName+1)*sizeof(WCHAR);
  260. if ( !CredpValidateDnsString( LocalUserName, FALSE, DnsNameDomain, &LocalStringSize ) &&
  261. !NetpIsDomainNameValid( LocalUserName ) ) {
  262. Status = STATUS_INVALID_ACCOUNT_NAME;
  263. goto Cleanup;
  264. }
  265. //
  266. // Ensure the string to the right of the \ is a valid user name
  267. //
  268. if ( !NetpIsUserNameValid( AfterSlashPointer )) {
  269. Status = STATUS_INVALID_ACCOUNT_NAME;
  270. goto Cleanup;
  271. }
  272. //
  273. // If the dns domain name was canonicalized,
  274. // rebuild the complete user name.
  275. //
  276. *SlashPointer = '\\';
  277. LocalUserNameEnd = &LocalUserName[LocalStringSize/sizeof(WCHAR) - 1];
  278. if ( SlashPointer != LocalUserNameEnd ) {
  279. RtlMoveMemory( LocalUserNameEnd,
  280. SlashPointer,
  281. (wcslen(SlashPointer) + 1) * sizeof(WCHAR) );
  282. }
  283. //
  284. // Otherwise the name must be a UPN
  285. //
  286. } else {
  287. //
  288. // A UPN has the syntax <AccountName>@<DnsDomainName>.
  289. // If there are multiple @ signs,
  290. // use the last one since an AccountName can have an @ in it.
  291. //
  292. //
  293. AtPointer = wcsrchr( LocalUserName, L'@' );
  294. if ( AtPointer == NULL ) {
  295. Status = STATUS_INVALID_ACCOUNT_NAME;
  296. goto Cleanup;
  297. }
  298. //
  299. // The string to the left of the @ can really have any syntax.
  300. // But must be non-null.
  301. //
  302. if ( AtPointer == LocalUserName ) {
  303. Status = STATUS_INVALID_ACCOUNT_NAME;
  304. goto Cleanup;
  305. }
  306. //
  307. // Ensure the string to the right of the @ is a DNS domain name
  308. //
  309. AtPointer ++;
  310. if ( !CredpValidateDnsString( AtPointer, FALSE, DnsNameDomain, &LocalStringSize ) ) {
  311. Status = STATUS_INVALID_ACCOUNT_NAME;
  312. goto Cleanup;
  313. }
  314. }
  315. }
  316. }
  317. Status = STATUS_SUCCESS;
  318. //
  319. // Copy parameters back to the caller
  320. //
  321. *CanonicalUserName = LocalUserName;
  322. LocalUserName = NULL;
  323. //
  324. // Cleanup
  325. //
  326. Cleanup:
  327. if ( LocalUserName != NULL ) {
  328. MIDL_user_free( LocalUserName );
  329. }
  330. return Status;
  331. }
  332. NTSTATUS
  333. NET_API_FUNCTION
  334. CredpValidateTargetName(
  335. IN OUT LPWSTR TargetName,
  336. IN ULONG Type,
  337. IN TARGET_NAME_TYPE TargetNameType,
  338. IN LPWSTR *UserNamePointer OPTIONAL,
  339. IN LPDWORD PersistPointer OPTIONAL,
  340. OUT PULONG TargetNameSize,
  341. OUT PWILDCARD_TYPE WildcardTypePointer OPTIONAL,
  342. OUT PUNICODE_STRING NonWildcardedTargetName OPTIONAL
  343. )
  344. /*++
  345. Routine Description:
  346. This routine validates a passed in TargetName and TargetType for a credential.
  347. Arguments:
  348. TargetName - TargetName to validate
  349. The returned buffer is a canonicalized form of the target name.
  350. Type - Specifies the Type of the credential.
  351. One of the CRED_TYPE_* values should be specified.
  352. TargetNameType - Specifies whether the TargetName needs to match UsernameTarget Syntax
  353. UserNamePointer - Points to the address of a string which is the user name on the credential.
  354. If NULL, the UserName is unknown.
  355. If not NULL, the user name is used for UsernameTarget target name validation.
  356. PersistPointer - Points to a DWORD describing the persistence of the credential named by TargetName.
  357. If NULL, the peristence is unknown.
  358. If not NULL, the persistence will be checked to ensure it is valid for TargetName.
  359. TargetNameSize - Returns the length of the TargetName (in bytes) including the
  360. trailing zero character.
  361. WildcardType - If specified, returns the type of the wildcard specified in TargetName
  362. NonWildcardedTargetName - If specified, returns the non-wildcarded form of TargetName.
  363. The caller must free NonWildcardedTargetName->Buffer using MIDL_user_free.
  364. Return Values:
  365. The following status codes may be returned:
  366. STATUS_INVALID_PARAMETER - The TargetName or Type are invalid.
  367. STATUS_INVALID_ACCOUNT_NAME - The user name is not valid.
  368. --*/
  369. {
  370. NTSTATUS Status;
  371. ULONG MaxStringLength;
  372. LPWSTR AllocatedTargetName = NULL;
  373. ULONG TempTargetNameSize;
  374. BOOLEAN TargetNameIsUserName = FALSE;
  375. WILDCARD_TYPE WildcardType;
  376. LPWSTR CanonicalUserName = NULL;
  377. LPWSTR TnAsCanonicalUserName = NULL;
  378. LPWSTR RealTargetName = TargetName; // TargetName sans wildcard chars
  379. ULONG RealTargetNameLength;
  380. //
  381. // Initialization
  382. //
  383. if ( NonWildcardedTargetName != NULL ) {
  384. RtlInitUnicodeString( NonWildcardedTargetName, NULL );
  385. }
  386. //
  387. // Validate the type
  388. //
  389. if ( Type == CRED_TYPE_GENERIC ) {
  390. MaxStringLength = CRED_MAX_GENERIC_TARGET_NAME_LENGTH;
  391. //
  392. // Don't allow generic UsernameTarget credentials
  393. //
  394. if ( TargetNameType == IsUsernameTarget ) {
  395. #ifdef LSA_SERVER_COMPILED
  396. DebugLog(( DEB_TRACE_CRED,
  397. "CredpValidateTargetName: Generic creds cannot be UsernameTarget: %ld.\n",
  398. Type ));
  399. #endif // LSA_SERVER_COMPILED
  400. Status = STATUS_INVALID_PARAMETER;
  401. goto Cleanup;
  402. }
  403. //
  404. // We really know this isn't a UsernameTarget credential
  405. //
  406. TargetNameType = IsNotUsernameTarget;
  407. } else if ( CredpIsDomainCredential( Type ) ) {
  408. MaxStringLength = CRED_MAX_DOMAIN_TARGET_NAME_LENGTH;
  409. ASSERT( CRED_MAX_DOMAIN_TARGET_NAME_LENGTH == DNS_MAX_NAME_LENGTH + 1 + 1 + NNLEN );
  410. } else {
  411. #ifdef LSA_SERVER_COMPILED
  412. DebugLog(( DEB_TRACE_CRED,
  413. "CredpValidateTargetName: %ws: Invalid Type: %ld.\n",
  414. TargetName,
  415. Type ));
  416. #endif // LSA_SERVER_COMPILED
  417. Status = STATUS_INVALID_PARAMETER;
  418. goto Cleanup;
  419. }
  420. //
  421. // If this might be a "UsernameTarget" credential,
  422. // check if the credential looks like a user name.
  423. //
  424. if ( TargetNameType == IsUsernameTarget ||
  425. TargetNameType == MightBeUsernameTarget ) {
  426. //
  427. // Also allow target names that are valid user names
  428. // (Don't canonicalize. We don't have an opportunity to canonicalize short names.)
  429. //
  430. Status = CredpValidateUserName( TargetName, Type, &TnAsCanonicalUserName );
  431. if ( NT_SUCCESS(Status) ) {
  432. //
  433. // If we don't know the user name,
  434. // accept this as valid syntax.
  435. //
  436. if ( UserNamePointer == NULL ) {
  437. MaxStringLength = CRED_MAX_USERNAME_LENGTH;
  438. TargetNameIsUserName = TRUE;
  439. //
  440. // If we know the user name,
  441. // it must match for this syntax to be valid.
  442. //
  443. } else {
  444. UNICODE_STRING UserNameString;
  445. UNICODE_STRING TargetNameString;
  446. //
  447. // Validate the user name before touching it.
  448. //
  449. Status = CredpValidateUserName( *UserNamePointer,
  450. Type,
  451. &CanonicalUserName );
  452. if ( !NT_SUCCESS(Status) ) {
  453. goto Cleanup;
  454. }
  455. RtlInitUnicodeString( &UserNameString, CanonicalUserName );
  456. RtlInitUnicodeString( &TargetNameString, TnAsCanonicalUserName );
  457. //
  458. // The target name might be identical to the UserName.
  459. //
  460. // Such credentials are the "UsernameTarget" credentials.
  461. //
  462. if ( UserNameString.Length != 0 &&
  463. RtlEqualUnicodeString( &TargetNameString,
  464. &UserNameString,
  465. TRUE ) ) {
  466. MaxStringLength = CRED_MAX_USERNAME_LENGTH;
  467. TargetNameIsUserName = TRUE;
  468. }
  469. }
  470. }
  471. //
  472. // If the caller was sure this is a UsernameTarget credential,
  473. // make sure it really was.
  474. //
  475. if ( TargetNameType == IsUsernameTarget && !TargetNameIsUserName ) {
  476. #ifdef LSA_SERVER_COMPILED
  477. DebugLog(( DEB_TRACE_CRED,
  478. "CredpValidateTargetName: %ws: Is 'UsernameTarget' and target name doesn't match user name: %ld.\n",
  479. TargetName,
  480. Type ));
  481. #endif // LSA_SERVER_COMPILED
  482. Status = STATUS_INVALID_PARAMETER;
  483. goto Cleanup;
  484. }
  485. }
  486. //
  487. // Validate the string
  488. //
  489. if ( !CredpValidateString( TargetName,
  490. MaxStringLength,
  491. FALSE, // NULL not OK
  492. TargetNameSize ) ) {
  493. #ifdef LSA_SERVER_COMPILED
  494. DebugLog(( DEB_TRACE_CRED,
  495. "CredpValidateTargetName: Invalid TargetName buffer.\n" ));
  496. #endif // LSA_SERVER_COMPILED
  497. Status = STATUS_INVALID_PARAMETER;
  498. goto Cleanup;
  499. }
  500. //
  501. // For generic credentials,
  502. // that's all the validation needed.
  503. //
  504. WildcardType = WcServerName;
  505. if ( Type == CRED_TYPE_GENERIC ) {
  506. /* Do nothing here */
  507. //
  508. // For domain credentials,
  509. // classify the target name.
  510. //
  511. } else {
  512. //
  513. // The target name might be a user name.
  514. // (If we're not sure, let the other types take precedence.)
  515. //
  516. RealTargetName = TargetName;
  517. RealTargetNameLength = (*TargetNameSize-sizeof(WCHAR))/sizeof(WCHAR);
  518. if ( TargetNameType == IsUsernameTarget && TargetNameIsUserName ) {
  519. WildcardType = WcUserName;
  520. wcscpy( TargetName, TnAsCanonicalUserName );
  521. *TargetNameSize = (wcslen( TargetName ) + 1) * sizeof(WCHAR);
  522. //
  523. // The target name might be of the form <Domain>\*
  524. //
  525. } else if ( RealTargetNameLength > 2 &&
  526. RealTargetName[RealTargetNameLength-1] == L'*' &&
  527. RealTargetName[RealTargetNameLength-2] == L'\\' ) {
  528. //
  529. // Allocate a buffer for the target name so we don't have to modify the
  530. // callers buffer.
  531. //
  532. WildcardType = WcDomainWildcard;
  533. AllocatedTargetName = (LPWSTR) MIDL_user_allocate( *TargetNameSize );
  534. if ( AllocatedTargetName == NULL ) {
  535. Status = STATUS_NO_MEMORY;
  536. goto Cleanup;
  537. }
  538. RtlCopyMemory( AllocatedTargetName, RealTargetName, *TargetNameSize );
  539. RealTargetName = AllocatedTargetName;
  540. RealTargetNameLength -= 2;
  541. RealTargetName[RealTargetNameLength] = '\0';
  542. //
  543. // The domain itself might be a netbios or DNS domain
  544. //
  545. // Do DNS test first. That allows the validate routine to truncate
  546. //
  547. TempTargetNameSize = ((RealTargetNameLength+1)*sizeof(WCHAR));
  548. if ( !CredpValidateDnsString(
  549. RealTargetName,
  550. FALSE,
  551. DnsNameDomain,
  552. &TempTargetNameSize ) &&
  553. !NetpIsDomainNameValid( RealTargetName ) ) {
  554. Status = STATUS_INVALID_PARAMETER;
  555. #ifdef LSA_SERVER_COMPILED
  556. DebugLog(( DEB_TRACE_CRED,
  557. "ValidateTargetName: %ws: TargetName for domain wildcard must netbios or dns domain.\n",
  558. TargetName ));
  559. #endif // LSA_SERVER_COMPILED
  560. goto Cleanup;
  561. }
  562. //
  563. // If Dns truncated,
  564. // put the canonical name back in the callers buffer.
  565. //
  566. RealTargetNameLength = (TempTargetNameSize-sizeof(WCHAR))/sizeof(WCHAR);
  567. RealTargetName[RealTargetNameLength] = '\0';
  568. if ( *TargetNameSize+(2*sizeof(WCHAR)) != TempTargetNameSize ) {
  569. RtlCopyMemory( TargetName,
  570. RealTargetName,
  571. TempTargetNameSize );
  572. TargetName[RealTargetNameLength] = '\\';
  573. TargetName[RealTargetNameLength+1] = '*';
  574. TargetName[RealTargetNameLength+2] = '\0';
  575. *TargetNameSize = (wcslen( TargetName ) + 1) * sizeof(WCHAR);
  576. }
  577. //
  578. // Handle the universal wildcard
  579. //
  580. } else if ( RealTargetNameLength == 1 &&
  581. RealTargetName[0] == L'*' ) {
  582. WildcardType = WcUniversalWildcard;
  583. //
  584. // Handle server wildcards
  585. //
  586. } else if ( CredpValidateDnsString(
  587. TargetName,
  588. FALSE,
  589. DnsNameWildcard,
  590. TargetNameSize )) {
  591. WildcardType = WcServerWildcard;
  592. RealTargetName += 1;
  593. RealTargetNameLength -= 1;
  594. //
  595. // Handle the universal session wildcard
  596. //
  597. } else if ( RealTargetNameLength == CRED_SESSION_WILDCARD_NAME_LENGTH &&
  598. _wcsicmp( RealTargetName, CRED_SESSION_WILDCARD_NAME_W ) == 0 ) {
  599. WildcardType = WcUniversalSessionWildcard;
  600. //
  601. // This target name requires session persistence.
  602. //
  603. if ( PersistPointer != NULL &&
  604. *PersistPointer != CRED_PERSIST_SESSION ) {
  605. Status = STATUS_INVALID_PARAMETER;
  606. #ifdef LSA_SERVER_COMPILED
  607. DebugLog(( DEB_TRACE_CRED,
  608. "ValidateTargetName: %ws: TargetName requires session persistence %ld.\n",
  609. TargetName,
  610. *PersistPointer ));
  611. #endif // LSA_SERVER_COMPILED
  612. goto Cleanup;
  613. }
  614. //
  615. // The target name might be a non-wildcard netbios name.
  616. // The target name might be a non-wildcard dns name.
  617. //
  618. // Do DNS test first. That allows the validate routine to truncate
  619. // the trailing .
  620. //
  621. //
  622. } else if ( CredpValidateDnsString(
  623. TargetName,
  624. FALSE,
  625. DnsNameHostnameFull,
  626. TargetNameSize ) ||
  627. NetpIsDomainNameValid( TargetName ) ) {
  628. WildcardType = WcServerName;
  629. //
  630. // This target name might be a DFS share name
  631. //
  632. // The format is <DfsRoot>\<DfsShare>
  633. //
  634. } else {
  635. LPWSTR SlashPtr;
  636. ULONG SavedTargetNameSize;
  637. //
  638. // A DFS Share has a slash in it
  639. //
  640. SlashPtr = wcschr( TargetName, L'\\' );
  641. if ( SlashPtr != NULL ) {
  642. //
  643. // A DFS share has a share name with the right syntax
  644. //
  645. if ( NetpIsShareNameValid( SlashPtr+1 ) ) {
  646. //
  647. // Allocate a copy of the data for the RealTargetName
  648. //
  649. AllocatedTargetName = (LPWSTR) MIDL_user_allocate( *TargetNameSize );
  650. if ( AllocatedTargetName == NULL ) {
  651. Status = STATUS_NO_MEMORY;
  652. goto Cleanup;
  653. }
  654. RtlCopyMemory( AllocatedTargetName, RealTargetName, *TargetNameSize );
  655. RealTargetName = AllocatedTargetName;
  656. RealTargetNameLength = (ULONG)(SlashPtr-TargetName);
  657. RealTargetName[RealTargetNameLength] = '\0';
  658. //
  659. // The domain itself might be a netbios or DNS domain
  660. //
  661. // Do DNS test first. That allows the validate routine to truncate
  662. //
  663. TempTargetNameSize = ((RealTargetNameLength+1)*sizeof(WCHAR));
  664. SavedTargetNameSize = TempTargetNameSize;
  665. if ( CredpValidateDnsString(
  666. RealTargetName,
  667. FALSE,
  668. DnsNameDomain,
  669. &TempTargetNameSize ) ||
  670. NetpIsDomainNameValid( RealTargetName ) ) {
  671. //
  672. // If Dns truncated,
  673. // put the canonical name back in the callers buffer.
  674. //
  675. RealTargetNameLength = (TempTargetNameSize-sizeof(WCHAR))/sizeof(WCHAR);
  676. RealTargetName[RealTargetNameLength] = '\0';
  677. if ( SavedTargetNameSize != TempTargetNameSize ) {
  678. ULONG DfsShareSize;
  679. DfsShareSize = *TargetNameSize - (SlashPtr-TargetName)*sizeof(WCHAR);
  680. // Copy <DfsRoot>
  681. RtlCopyMemory( TargetName,
  682. RealTargetName,
  683. RealTargetNameLength*sizeof(WCHAR) );
  684. // Copy \<DfsShare><\0>
  685. RtlMoveMemory( &TargetName[RealTargetNameLength],
  686. SlashPtr,
  687. DfsShareSize );
  688. *TargetNameSize = RealTargetNameLength*sizeof(WCHAR) + DfsShareSize;
  689. }
  690. WildcardType = WcDfsShareName;
  691. }
  692. }
  693. }
  694. //
  695. // At this point,
  696. // if the syntax isn't DFS SHARE,
  697. // Then it must be one of the other syntaxes.
  698. //
  699. if ( WildcardType != WcDfsShareName ) {
  700. //
  701. // The target name might have defaulted to be a user name.
  702. //
  703. if ( TargetNameIsUserName ) {
  704. WildcardType = WcUserName;
  705. wcscpy( TargetName, TnAsCanonicalUserName );
  706. *TargetNameSize = (wcslen( TargetName ) + 1) * sizeof(WCHAR);
  707. //
  708. // Everything else is invalid
  709. //
  710. } else {
  711. Status = STATUS_INVALID_PARAMETER;
  712. #ifdef LSA_SERVER_COMPILED
  713. DebugLog(( DEB_TRACE_CRED,
  714. "ValidateTargetName: %ws: TargetName syntax invalid.\n",
  715. TargetName ));
  716. #endif // LSA_SERVER_COMPILED
  717. goto Cleanup;
  718. }
  719. }
  720. }
  721. }
  722. //
  723. // On success, copy the parameters back to the caller.
  724. //
  725. if ( WildcardTypePointer != NULL ) {
  726. *WildcardTypePointer = WildcardType;
  727. }
  728. if ( NonWildcardedTargetName != NULL ) {
  729. ULONG BufferSize = (wcslen(RealTargetName) + 1) * sizeof(WCHAR);
  730. NonWildcardedTargetName->Buffer = (LPWSTR) MIDL_user_allocate( BufferSize );
  731. if ( NonWildcardedTargetName->Buffer == NULL ) {
  732. Status = STATUS_NO_MEMORY;
  733. goto Cleanup;
  734. }
  735. RtlCopyMemory( NonWildcardedTargetName->Buffer, RealTargetName, BufferSize );
  736. NonWildcardedTargetName->MaximumLength = (USHORT)BufferSize;
  737. NonWildcardedTargetName->Length = (USHORT)(BufferSize - sizeof(WCHAR));
  738. }
  739. Status = STATUS_SUCCESS;
  740. Cleanup:
  741. if ( AllocatedTargetName != NULL ) {
  742. MIDL_user_free( AllocatedTargetName );
  743. }
  744. if ( CanonicalUserName != NULL ) {
  745. MIDL_user_free( CanonicalUserName );
  746. }
  747. if ( TnAsCanonicalUserName != NULL ) {
  748. MIDL_user_free( TnAsCanonicalUserName );
  749. }
  750. return Status;
  751. }