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.

1375 lines
36 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fsp_srv.c
  5. Abstract:
  6. This module contains the entry points for the AFP server APIs queued to
  7. the FSP. These are all callable from FSP Only.
  8. Author:
  9. Jameel Hyder (microsoft!jameelh)
  10. Revision History:
  11. 25 Apr 1992 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #define FILENUM FILE_FSP_SRV
  15. #include <afp.h>
  16. #include <gendisp.h>
  17. #include <client.h>
  18. #include <scavengr.h>
  19. #include <secutil.h>
  20. LOCAL BOOLEAN
  21. afpGetUserNameAndPwdOrWSName(
  22. IN PANSI_STRING Block,
  23. IN BOOLEAN Password,
  24. OUT PUNICODE_STRING pUserName,
  25. OUT PUNICODE_STRING pDomainName,
  26. OUT PVOID pParm
  27. );
  28. LOCAL BOOLEAN
  29. afpGetNameAndDomain(
  30. IN PANSI_STRING pDomainNUser,
  31. OUT PUNICODE_STRING pUserName,
  32. OUT PUNICODE_STRING pDomainName
  33. );
  34. #ifdef ALLOC_PRAGMA
  35. #pragma alloc_text( PAGE, AfpFspDispLogin)
  36. #pragma alloc_text( PAGE, AfpFspDispLoginCont)
  37. #pragma alloc_text( PAGE, AfpFspDispLogout)
  38. #pragma alloc_text( PAGE, AfpFspDispChangePassword)
  39. #pragma alloc_text( PAGE, AfpFspDispMapName)
  40. #pragma alloc_text( PAGE, AfpFspDispMapId)
  41. #pragma alloc_text( PAGE, AfpFspDispGetUserInfo)
  42. #pragma alloc_text( PAGE, afpGetUserNameAndPwdOrWSName)
  43. #pragma alloc_text( PAGE, afpGetNameAndDomain)
  44. #endif
  45. /*** AfpFspDispLogin
  46. *
  47. * This is the worker routine for the AfpLogin API.
  48. *
  49. * The request packet is represented below.
  50. *
  51. * sda_Name1 ANSI_STRING AFP Version
  52. * sda_Name2 ANSI_STRING UAM String
  53. * sda_Name3 BLOCK Depends on the UAM used
  54. * NO_USER_AUTHENT Not used
  55. * CLEAR_TEXT_AUTHENT User Name & Password string
  56. * CUSTOM_UAM User Name & Machine Name
  57. * Both the ClearText and the Custom UAM case are treated identically
  58. * except for validation.
  59. *
  60. * LOCKS: sda_Lock (SPIN)
  61. */
  62. AFPSTATUS FASTCALL
  63. AfpFspDispLogin(
  64. IN PSDA pSda
  65. )
  66. {
  67. LONG i;
  68. ANSI_STRING UserPasswd;
  69. AFPSTATUS Status = AFP_ERR_NONE;
  70. IPADDRESS IpAddress;
  71. struct _AppleUamRespPacket
  72. {
  73. BYTE _LogonId[2];
  74. BYTE _ChallengeToClient[1];
  75. };
  76. struct _AppleUamRespPacket *pAppleUamRespPacket;
  77. struct _ResponsePacket
  78. {
  79. BYTE _ChallengeToClient[MSV1_0_CHALLENGE_LENGTH];
  80. BYTE _TranslationTable[1];
  81. };
  82. PAGED_CODE( );
  83. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  84. ("AfpFspDispLogin: Entered\n"));
  85. UserPasswd.Length = 0;
  86. UserPasswd.MaximumLength = 0;
  87. UserPasswd.Buffer = NULL;
  88. AfpSetEmptyAnsiString(&UserPasswd, 0, NULL);
  89. do
  90. {
  91. // First validate whether the call is allowed at this time. If a user
  92. // is either already logged on OR if we are awaiting a response after
  93. // a challenge has already been given, then this goes no further.
  94. if ((pSda->sda_Flags & SDA_LOGIN_MASK) != SDA_USER_NOT_LOGGEDIN)
  95. {
  96. Status = AFP_ERR_MISC;
  97. break;
  98. }
  99. // Validate the AFP Version
  100. for (i = 0; i < AFP_NUM_VERSIONS; i++)
  101. {
  102. if (RtlEqualString(&pSda->sda_Name1, &AfpVersions[i], True))
  103. {
  104. pSda->sda_ClientVersion = (BYTE)i;
  105. break;
  106. }
  107. }
  108. if (i == AFP_NUM_VERSIONS)
  109. {
  110. Status = AFP_ERR_BAD_VERSION;
  111. break;
  112. }
  113. #if DBG
  114. if (pSda->sda_Flags & SDA_SESSION_OVER_TCP)
  115. {
  116. PTCPCONN pTcpConn;
  117. pTcpConn = (PTCPCONN)(pSda->sda_SessHandle);
  118. IpAddress = pTcpConn->con_DestIpAddr;
  119. DBGPRINT(DBG_COMP_STACKIF, DBG_LEVEL_WARN,
  120. ("AFP/TCP: Mac client version 2.%d (%d.%d.%d.%d) connected (%lx)\n",
  121. pTcpConn->con_pSda->sda_ClientVersion,(IpAddress>>24)&0xFF,
  122. (IpAddress>>16)&0xFF,(IpAddress>>8)&0xFF,IpAddress&0xFF,pTcpConn));
  123. }
  124. else if (pSda->sda_ClientVersion >= AFP_VER_22)
  125. {
  126. DBGPRINT(DBG_COMP_STACKIF, DBG_LEVEL_WARN,
  127. ("AFP/Appletalk: Mac client version 2.%d connected\n",
  128. pSda->sda_ClientVersion));
  129. }
  130. #endif
  131. // Validate the UAM string
  132. for (i = 0; i < AFP_NUM_UAMS; i++)
  133. {
  134. if (RtlEqualString(&pSda->sda_Name2, &AfpUamStrings[i], True))
  135. {
  136. pSda->sda_ClientType = (BYTE)i;
  137. break;
  138. }
  139. }
  140. if (i == AFP_NUM_UAMS)
  141. {
  142. DBGPRINT(DBG_COMP_STACKIF, DBG_LEVEL_ERR,
  143. ("AfpFspDispLogin: unknown UAM, ignoring!\n"));
  144. Status = AFP_ERR_BAD_UAM;
  145. break;
  146. }
  147. // All seems OK so far. Handle the simple GUEST logon case first.
  148. pSda->sda_DomainName.Length = 0;
  149. pSda->sda_DomainName.Buffer = NULL;
  150. if (pSda->sda_ClientType == SDA_CLIENT_GUEST)
  151. {
  152. if (!(AfpServerOptions & AFP_SRVROPT_GUESTLOGONALLOWED))
  153. {
  154. Status = AFP_ERR_BAD_UAM;
  155. break;
  156. }
  157. // Lookup the current Guest account name
  158. if (1)
  159. {
  160. ULONG64 TempBuffer[16];
  161. PSID GuestSid;
  162. ULONG NameSize;
  163. ULONG DomainSize;
  164. UNICODE_STRING Name;
  165. SID_NAME_USE NameUse;
  166. WCHAR NameString[UNLEN+1];
  167. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  168. NTSTATUS TempStatus = STATUS_SUCCESS;
  169. GuestSid = (PSID)TempBuffer;
  170. RtlInitializeSid (
  171. GuestSid,
  172. &NtAuthority,
  173. 2
  174. );
  175. *(RtlSubAuthoritySid (GuestSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
  176. *(RtlSubAuthoritySid (GuestSid, 1)) = DOMAIN_USER_RID_GUEST;
  177. Name.Buffer = NameString;
  178. Name.Length = sizeof (NameString);
  179. Name.MaximumLength = Name.Length;
  180. TempStatus = SecLookupAccountSid (
  181. GuestSid,
  182. &NameSize,
  183. &Name,
  184. &DomainSize,
  185. NULL,
  186. &NameUse
  187. );
  188. if (TempStatus != STATUS_SUCCESS)
  189. {
  190. DBGPRINT(DBG_COMP_STACKIF, DBG_LEVEL_ERR,
  191. ("AfpFspDispLogin: SecLookupAccountSid failed with error %ld\n",
  192. TempStatus));
  193. Status = AFP_ERR_MISC;
  194. break;
  195. }
  196. DBGPRINT(DBG_COMP_STACKIF, DBG_LEVEL_ERR,
  197. ("AfpFspDispLogin: SecLookupAccountSid returned GuestName = %Z, Guestname Size = %d\n",
  198. &Name, Name.Length));
  199. if ((pSda->sda_UserName.Buffer =
  200. (PWSTR)AfpAllocNonPagedMemory(Name.Length)) == NULL)
  201. {
  202. Status = AFP_ERR_MISC;
  203. break;
  204. }
  205. memcpy ((BYTE *)(pSda->sda_UserName.Buffer), (BYTE *)Name.Buffer,
  206. Name.Length);
  207. pSda->sda_UserName.Length = Name.Length;
  208. pSda->sda_UserName.MaximumLength = Name.Length;
  209. }
  210. // Consider the guest as a cleartext client from this point on
  211. // with NULL password
  212. pSda->sda_ClientType = SDA_CLIENT_CLEARTEXT;
  213. Status = AfpLogonUser(pSda, &UserPasswd);
  214. break;
  215. }
  216. // Take apart the sda_Name3 block. The block looks as follows. We have
  217. // already eliminated the possibility of a GUEST login.
  218. // 1. ClearText/Custom UAM PASCALSTR - UserName (+DomainName)
  219. // 2. ClearText PASCALSTR - Password
  220. // Custom UAM PASCALSTR - MachineName
  221. if (pSda->sda_ClientType == SDA_CLIENT_CLEARTEXT)
  222. {
  223. if (!(AfpServerOptions & AFP_SRVROPT_CLEARTEXTLOGONALLOWED))
  224. {
  225. Status = AFP_ERR_BAD_UAM;
  226. break;
  227. }
  228. }
  229. if (!afpGetUserNameAndPwdOrWSName(&pSda->sda_Name3,
  230. (BOOLEAN)(pSda->sda_ClientType == SDA_CLIENT_CLEARTEXT),
  231. &pSda->sda_UserName,
  232. &pSda->sda_DomainName,
  233. (pSda->sda_ClientType == SDA_CLIENT_CLEARTEXT) ?
  234. (PVOID)&UserPasswd : (PVOID)&pSda->sda_WSName))
  235. {
  236. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  237. ("AfpFspDispLogin: afpGetUserNameAndPwdOrWSName failed\n"));
  238. Status = AFP_ERR_USER_NOT_AUTH;
  239. break;
  240. }
  241. // Attempt to logon user for Cleartext case
  242. if (pSda->sda_ClientType == SDA_CLIENT_CLEARTEXT)
  243. {
  244. // The user password as we have it is potentially padded with nulls
  245. // if it is less than 8 chars. Get the length right
  246. UserPasswd.Length = strlen(UserPasswd.Buffer) + 1;
  247. Status = AfpLogonUser(pSda, &UserPasswd);
  248. // Free the buffer for the password
  249. AfpFreeMemory(UserPasswd.Buffer);
  250. break;
  251. }
  252. else
  253. {
  254. // Using the custom UAM, ship the challenge token
  255. pSda->sda_ReplySize = MSV1_0_CHALLENGE_LENGTH;
  256. // is this MS-UAM client? if so, need room for translation table
  257. if ((pSda->sda_ClientType == SDA_CLIENT_MSUAM_V1) ||
  258. (pSda->sda_ClientType == SDA_CLIENT_MSUAM_V2))
  259. {
  260. pSda->sda_ReplySize += AFP_XLAT_TABLE_SIZE;
  261. }
  262. else
  263. {
  264. pSda->sda_ReplySize += sizeof(USHORT); // space for LogonId
  265. }
  266. if (AfpAllocReplyBuf(pSda) != AFP_ERR_NONE)
  267. {
  268. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  269. ("AfpFspDispLogin: AfpAllocReplyBuf failed\n"));
  270. Status = AFP_ERR_USER_NOT_AUTH;
  271. break;
  272. }
  273. if ((pSda->sda_Challenge = AfpGetChallenge()) == NULL)
  274. {
  275. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  276. ("AfpFspDispLogin: AfpGetChallenge failed\n"));
  277. Status = AFP_ERR_USER_NOT_AUTH;
  278. AfpFreeReplyBuf(pSda, FALSE);
  279. break;
  280. }
  281. Status = AFP_ERR_AUTH_CONTINUE;
  282. // MS-UAM client? copy challenge and translation table
  283. if ((pSda->sda_ClientType == SDA_CLIENT_MSUAM_V1) ||
  284. (pSda->sda_ClientType == SDA_CLIENT_MSUAM_V2))
  285. {
  286. RtlCopyMemory(pRspPkt->_ChallengeToClient, pSda->sda_Challenge,
  287. MSV1_0_CHALLENGE_LENGTH);
  288. RtlCopyMemory(pRspPkt->_TranslationTable,
  289. AfpTranslationTable+AFP_XLAT_TABLE_SIZE,
  290. AFP_XLAT_TABLE_SIZE);
  291. }
  292. else
  293. {
  294. pAppleUamRespPacket = (struct _AppleUamRespPacket *)(pSda->sda_ReplyBuf);
  295. // copy the LogonId (make one up, using the sda pointer itself!)
  296. //*(USHORT *)(&pAppleUamRespPacket->_LogonId[0]) = (USHORT)pSda;
  297. pAppleUamRespPacket->_LogonId[0] = 0;
  298. pAppleUamRespPacket->_LogonId[1] = 0;
  299. // copy the challenge
  300. RtlCopyMemory(&pAppleUamRespPacket->_ChallengeToClient[0],
  301. pSda->sda_Challenge,
  302. MSV1_0_CHALLENGE_LENGTH);
  303. }
  304. }
  305. } while (False);
  306. // Set the SDA in the right state
  307. if (Status == AFP_ERR_NONE)
  308. {
  309. AfpInterlockedSetNClearDword(&pSda->sda_Flags,
  310. SDA_USER_LOGGEDIN,
  311. SDA_LOGIN_FAILED,
  312. &pSda->sda_Lock);
  313. pSda->sda_WSName.Length = 0;
  314. pSda->sda_WSName.MaximumLength = 0;
  315. pSda->sda_WSName.Buffer = NULL;
  316. if (pSda->sda_tTillKickOff < MAXLONG)
  317. AfpScavengerScheduleEvent(
  318. AfpSdaCheckSession,
  319. (PVOID)((ULONG_PTR)(pSda->sda_SessionId)),
  320. (pSda->sda_tTillKickOff > SESSION_WARN_TIME) ?
  321. (pSda->sda_tTillKickOff - SESSION_WARN_TIME) :
  322. SESSION_CHECK_TIME,
  323. True);
  324. }
  325. else if (Status == AFP_ERR_AUTH_CONTINUE)
  326. {
  327. // Login is half-way done. Set to receive a FPLoginCont call
  328. AfpInterlockedSetDword(&pSda->sda_Flags,
  329. SDA_USER_LOGIN_PARTIAL,
  330. &pSda->sda_Lock);
  331. }
  332. else if (Status == AFP_ERR_PWD_EXPIRED)
  333. {
  334. AfpInterlockedSetDword(&pSda->sda_Flags,
  335. SDA_LOGIN_FAILED,
  336. &pSda->sda_Lock);
  337. Status = AFP_ERR_NONE;
  338. }
  339. return Status;
  340. }
  341. /*** AfpFspDispLoginCont
  342. *
  343. * This is the worker routine for the AfpLoginCont API.
  344. *
  345. * The request packet is represented below.
  346. *
  347. * sda_Name1 BLOCK Response to challenge (24 bytes)
  348. */
  349. AFPSTATUS FASTCALL
  350. AfpFspDispLoginCont(
  351. IN PSDA pSda
  352. )
  353. {
  354. AFPSTATUS Status = AFP_ERR_NONE;
  355. ANSI_STRING Passwd;
  356. struct _AppleUamReqPkt
  357. {
  358. BYTE _LogonId[2];
  359. BYTE _ChallengeResponse[1];
  360. };
  361. struct _AppleUamReqPkt *pAppleUamReqPkt;
  362. struct _RequestPacket
  363. {
  364. DWORD _ChallengeResponse[1];
  365. };
  366. PAGED_CODE( );
  367. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  368. ("AfpFspDispLoginCont: Entered\n"));
  369. if ((pSda->sda_Flags & SDA_LOGIN_MASK) != SDA_USER_LOGIN_PARTIAL)
  370. {
  371. Status = AFP_ERR_USER_NOT_AUTH;
  372. }
  373. else
  374. {
  375. if ((pSda->sda_ClientType == SDA_CLIENT_MSUAM_V1) ||
  376. (pSda->sda_ClientType == SDA_CLIENT_MSUAM_V2))
  377. {
  378. Passwd.Length = Passwd.MaximumLength = LM_RESPONSE_LENGTH;
  379. Passwd.Buffer = (PBYTE)&pReqPkt->_ChallengeResponse[0];
  380. }
  381. else
  382. {
  383. pAppleUamReqPkt = (struct _AppleUamReqPkt *)(pSda->sda_ReqBlock);
  384. Passwd.Buffer = (PBYTE)&pAppleUamReqPkt->_ChallengeResponse[0];
  385. if (pSda->sda_ClientType == SDA_CLIENT_RANDNUM)
  386. {
  387. Passwd.Length = Passwd.MaximumLength = RANDNUM_RESP_LEN;
  388. }
  389. else
  390. {
  391. Passwd.Length = Passwd.MaximumLength = TWOWAY_RESP_LEN;
  392. }
  393. }
  394. ASSERT (pSda->sda_Challenge != NULL);
  395. Status = AfpLogonUser(pSda, &Passwd);
  396. AfpFreeMemory(pSda->sda_Challenge);
  397. pSda->sda_Challenge = NULL;
  398. }
  399. // Set the SDA in the right state
  400. if (Status == AFP_ERR_NONE)
  401. {
  402. AfpInterlockedSetNClearDword(&pSda->sda_Flags,
  403. SDA_USER_LOGGEDIN,
  404. SDA_USER_LOGIN_PARTIAL,
  405. &pSda->sda_Lock);
  406. if (pSda->sda_tTillKickOff < MAXLONG)
  407. AfpScavengerScheduleEvent(
  408. AfpSdaCheckSession,
  409. (PVOID)((ULONG_PTR)(pSda->sda_SessionId)),
  410. (pSda->sda_tTillKickOff > SESSION_WARN_TIME) ?
  411. (pSda->sda_tTillKickOff - SESSION_WARN_TIME) :
  412. SESSION_CHECK_TIME,
  413. True);
  414. }
  415. return Status;
  416. }
  417. /*** AfpFspDispLogout
  418. *
  419. * This is the worker routine for the AfpLogout API.
  420. *
  421. * There is no request packet for this API.
  422. */
  423. AFPSTATUS FASTCALL
  424. AfpFspDispLogout(
  425. IN PSDA pSda
  426. )
  427. {
  428. AFP_SESSION_INFO SessInfo;
  429. PAGED_CODE( );
  430. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  431. ("AfpFspDispLogout: Entered\n"));
  432. AfpInterlockedClearDword(&pSda->sda_Flags, SDA_LOGIN_MASK, &pSda->sda_Lock);
  433. return AFP_ERR_NONE;
  434. }
  435. /*** AfpFspDispChangePassword
  436. *
  437. * This is the worker routine for the AfpChangePassword API.
  438. *
  439. * The request packet is represented below.
  440. *
  441. * sda_AfpSubFunc BYTE New password length - UAM
  442. * sda_Name1 ANSI_STRING UAM String
  443. * sda_Name2 ANSI_STRING User Name [and domain]
  444. * sda_Name3 BLOCK Old and New passwords
  445. * Format depends on the UAM
  446. * ClearText Old Password (8 bytes, 0 padded)
  447. * New Password (8 bytes, 0 padded)
  448. * Encrypted Old Password LM_OWF_PASSWORD (16)
  449. * New Password LM_OWF_PASSWORD (16)
  450. *
  451. * All we do here is package the user name, domain name, old and new password
  452. * and give it up to user mode to attempt the password change since we cannot
  453. * do it in kernel mode.
  454. */
  455. AFPSTATUS FASTCALL
  456. AfpFspDispChangePassword(
  457. IN PSDA pSda
  458. )
  459. {
  460. AFPSTATUS Status;
  461. PAFP_PASSWORD_DESC pPwdDesc=NULL;
  462. ANSI_STRING NewPwd;
  463. UNICODE_STRING UserName;
  464. UNICODE_STRING DomainName;
  465. BYTE Method;
  466. struct _ResponsePacket
  467. {
  468. BYTE __ExtendedErrorCode[4];
  469. };
  470. PAGED_CODE( );
  471. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  472. ("AfpFspDispChangePassword: Entered\n"));
  473. if ((pPwdDesc =
  474. (PAFP_PASSWORD_DESC)AfpAllocPagedMemory(sizeof(AFP_PASSWORD_DESC))) == NULL)
  475. {
  476. return AFP_ERR_MISC;
  477. }
  478. AfpSetEmptyUnicodeString(&DomainName,
  479. sizeof(pPwdDesc->DomainName),
  480. pPwdDesc->DomainName);
  481. AfpSetEmptyUnicodeString(&UserName,
  482. sizeof(pPwdDesc->UserName),
  483. pPwdDesc->UserName);
  484. do
  485. {
  486. Status = AFP_ERR_BAD_UAM; // Default
  487. // Validate the UAM string, cannot be 'No User Authent'
  488. for (Method = CLEAR_TEXT_AUTHENT; Method < AFP_NUM_UAMS; Method++)
  489. {
  490. if (RtlEqualString(&pSda->sda_Name1,
  491. &AfpUamStrings[Method],
  492. True))
  493. {
  494. if (pSda->sda_Flags & SDA_USER_LOGGEDIN)
  495. {
  496. // if the client is logged in using TWOWAY_EXCHANGE, the
  497. // UAM specified in password change is still RANDNUM_EXCHANGE
  498. // so, hack it, so rest of our logic works!
  499. //
  500. if ((Method == RANDNUM_EXCHANGE) &&
  501. (pSda->sda_ClientType == TWOWAY_EXCHANGE))
  502. {
  503. Method = TWOWAY_EXCHANGE;
  504. }
  505. if (pSda->sda_ClientType == Method)
  506. {
  507. Status = AFP_ERR_NONE;
  508. }
  509. else
  510. {
  511. Status = AFP_ERR_PARAM;
  512. }
  513. }
  514. else
  515. {
  516. pSda->sda_ClientType = Method;
  517. Status = AFP_ERR_NONE;
  518. }
  519. break;
  520. }
  521. }
  522. if ((Status != AFP_ERR_NONE) ||
  523. ((Method == CLEAR_TEXT_AUTHENT) &&
  524. !(AfpServerOptions & AFP_SRVROPT_CLEARTEXTLOGONALLOWED)))
  525. {
  526. break;
  527. }
  528. Status = AFP_ERR_PARAM; // Assume failure
  529. RtlZeroMemory(pPwdDesc, sizeof(AFP_PASSWORD_DESC));
  530. // Validate and Convert user name to unicode. If the user is already
  531. // logged in, make sure the user name matches what we already know
  532. if (!afpGetNameAndDomain(&pSda->sda_Name2,
  533. &UserName,
  534. &DomainName) ||
  535. !RtlEqualUnicodeString(&UserName,
  536. &pSda->sda_UserName,
  537. True) ||
  538. !RtlEqualUnicodeString(&DomainName,
  539. &pSda->sda_DomainName,
  540. True))
  541. {
  542. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_ERR,
  543. ("AfpFspDispChangePassword: afpGetNameAndDomain failed\n"));
  544. break;
  545. }
  546. pPwdDesc->AuthentMode = Method;
  547. if (Method == CLEAR_TEXT_AUTHENT)
  548. {
  549. ANSI_STRING OldPwd;
  550. // Make sure the old and new passwords are atleast the min. size
  551. if (pSda->sda_Name3.Length < (2 * sizeof(AFP_MAXPWDSIZE)))
  552. break;
  553. // Translate both passwords to host ansi (upper case)
  554. OldPwd.Buffer = pPwdDesc->OldPassword;
  555. OldPwd.Length = sizeof(pPwdDesc->OldPassword);
  556. OldPwd.MaximumLength = sizeof(pPwdDesc->OldPassword);
  557. RtlCopyMemory(pPwdDesc->OldPassword,
  558. pSda->sda_Name3.Buffer,
  559. AFP_MAXPWDSIZE);
  560. if (AfpConvertMacAnsiToHostAnsi(&OldPwd) != AFP_ERR_NONE)
  561. {
  562. break;
  563. }
  564. NewPwd.Buffer = pPwdDesc->NewPassword;
  565. NewPwd.Length = sizeof(pPwdDesc->NewPassword);
  566. NewPwd.MaximumLength = sizeof(pPwdDesc->NewPassword);
  567. RtlCopyMemory(pPwdDesc->NewPassword,
  568. pSda->sda_Name3.Buffer+AFP_MAXPWDSIZE,
  569. AFP_MAXPWDSIZE);
  570. if (AfpConvertMacAnsiToHostAnsi(&NewPwd) != AFP_ERR_NONE)
  571. {
  572. break;
  573. }
  574. }
  575. //
  576. // if this is a client using Apple's native UAM, parms are different!
  577. //
  578. else if ((Method == RANDNUM_EXCHANGE) ||
  579. (Method == TWOWAY_EXCHANGE))
  580. {
  581. // Make sure the old and new passwords are atleast the min. size
  582. if (pSda->sda_Name3.Length < (2 * MAX_MAC_PWD_LEN))
  583. {
  584. ASSERT(0);
  585. break;
  586. }
  587. RtlCopyMemory(pPwdDesc->OldPassword,
  588. pSda->sda_Name3.Buffer,
  589. MAX_MAC_PWD_LEN);
  590. RtlCopyMemory(pPwdDesc->NewPassword,
  591. pSda->sda_Name3.Buffer + RANDNUM_RESP_LEN,
  592. MAX_MAC_PWD_LEN);
  593. }
  594. else if (Method == SDA_CLIENT_MSUAM_V1)
  595. {
  596. // Make sure the old and new passwords are atleast the min. size
  597. if (pSda->sda_Name3.Length < (2 * LM_OWF_PASSWORD_LENGTH))
  598. {
  599. break;
  600. }
  601. pPwdDesc->bPasswordLength = pSda->sda_AfpSubFunc;
  602. RtlCopyMemory(pPwdDesc->OldPassword,
  603. pSda->sda_Name3.Buffer,
  604. LM_OWF_PASSWORD_LENGTH);
  605. RtlCopyMemory(pPwdDesc->NewPassword,
  606. pSda->sda_Name3.Buffer + LM_OWF_PASSWORD_LENGTH,
  607. LM_OWF_PASSWORD_LENGTH);
  608. }
  609. else if (Method == SDA_CLIENT_MSUAM_V2)
  610. {
  611. // the data expected here is large (532 bytes) here
  612. try {
  613. RtlCopyMemory(pPwdDesc->OldPassword,
  614. pSda->sda_Name3.Buffer,
  615. LM_OWF_PASSWORD_LENGTH);
  616. RtlCopyMemory(pPwdDesc->NewPassword,
  617. pSda->sda_Name3.Buffer + LM_OWF_PASSWORD_LENGTH,
  618. (SAM_MAX_PASSWORD_LENGTH * 2) + 4);
  619. } except( EXCEPTION_EXECUTE_HANDLER ) {
  620. ASSERT(0);
  621. break;
  622. }
  623. }
  624. else
  625. {
  626. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_ERR,
  627. ("AfpFspDispChangePassword: unknown method %d\n",Method));
  628. ASSERT(0);
  629. }
  630. Status = AfpChangePassword(pSda, pPwdDesc);
  631. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_ERR,
  632. ("AfpFspDispChangePassword: AfpChangePassword returned %lx\n",
  633. Status));
  634. } while (False);
  635. if (NT_SUCCESS(Status))
  636. {
  637. // Check if we are here because the login returned password expired.
  638. // If this is Afp 2.1 chooser, we also need to logon this fella
  639. if (pSda->sda_Flags & SDA_LOGIN_FAILED)
  640. {
  641. AfpInterlockedClearDword(&pSda->sda_Flags,
  642. SDA_LOGIN_FAILED,
  643. &pSda->sda_Lock);
  644. // The user password as we have it is potentially padded with nulls
  645. // if it is less than 8 chars. Get the length right
  646. NewPwd.Length = strlen(NewPwd.Buffer) + 1;
  647. Status = AfpLogonUser(pSda, &NewPwd);
  648. if (Status == AFP_ERR_NONE)
  649. {
  650. AfpInterlockedSetDword(&pSda->sda_Flags,
  651. SDA_USER_LOGGEDIN,
  652. &pSda->sda_Lock);
  653. pSda->sda_WSName.Length = 0;
  654. pSda->sda_WSName.MaximumLength = 0;
  655. pSda->sda_WSName.Buffer = NULL;
  656. if (pSda->sda_tTillKickOff < MAXLONG)
  657. AfpScavengerScheduleEvent(
  658. AfpSdaCheckSession,
  659. (PVOID)((ULONG_PTR)(pSda->sda_SessionId)),
  660. (pSda->sda_tTillKickOff > SESSION_WARN_TIME) ?
  661. (pSda->sda_tTillKickOff - SESSION_WARN_TIME) :
  662. SESSION_CHECK_TIME,
  663. True);
  664. }
  665. }
  666. }
  667. else // Failure - convert to right status code
  668. {
  669. if ((pSda->sda_ClientType == SDA_CLIENT_MSUAM_V1) ||
  670. (pSda->sda_ClientType == SDA_CLIENT_MSUAM_V2))
  671. {
  672. if (Status == STATUS_PASSWORD_EXPIRED)
  673. Status = AFP_ERR_PASSWORD_EXPIRED;
  674. else if (Status == STATUS_ACCOUNT_DISABLED)
  675. Status = AFP_ERR_ACCOUNT_DISABLED;
  676. else if (Status == STATUS_INVALID_LOGON_HOURS)
  677. Status = AFP_ERR_INVALID_LOGON_HOURS;
  678. else if (Status == STATUS_INVALID_WORKSTATION)
  679. Status = AFP_ERR_INVALID_WORKSTATION;
  680. else if (Status == STATUS_PASSWORD_RESTRICTION)
  681. Status = AFP_ERR_PASSWORD_RESTRICTED;
  682. else if (Status == STATUS_PWD_TOO_SHORT)
  683. Status = AFP_ERR_PASSWORD_TOO_SHORT;
  684. else if (Status == STATUS_ACCOUNT_RESTRICTION)
  685. Status = AFP_ERR_ACCOUNT_RESTRICTED;
  686. else if (Status == STATUS_ACCESS_DENIED)
  687. Status = AFP_ERR_PASSWORD_CANT_CHANGE;
  688. else if ((Status != AFP_ERR_BAD_UAM) &&
  689. (Status != AFP_ERR_PARAM))
  690. Status = AFP_ERR_MISC;
  691. }
  692. else
  693. {
  694. if (Status == STATUS_WRONG_PASSWORD)
  695. Status = AFP_ERR_USER_NOT_AUTH;
  696. else if ((Status == STATUS_PASSWORD_RESTRICTION) ||
  697. (Status == STATUS_ACCOUNT_DISABLED))
  698. Status = AFP_ERR_ACCESS_DENIED;
  699. else if (Status == STATUS_PWD_TOO_SHORT)
  700. {
  701. if ((pSda->sda_Flags & SDA_USER_LOGGEDIN) &&
  702. (pSda->sda_ClientVersion >= AFP_VER_21))
  703. {
  704. Status = AFP_ERR_PWD_TOO_SHORT;
  705. }
  706. else
  707. Status = AFP_ERR_ACCESS_DENIED;
  708. }
  709. else if ((Status == STATUS_NONE_MAPPED) ||
  710. (Status == STATUS_NO_SUCH_USER))
  711. Status = AFP_ERR_PARAM;
  712. else if ((Status != AFP_ERR_BAD_UAM) &&
  713. (Status != AFP_ERR_PARAM))
  714. Status = AFP_ERR_MISC;
  715. }
  716. }
  717. if (pPwdDesc)
  718. {
  719. AfpFreeMemory(pPwdDesc);
  720. }
  721. return Status;
  722. }
  723. /*** AfpFspDispMapName
  724. *
  725. * This is the worker routine for the AfpMapName API.
  726. *
  727. * The request packet is represented below.
  728. *
  729. * sda_SubFunc BYTE User/Group Flag
  730. * sda_Name1 ANSI_STRING Name of user/group
  731. */
  732. AFPSTATUS FASTCALL
  733. AfpFspDispMapName(
  734. IN PSDA pSda
  735. )
  736. {
  737. AFPSTATUS Status = AFP_ERR_NONE;
  738. UNICODE_STRING Us;
  739. DWORD UserOrGroupId = 0;
  740. struct _ResponsePacket
  741. {
  742. BYTE __UserOrGroupId[4];
  743. };
  744. PAGED_CODE( );
  745. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  746. ("AfpFspDispMapName: Entered\n"));
  747. if ((pSda->sda_AfpSubFunc != MAP_USER_NAME) &&
  748. (pSda->sda_AfpSubFunc != MAP_GROUP_NAME))
  749. return AFP_ERR_PARAM;
  750. AfpSetEmptyUnicodeString(&Us, 0, NULL);
  751. // If this is the first time we are asking for the name to be translated.
  752. if ((pSda->sda_Name1.Length != 0) &&
  753. (pSda->sda_SecUtilSid == NULL) &&
  754. (NT_SUCCESS(pSda->sda_SecUtilResult)))
  755. {
  756. Us.MaximumLength = (pSda->sda_Name1.Length + 1) * sizeof(WCHAR);
  757. if ((Us.Buffer = (LPWSTR)AfpAllocPagedMemory(Us.MaximumLength)) == NULL)
  758. {
  759. return AFP_ERR_MISC;
  760. }
  761. if (!NT_SUCCESS(Status = AfpConvertStringToUnicode(&pSda->sda_Name1, &Us)))
  762. {
  763. AfpFreeMemory(Us.Buffer);
  764. return AFP_ERR_MISC;
  765. }
  766. Status = AfpNameToSid( pSda, &Us );
  767. AfpFreeMemory(Us.Buffer);
  768. if (!NT_SUCCESS(Status))
  769. {
  770. if (Status != AFP_ERR_EXTENDED)
  771. Status = AFP_ERR_MISC;
  772. }
  773. return Status;
  774. }
  775. // If we have successfully translated the name
  776. if (pSda->sda_Name1.Length != 0)
  777. {
  778. if ((pSda->sda_SecUtilSid != NULL) &&
  779. (NT_SUCCESS( pSda->sda_SecUtilResult)))
  780. Status = AfpSidToMacId(pSda->sda_SecUtilSid, &UserOrGroupId);
  781. else Status = AFP_ERR_ITEM_NOT_FOUND;
  782. }
  783. if (NT_SUCCESS(Status))
  784. {
  785. pSda->sda_ReplySize = SIZE_RESPPKT;
  786. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  787. {
  788. PUTDWORD2DWORD(pRspPkt->__UserOrGroupId, UserOrGroupId);
  789. }
  790. }
  791. if (pSda->sda_SecUtilSid != NULL)
  792. {
  793. AfpFreeMemory(pSda->sda_SecUtilSid);
  794. pSda->sda_SecUtilSid = NULL;
  795. }
  796. return Status;
  797. }
  798. /*** AfpFspDispMapId
  799. *
  800. * This is the worker routine for the AfpMapId API.
  801. *
  802. * The request packet is represented below.
  803. *
  804. * sda_SubFunc BYTE User/Group Flag
  805. * sda_ReqBlock DWORD UserId
  806. *
  807. * We do not use the UserId field since it is invalid anyway !!
  808. */
  809. AFPSTATUS FASTCALL
  810. AfpFspDispMapId(
  811. IN PSDA pSda
  812. )
  813. {
  814. AFPSTATUS Status = AFP_ERR_NONE;
  815. PAFP_SID_NAME pSidName = NULL;
  816. PSID pSid; // Sid of user or group
  817. struct _RequestPacket
  818. {
  819. DWORD _UserOrGroupId;
  820. };
  821. struct _ResponsePacket
  822. {
  823. BYTE __NameLength[1];
  824. BYTE __Name[1];
  825. };
  826. PAGED_CODE( );
  827. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  828. ("AfpFspDispMapId: Entered\n"));
  829. if ((pSda->sda_AfpSubFunc != MAP_USER_ID) &&
  830. (pSda->sda_AfpSubFunc != MAP_GROUP_ID))
  831. return AFP_ERR_PARAM;
  832. Status = AFP_ERR_ITEM_NOT_FOUND; // Assume failure
  833. if (NT_SUCCESS(pSda->sda_SecUtilResult)) do
  834. {
  835. ANSI_STRING As;
  836. As.Length = 0;
  837. As.MaximumLength = 1;
  838. As.Buffer = "";
  839. if (pReqPkt->_UserOrGroupId != 0)
  840. {
  841. Status = AfpMacIdToSid(pReqPkt->_UserOrGroupId, &pSid);
  842. if (!NT_SUCCESS(Status))
  843. {
  844. Status = AFP_ERR_ITEM_NOT_FOUND;
  845. break;
  846. }
  847. Status = AfpSidToName(pSda, pSid, &pSidName);
  848. if (!NT_SUCCESS(Status))
  849. {
  850. if (Status != AFP_ERR_EXTENDED)
  851. Status = AFP_ERR_MISC;
  852. break;
  853. }
  854. /* MSKK hideyukn, Unicode char length not eqaul to ansi byte length in DBCS, 08/07/95 */
  855. #ifdef DBCS
  856. pSda->sda_ReplySize = pSidName->Name.Length + SIZE_RESPPKT;
  857. #else
  858. pSda->sda_ReplySize = pSidName->Name.Length/sizeof(WCHAR) + SIZE_RESPPKT;
  859. #endif // DBCS
  860. }
  861. else pSda->sda_ReplySize = SIZE_RESPPKT; // For an id of 0
  862. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  863. {
  864. if (pSidName != NULL)
  865. {
  866. As.MaximumLength = pSda->sda_ReplySize - 1;
  867. As.Buffer = pRspPkt->__Name;
  868. if ((Status = AfpConvertStringToAnsi(&pSidName->Name, &As)) != AFP_ERR_NONE)
  869. {
  870. AfpFreeReplyBuf(pSda, FALSE);
  871. }
  872. PUTBYTE2BYTE(pRspPkt->__NameLength, As.Length);
  873. }
  874. else PUTBYTE2BYTE(pRspPkt->__NameLength, 0);
  875. }
  876. } while (False);
  877. return Status;
  878. }
  879. /*** AfpFspDispGetUserInfo
  880. *
  881. * This routine implements the AfpGetUserInfo API.
  882. *
  883. * The request packet is represented below.
  884. *
  885. * sda_AfpSubFunc BYTE ThisUser flag
  886. * sda_ReqBlock DWORD UserId
  887. * sda_ReqBlock DWORD Bitmap
  888. *
  889. * We do not use the UserId field since it is invalid anyway !!
  890. */
  891. AFPSTATUS FASTCALL
  892. AfpFspDispGetUserInfo(
  893. IN PSDA pSda
  894. )
  895. {
  896. DWORD Bitmap;
  897. PBYTE pTemp;
  898. AFPSTATUS Status = AFP_ERR_PARAM;
  899. DWORD Uid, Gid;
  900. struct _RequestPacket
  901. {
  902. DWORD _UserId;
  903. DWORD _Bitmap;
  904. };
  905. struct _ResponsePacket
  906. {
  907. BYTE __Bitmap[2];
  908. BYTE __Id1[4];
  909. BYTE __Id2[4];
  910. };
  911. PAGED_CODE( );
  912. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  913. ("AfpFspDispGetUserInfo: Entered\n"));
  914. do
  915. {
  916. if (!(pSda->sda_AfpSubFunc & USERINFO_THISUSER))
  917. break;
  918. Bitmap = pReqPkt->_Bitmap;
  919. if (Bitmap & ~(USERINFO_BITMAP_USERID | USERINFO_BITMAP_PRIGID))
  920. {
  921. Status = AFP_ERR_BITMAP;
  922. break;
  923. }
  924. if (Bitmap & USERINFO_BITMAP_USERID)
  925. {
  926. if (!NT_SUCCESS(Status = AfpSidToMacId(pSda->sda_UserSid, &Uid)))
  927. {
  928. Status = AFP_ERR_MISC;
  929. break;
  930. }
  931. }
  932. if (Bitmap & USERINFO_BITMAP_PRIGID)
  933. {
  934. if (!NT_SUCCESS(Status = AfpSidToMacId(pSda->sda_GroupSid, &Gid)))
  935. {
  936. Status = AFP_ERR_MISC;
  937. break;
  938. }
  939. }
  940. pSda->sda_ReplySize = SIZE_RESPPKT;
  941. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  942. {
  943. PUTSHORT2SHORT(pRspPkt->__Bitmap, Bitmap);
  944. pTemp = pRspPkt->__Id1;
  945. if (Bitmap & USERINFO_BITMAP_USERID)
  946. {
  947. PUTDWORD2DWORD(pTemp, Uid);
  948. pTemp = pRspPkt->__Id2;
  949. }
  950. else pSda->sda_ReplySize -= sizeof(DWORD);
  951. if (Bitmap & USERINFO_BITMAP_PRIGID)
  952. {
  953. PUTDWORD2DWORD(pTemp, Gid);
  954. }
  955. else pSda->sda_ReplySize -= sizeof(DWORD);
  956. }
  957. } while (False);
  958. return Status;
  959. }
  960. /*** afpGetUserNameAndPwdOrWSName
  961. *
  962. * Unmarshall the block containing UserName and either password or WS Name
  963. * into unicode/ansi strings. Allocate memory for the output strings.
  964. *
  965. * The layout of the Buffer is as follows:
  966. * User Name and an optional pad
  967. * Workstation name or user password depending on the UAM.
  968. *
  969. * The optional pad is not directly determined since this buffer has been
  970. * copied and we do not know at this point whether this started at an odd
  971. * or an even boundary. We get to it indirectly from the size.
  972. */
  973. LOCAL BOOLEAN
  974. afpGetUserNameAndPwdOrWSName(
  975. IN PANSI_STRING Block,
  976. IN BYTE ClientType,
  977. OUT PUNICODE_STRING pUserName,
  978. OUT PUNICODE_STRING pDomainName,
  979. OUT PVOID pParm // Either password or WSName
  980. )
  981. {
  982. ANSI_STRING UserName;
  983. #define pPwd ((PANSI_STRING)pParm)
  984. #define pWS ((PUNICODE_STRING)pParm)
  985. PBYTE pTmp;
  986. BOOLEAN RetCode = False;
  987. PAGED_CODE( );
  988. do
  989. {
  990. pPwd->Buffer = NULL;
  991. pPwd->Length = 0;
  992. pUserName->Buffer = NULL;
  993. if (Block->Buffer == NULL)
  994. {
  995. ASSERT(0);
  996. return(False);
  997. }
  998. pTmp = Block->Buffer;
  999. UserName.Length = (USHORT)*pTmp;
  1000. UserName.Buffer = ++pTmp;
  1001. // Sanity check
  1002. if ((USHORT)(UserName.Length + 1) > Block->Length)
  1003. break;
  1004. pTmp += UserName.Length;
  1005. // make sure we are within bounds!
  1006. if (pTmp <= (Block->Buffer + Block->Length))
  1007. {
  1008. // If there is a NULL pad, go past it.
  1009. if (*pTmp == '\0')
  1010. pTmp++;
  1011. }
  1012. pUserName->Buffer = NULL; // Force allocation
  1013. pDomainName->Buffer = NULL; // Force allocation
  1014. if (!afpGetNameAndDomain(&UserName, pUserName, pDomainName))
  1015. break;
  1016. // Make sure we do not have a name of the form "DOMAIN\" i.e. a
  1017. // valid domain name and a NULL user name, disallow that explicitly
  1018. // so that we don't logon such users with a NULL session
  1019. if (pUserName->Length == 0)
  1020. {
  1021. if (pUserName->Buffer != NULL)
  1022. {
  1023. AfpFreeMemory(pUserName->Buffer);
  1024. pUserName->Buffer = NULL;
  1025. }
  1026. if (pDomainName->Buffer != NULL)
  1027. {
  1028. AfpFreeMemory(pDomainName->Buffer);
  1029. pDomainName->Buffer = NULL;
  1030. }
  1031. return False;
  1032. }
  1033. // The balance of the buffer is the block, if it is a password. Else
  1034. // it is the machine name string which is a PASCALSTR.
  1035. pPwd->MaximumLength = (USHORT)(Block->Length - (pTmp - Block->Buffer) + 1);
  1036. if (ClientType != SDA_CLIENT_CLEARTEXT)
  1037. {
  1038. // in case of Apple UAM (scrambled or 2-way), machine name won't
  1039. // be present, so check only for MS-UAM
  1040. //
  1041. if ((ClientType == SDA_CLIENT_MSUAM_V1) ||
  1042. (ClientType == SDA_CLIENT_MSUAM_V2))
  1043. {
  1044. pWS->MaximumLength = (USHORT)((*pTmp + 1) * sizeof(WCHAR));
  1045. if (pWS->MaximumLength < (USHORT)((Block->Length -
  1046. (pTmp - Block->Buffer + 1)) *sizeof(WCHAR)))
  1047. {
  1048. return False;
  1049. }
  1050. }
  1051. else
  1052. {
  1053. pWS->MaximumLength = ((sizeof(AFP_DEFAULT_WORKSTATION_A) + 1) *
  1054. sizeof(WCHAR));
  1055. }
  1056. }
  1057. if ((pPwd->Buffer = AfpAllocNonPagedMemory(pPwd->MaximumLength)) == NULL)
  1058. break;
  1059. if (ClientType == SDA_CLIENT_CLEARTEXT)
  1060. {
  1061. // We are dealing with a clear text password
  1062. pPwd->Length = pPwd->MaximumLength - 1;
  1063. RtlCopyMemory(pPwd->Buffer, pTmp, pPwd->Length);
  1064. if (AfpConvertMacAnsiToHostAnsi(pPwd) != AFP_ERR_NONE)
  1065. break;
  1066. pPwd->Buffer[pPwd->Length] = 0;
  1067. }
  1068. else
  1069. {
  1070. ANSI_STRING AS;
  1071. if ((ClientType == SDA_CLIENT_MSUAM_V1) ||
  1072. (ClientType == SDA_CLIENT_MSUAM_V2))
  1073. {
  1074. AS.Buffer = ++pTmp;
  1075. AS.MaximumLength = pWS->MaximumLength/sizeof(WCHAR);
  1076. AS.Length = AS.MaximumLength - 1;
  1077. }
  1078. //
  1079. // for scrambled and 2-way exchange, use default wksta name since
  1080. // we don't know what it is
  1081. //
  1082. else
  1083. {
  1084. AS.Buffer = AFP_DEFAULT_WORKSTATION_A;
  1085. AS.MaximumLength = pWS->MaximumLength/sizeof(WCHAR);
  1086. AS.Length = AS.MaximumLength - 1;
  1087. }
  1088. // We have potentially a workstation name here. Since this is a
  1089. // pascal string, adjust the length etc.
  1090. AfpConvertStringToUnicode(&AS, pWS);
  1091. pWS->Buffer[pWS->Length/sizeof(WCHAR)] = L'\0';
  1092. }
  1093. RetCode = True;
  1094. } while (False);
  1095. if (!RetCode)
  1096. {
  1097. if (pUserName->Buffer != NULL)
  1098. {
  1099. AfpFreeMemory(pUserName->Buffer);
  1100. pUserName->Buffer = NULL;
  1101. }
  1102. if (pPwd->Buffer != NULL)
  1103. {
  1104. AfpFreeMemory(pPwd->Buffer);
  1105. pPwd->Buffer = NULL;
  1106. }
  1107. if (pDomainName->Buffer != NULL)
  1108. {
  1109. AfpFreeMemory(pDomainName->Buffer);
  1110. pDomainName->Buffer = NULL;
  1111. }
  1112. }
  1113. return RetCode;
  1114. }
  1115. /*** afpGetNameAndDomain
  1116. *
  1117. * Extract the name and domain from a string formed as DOMAIN\NAME.
  1118. */
  1119. BOOLEAN
  1120. afpGetNameAndDomain(
  1121. IN PANSI_STRING pDomainNUser,
  1122. OUT PUNICODE_STRING pUserName,
  1123. OUT PUNICODE_STRING pDomainName
  1124. )
  1125. {
  1126. BYTE c;
  1127. ANSI_STRING User, Domain;
  1128. BOOLEAN fDomainBuffAlloc=FALSE;
  1129. // Check if the user name has a '\' character in it. If it does,
  1130. // seperate the domain name from user name. The Username string is
  1131. // not ASCIIZ. Before we search for a '\', make it ASCIIZ w/o trashing
  1132. // whatever is there.
  1133. PAGED_CODE( );
  1134. User.Buffer = AfpStrChr(pDomainNUser->Buffer, pDomainNUser->Length, '\\');
  1135. if (User.Buffer != NULL)
  1136. {
  1137. (User.Buffer) ++; // Past the '\'
  1138. Domain.Buffer = pDomainNUser->Buffer;
  1139. Domain.Length = (USHORT)(User.Buffer - Domain.Buffer - 1);
  1140. User.Length = pDomainNUser->Length - Domain.Length - 1;
  1141. if (Domain.Length > DNLEN)
  1142. {
  1143. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_ERR,
  1144. ("afpGetNameAndDomain: domain name too long (%d vs. max %d): rejecting\n",
  1145. Domain.Length, DNLEN));
  1146. return(False);
  1147. }
  1148. Domain.MaximumLength = Domain.Length + 1;
  1149. pDomainName->MaximumLength = Domain.MaximumLength * sizeof(WCHAR);
  1150. if (pDomainName->Buffer == NULL)
  1151. {
  1152. if ((pDomainName->Buffer =
  1153. (PWSTR)AfpAllocNonPagedMemory(pDomainName->MaximumLength)) == NULL)
  1154. {
  1155. return False;
  1156. }
  1157. fDomainBuffAlloc = TRUE;
  1158. }
  1159. AfpConvertStringToUnicode(&Domain, pDomainName);
  1160. }
  1161. else User = *pDomainNUser;
  1162. if (User.Length > LM20_UNLEN)
  1163. {
  1164. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_ERR,
  1165. ("afpGetNameAndDomain: user name too long (%d vs. max %d): rejecting\n",
  1166. User.Length,LM20_UNLEN));
  1167. return(False);
  1168. }
  1169. User.MaximumLength = User.Length + 1;
  1170. pUserName->MaximumLength = User.MaximumLength * sizeof(WCHAR);
  1171. if ((pUserName->Buffer == NULL) &&
  1172. (pUserName->Buffer =
  1173. (PWSTR)AfpAllocNonPagedMemory(pUserName->MaximumLength)) == NULL)
  1174. {
  1175. if (fDomainBuffAlloc)
  1176. {
  1177. AfpFreeMemory(pDomainName->Buffer);
  1178. pDomainName->Buffer = NULL;
  1179. }
  1180. return False;
  1181. }
  1182. AfpConvertStringToUnicode(&User, pUserName);
  1183. return True;
  1184. }