Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

560 lines
21 KiB

  1. /*++ BUILD Version: 0009 // Increment this if a change has global effects
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. sessetup.c
  5. Abstract:
  6. This module implements the Session setup related routines
  7. Author:
  8. Balan Sethu Raman (SethuR) 06-Mar-95 Created
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include <exsessup.h>
  13. #include "ntlsapi.h"
  14. #include "mrxsec.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, BuildSessionSetupSecurityInformation)
  17. #pragma alloc_text(PAGE, BuildTreeConnectSecurityInformation)
  18. #endif
  19. extern BOOLEAN EnablePlainTextPassword;
  20. extern BOOLEAN MRxSmbExtendedSignaturesEnabled;
  21. NTSTATUS
  22. BuildSessionSetupSecurityInformation(
  23. PSMB_EXCHANGE pExchange,
  24. PBYTE pSmbBuffer,
  25. PULONG pSmbBufferSize)
  26. /*++
  27. Routine Description:
  28. This routine builds the security related information for the session setup SMB
  29. Arguments:
  30. pServer - the server instance
  31. pSmbBuffer - the SMB buffer
  32. pSmbBufferSize - the size of the buffer on input ( modified to size remaining on
  33. output)
  34. Return Value:
  35. RXSTATUS - The return status for the operation
  36. Notes:
  37. Eventhough the genral structure of the code tries to isolate dialect specific issues
  38. as much as possible this routine takes the opposite approach. This is because of the
  39. preamble and prologue to security interaction which far outweigh the dialect specific
  40. work required to be done. Therefore in the interests of a smaller footprint this approach
  41. has been adopted.
  42. --*/
  43. {
  44. NTSTATUS Status = STATUS_SUCCESS;
  45. UNICODE_STRING UserName;
  46. UNICODE_STRING DomainName;
  47. STRING CaseSensitiveResponse;
  48. STRING CaseInsensitiveResponse;
  49. PVOID pSecurityBlob;
  50. USHORT SecurityBlobSize;
  51. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(pExchange);
  52. PSMBCE_SESSION pSession = SmbCeGetExchangeSession(pExchange);
  53. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  54. SECURITY_RESPONSE_CONTEXT ResponseContext;
  55. KAPC_STATE ApcState;
  56. BOOLEAN AttachToSystemProcess = FALSE;
  57. ULONG BufferSize = *pSmbBufferSize;
  58. PAGED_CODE();
  59. RxDbgTrace( +1, Dbg, ("BuildSessionSetupSecurityInformation -- Entry\n"));
  60. SmbLog(LOG,
  61. BuildSessionSetupSecurityInformation,
  62. LOGPTR(pSession)
  63. LOGULONG(pSession->LogonId.HighPart)
  64. LOGULONG(pSession->LogonId.LowPart));
  65. if ((pServer->DialectFlags & DF_EXTENDED_SECURITY) &&
  66. !FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  67. //
  68. // For uplevel servers, this gets handled all at once:
  69. //
  70. PREQ_NT_EXTENDED_SESSION_SETUP_ANDX pExtendedNtSessionSetupReq;
  71. PBYTE pBuffer = pSmbBuffer;
  72. // Position the buffer for copying the security blob
  73. pBuffer += FIELD_OFFSET(REQ_NT_EXTENDED_SESSION_SETUP_ANDX,Buffer);
  74. BufferSize -= FIELD_OFFSET(REQ_NT_EXTENDED_SESSION_SETUP_ANDX,Buffer);
  75. pExtendedNtSessionSetupReq = (PREQ_NT_EXTENDED_SESSION_SETUP_ANDX)pSmbBuffer;
  76. pSecurityBlob = pBuffer ;
  77. SecurityBlobSize = (USHORT) BufferSize ;
  78. Status = BuildExtendedSessionSetupResponsePrologue(
  79. pExchange,
  80. pSecurityBlob,
  81. &SecurityBlobSize,
  82. &ResponseContext);
  83. if ( NT_SUCCESS( Status ) )
  84. {
  85. SmbPutUshort(
  86. &pExtendedNtSessionSetupReq->SecurityBlobLength,
  87. SecurityBlobSize);
  88. BufferSize -= SecurityBlobSize;
  89. }
  90. } else {
  91. if (!MRxSmbUseKernelModeSecurity &&
  92. !FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  93. //NTRAID-455636-2/2/2000-yunlin We should consolidate three routines calling LSA into one
  94. Status = BuildExtendedSessionSetupResponsePrologueFake(pExchange);
  95. if (Status != STATUS_SUCCESS) {
  96. goto FINALLY;
  97. }
  98. }
  99. Status = BuildNtLanmanResponsePrologue(
  100. pExchange,
  101. &UserName,
  102. &DomainName,
  103. &CaseSensitiveResponse,
  104. &CaseInsensitiveResponse,
  105. &ResponseContext);
  106. if (Status == STATUS_SUCCESS) {
  107. // If the security package returns us the credentials corresponding to a
  108. // NULL session mark the session as a NULL session. This will avoid
  109. // conflicts with the user trying to present the credentials for a NULL
  110. // session, i.e., explicitly specified zero length passwords, user name
  111. // and domain name.
  112. RxDbgTrace(0,Dbg,("Session %lx UN Length %lx DN length %ld IR length %ld SR length %ld\n",
  113. pSession,UserName.Length,DomainName.Length,
  114. CaseInsensitiveResponse.Length,CaseSensitiveResponse.Length));
  115. if ((UserName.Length == 0) &&
  116. (DomainName.Length == 0) &&
  117. (CaseSensitiveResponse.Length == 0) &&
  118. (CaseInsensitiveResponse.Length == 1)) {
  119. RxDbgTrace(0,Dbg,("Implicit NULL session setup\n"));
  120. pSession->Flags |= SMBCE_SESSION_FLAGS_NULL_CREDENTIALS;
  121. pSession->SessionKeyState = SmbSessionKeyAvailible;
  122. } else {
  123. if( pServerEntry->SecuritySignaturesEnabled == TRUE &&
  124. pServerEntry->SecuritySignaturesActive == FALSE &&
  125. !FlagOn(pSession->Flags, SMBCE_SESSION_FLAGS_GUEST_SESSION)) {
  126. if (FlagOn(pSession->Flags, SMBCE_SESSION_FLAGS_LANMAN_SESSION_KEY_USED)) {
  127. UCHAR SessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  128. RtlZeroMemory(SessionKey, sizeof(SessionKey));
  129. RtlCopyMemory(SessionKey, pSession->LanmanSessionKey, MSV1_0_LANMAN_SESSION_KEY_LENGTH);
  130. SmbInitializeSmbSecuritySignature(pServer,
  131. SessionKey,
  132. CaseInsensitiveResponse.Buffer,
  133. CaseInsensitiveResponse.Length);
  134. } else{
  135. SmbInitializeSmbSecuritySignature(pServer,
  136. pSession->UserSessionKey,
  137. CaseSensitiveResponse.Buffer,
  138. CaseSensitiveResponse.Length);
  139. }
  140. if( MRxSmbExtendedSignaturesEnabled )
  141. {
  142. pSession->SessionKeyState = SmbSessionKeyAuthenticating;
  143. ClearFlag( pSession->Flags, SMBCE_SESSION_FLAGS_SESSION_KEY_HASHED );
  144. }
  145. else
  146. {
  147. pSession->SessionKeyState = SmbSessionKeyAvailible;
  148. }
  149. }
  150. else
  151. {
  152. pSession->SessionKeyState = SmbSessionKeyAvailible;
  153. }
  154. }
  155. }
  156. }
  157. if (NT_SUCCESS(Status)) {
  158. PBYTE pBuffer = pSmbBuffer;
  159. if (pServer->Dialect == NTLANMAN_DIALECT) {
  160. if (FlagOn(pServer->DialectFlags,DF_EXTENDED_SECURITY) &&
  161. !FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  162. //
  163. // Already done above
  164. //
  165. NOTHING ;
  166. } else {
  167. //PREQ_SESSION_SETUP_ANDX pSessionSetupReq = (PREQ_SESSION_SETUP_ANDX)pSmbBuffer;
  168. PREQ_NT_SESSION_SETUP_ANDX pNtSessionSetupReq = (PREQ_NT_SESSION_SETUP_ANDX)pSmbBuffer;
  169. // It it is a NT server both the case insensitive and case sensitive passwords
  170. // need to be copied. for share-level, just copy a token 1-byte NULL password
  171. // Position the buffer for copying the password.
  172. pBuffer += FIELD_OFFSET(REQ_NT_SESSION_SETUP_ANDX,Buffer);
  173. BufferSize -= FIELD_OFFSET(REQ_NT_SESSION_SETUP_ANDX,Buffer);
  174. SmbPutUlong(&pNtSessionSetupReq->Reserved,0);
  175. if (pServer->SecurityMode == SECURITY_MODE_USER_LEVEL){
  176. RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- NtUserPasswords\n"));
  177. if (pServer->EncryptPasswords) {
  178. SmbPutUshort(
  179. &pNtSessionSetupReq->CaseInsensitivePasswordLength,
  180. CaseInsensitiveResponse.Length);
  181. SmbPutUshort(
  182. &pNtSessionSetupReq->CaseSensitivePasswordLength,
  183. CaseSensitiveResponse.Length);
  184. Status = SmbPutString(
  185. &pBuffer,
  186. &CaseInsensitiveResponse,
  187. &BufferSize);
  188. if (NT_SUCCESS(Status)) {
  189. Status = SmbPutString(
  190. &pBuffer,
  191. &CaseSensitiveResponse,
  192. &BufferSize);
  193. }
  194. } else if (EnablePlainTextPassword) {
  195. if (pSession->pPassword != NULL) {
  196. if (FlagOn(pServer->DialectFlags,DF_UNICODE)) {
  197. PBYTE pTempBuffer = pBuffer;
  198. *pBuffer = 0;
  199. pBuffer = ALIGN_SMB_WSTR(pBuffer);
  200. BufferSize -= (ULONG)(pBuffer - pTempBuffer);
  201. SmbPutUshort(
  202. &pNtSessionSetupReq->CaseInsensitivePasswordLength,
  203. 0);
  204. SmbPutUshort(
  205. &pNtSessionSetupReq->CaseSensitivePasswordLength,
  206. pSession->pPassword->Length + 2);
  207. Status = SmbPutUnicodeString(
  208. &pBuffer,
  209. pSession->pPassword,
  210. &BufferSize);
  211. } else {
  212. SmbPutUshort(
  213. &pNtSessionSetupReq->CaseInsensitivePasswordLength,
  214. pSession->pPassword->Length/2 + 1);
  215. SmbPutUshort(
  216. &pNtSessionSetupReq->CaseSensitivePasswordLength,
  217. 0);
  218. Status = SmbPutUnicodeStringAsOemString(
  219. &pBuffer,
  220. pSession->pPassword,
  221. &BufferSize);
  222. }
  223. } else {
  224. SmbPutUshort(&pNtSessionSetupReq->CaseSensitivePasswordLength,0);
  225. SmbPutUshort(&pNtSessionSetupReq->CaseInsensitivePasswordLength,1);
  226. *pBuffer++ = '\0';
  227. BufferSize -= sizeof(CHAR);
  228. }
  229. } else {
  230. Status = STATUS_LOGIN_WKSTA_RESTRICTION;
  231. }
  232. } else {
  233. RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- NtSharePasswords\n"));
  234. SmbPutUshort(&pNtSessionSetupReq->CaseInsensitivePasswordLength, 1);
  235. SmbPutUshort(&pNtSessionSetupReq->CaseSensitivePasswordLength, 1);
  236. *pBuffer = 0;
  237. *(pBuffer+1) = 0;
  238. pBuffer += 2;
  239. BufferSize -= 2;
  240. }
  241. }
  242. } else {
  243. PREQ_SESSION_SETUP_ANDX pSessionSetupReq = (PREQ_SESSION_SETUP_ANDX)pSmbBuffer;
  244. // Position the buffer for copying the password.
  245. pBuffer += FIELD_OFFSET(REQ_SESSION_SETUP_ANDX,Buffer);
  246. BufferSize -= FIELD_OFFSET(REQ_SESSION_SETUP_ANDX,Buffer);
  247. if ( (pServer->SecurityMode == SECURITY_MODE_USER_LEVEL)
  248. && (CaseInsensitiveResponse.Length > 0)) {
  249. if (pServer->EncryptPasswords) {
  250. // For other lanman servers only the case insensitive password is required.
  251. SmbPutUshort(
  252. &pSessionSetupReq->PasswordLength,
  253. CaseInsensitiveResponse.Length);
  254. // Copy the password
  255. Status = SmbPutString(
  256. &pBuffer,
  257. &CaseInsensitiveResponse,
  258. &BufferSize);
  259. } else {
  260. if (EnablePlainTextPassword) {
  261. if (pSession->pPassword != NULL) {
  262. SmbPutUshort(
  263. &pSessionSetupReq->PasswordLength,
  264. pSession->pPassword->Length/2 + 1);
  265. Status = SmbPutUnicodeStringAsOemString(
  266. &pBuffer,
  267. pSession->pPassword,
  268. &BufferSize);
  269. } else {
  270. SmbPutUshort(&pSessionSetupReq->PasswordLength,1);
  271. *pBuffer++ = '\0';
  272. BufferSize -= sizeof(CHAR);
  273. }
  274. } else {
  275. Status = STATUS_LOGIN_WKSTA_RESTRICTION;
  276. }
  277. }
  278. } else {
  279. // Share level security. Send a null string for the password
  280. SmbPutUshort(&pSessionSetupReq->PasswordLength,1);
  281. *pBuffer++ = '\0';
  282. BufferSize -= sizeof(CHAR);
  283. }
  284. }
  285. // The User name and the domain name strings can be either copied from
  286. // the information returned in the request response or the information
  287. // that is already present in the session entry.
  288. if (NT_SUCCESS(Status) &&
  289. (!FlagOn(pServer->DialectFlags,DF_EXTENDED_SECURITY) ||
  290. FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION))) {
  291. if ((pServer->Dialect == NTLANMAN_DIALECT) &&
  292. (pServer->NtServer.NtCapabilities & CAP_UNICODE)) {
  293. // Copy the account/domain names as UNICODE strings
  294. PBYTE pTempBuffer = pBuffer;
  295. RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- account/domain as unicode\n"));
  296. *pBuffer = 0;
  297. pBuffer = ALIGN_SMB_WSTR(pBuffer);
  298. BufferSize -= (ULONG)(pBuffer - pTempBuffer);
  299. Status = SmbPutUnicodeString(
  300. &pBuffer,
  301. &UserName,
  302. &BufferSize);
  303. if (NT_SUCCESS(Status)) {
  304. Status = SmbPutUnicodeString(
  305. &pBuffer,
  306. &DomainName,
  307. &BufferSize);
  308. }
  309. } else {
  310. // Copy the account/domain names as ASCII strings.
  311. RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- account/domain as ascii\n"));
  312. Status = SmbPutUnicodeStringAsOemString(
  313. &pBuffer,
  314. &UserName,
  315. &BufferSize);
  316. if (NT_SUCCESS(Status)) {
  317. Status = SmbPutUnicodeStringAsOemString(
  318. &pBuffer,
  319. &DomainName,
  320. &BufferSize);
  321. }
  322. }
  323. }
  324. if (NT_SUCCESS(Status)) {
  325. *pSmbBufferSize = BufferSize;
  326. }
  327. }
  328. // Free the buffer allocated by the security package.
  329. if ((pServer->DialectFlags & DF_EXTENDED_SECURITY) &&
  330. !FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  331. BuildExtendedSessionSetupResponseEpilogue(&ResponseContext);
  332. } else {
  333. BuildNtLanmanResponseEpilogue(pExchange, &ResponseContext);
  334. }
  335. // Detach from the rdr process.
  336. FINALLY:
  337. RxDbgTrace( -1, Dbg, ("BuildSessionSetupSecurityInformation -- Exit, status=%08lx\n",Status));
  338. return Status;
  339. }
  340. NTSTATUS
  341. BuildTreeConnectSecurityInformation(
  342. PSMB_EXCHANGE pExchange,
  343. PBYTE pBuffer,
  344. PBYTE pPasswordLength,
  345. PULONG pSmbBufferSize)
  346. /*++
  347. Routine Description:
  348. This routine builds the security related information for the session setup SMB
  349. Arguments:
  350. pServer - the server instance
  351. pLogonId - the logon id. for which the session is being setup
  352. pPassword - the user supplied password if any
  353. pBuffer - the password buffer
  354. pPasswordLength - where the password length is to be stored
  355. pSmbBufferSize - the size of the buffer on input ( modified to size remaining on
  356. output)
  357. Return Value:
  358. NTSTATUS - The return status for the operation
  359. Notes:
  360. Eventhough the genral structure of the code tries to isolate dialect specific issues
  361. as much as possible this routine takes the opposite approach. This is because of the
  362. preamble and prologue to security interaction which far outweigh the dialect specific
  363. work required to be done. Therefore in the interests of a smaller footprint this approach
  364. has been adopted.
  365. --*/
  366. {
  367. NTSTATUS FinalStatus,Status;
  368. UNICODE_STRING UserName,DomainName;
  369. STRING CaseSensitiveChallengeResponse,CaseInsensitiveChallengeResponse;
  370. SECURITY_RESPONSE_CONTEXT ResponseContext;
  371. ULONG PasswordLength = 0;
  372. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(pExchange);
  373. PSMBCE_SESSION pSession = SmbCeGetExchangeSession(pExchange);
  374. KAPC_STATE ApcState;
  375. BOOLEAN AttachToSystemProcess = FALSE;
  376. PAGED_CODE();
  377. Status = STATUS_SUCCESS;
  378. if (pServer->EncryptPasswords) {
  379. Status = BuildNtLanmanResponsePrologue(
  380. pExchange,
  381. &UserName,
  382. &DomainName,
  383. &CaseSensitiveChallengeResponse,
  384. &CaseInsensitiveChallengeResponse,
  385. &ResponseContext);
  386. if (NT_SUCCESS(Status)) {
  387. if (FlagOn(pServer->DialectFlags,DF_MIXEDCASEPW)) {
  388. RxDbgTrace( 0, Dbg, ("BuildTreeConnectSecurityInformation -- case sensitive password\n"));
  389. // Copy the password length onto the SMB buffer
  390. PasswordLength = CaseSensitiveChallengeResponse.Length;
  391. // Copy the password
  392. Status = SmbPutString(
  393. &pBuffer,
  394. &CaseSensitiveChallengeResponse,
  395. pSmbBufferSize);
  396. } else {
  397. RxDbgTrace( 0, Dbg, ("BuildTreeConnectSecurityInformation -- case insensitive password\n"));
  398. // Copy the password length onto the SMB buffer
  399. PasswordLength = CaseInsensitiveChallengeResponse.Length;
  400. // Copy the password
  401. Status = SmbPutString(
  402. &pBuffer,
  403. &CaseInsensitiveChallengeResponse,
  404. pSmbBufferSize);
  405. }
  406. BuildNtLanmanResponseEpilogue(pExchange, &ResponseContext);
  407. }
  408. } else {
  409. if (pSession->pPassword == NULL) {
  410. // The logon password cannot be sent as plain text. Send a Null string as password.
  411. PasswordLength = 1;
  412. if (*pSmbBufferSize >= 1) {
  413. *((PCHAR)pBuffer) = '\0';
  414. pBuffer += sizeof(CHAR);
  415. Status = STATUS_SUCCESS;
  416. } else {
  417. Status = STATUS_BUFFER_OVERFLOW;
  418. }
  419. } else {
  420. if (EnablePlainTextPassword) {
  421. OEM_STRING OemString;
  422. OemString.Length = OemString.MaximumLength = (USHORT)(*pSmbBufferSize - sizeof(CHAR));
  423. OemString.Buffer = pBuffer;
  424. Status = RtlUnicodeStringToOemString(
  425. &OemString,
  426. pSession->pPassword,
  427. FALSE);
  428. if (NT_SUCCESS(Status)) {
  429. PasswordLength = OemString.Length+1;
  430. }
  431. } else {
  432. Status = STATUS_LOGON_FAILURE;
  433. }
  434. }
  435. // reduce the byte count
  436. *pSmbBufferSize -= PasswordLength;
  437. }
  438. SmbPutUshort(pPasswordLength,(USHORT)PasswordLength);
  439. return Status;
  440. }