SessionSetupHelper.cs 4.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /* Copyright (C) 2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using SMBLibrary.Authentication.GSSAPI;
  10. using SMBLibrary.Authentication.NTLM;
  11. using SMBLibrary.SMB2;
  12. using Utilities;
  13. namespace SMBLibrary.Server.SMB2
  14. {
  15. /// <summary>
  16. /// Session Setup helper
  17. /// </summary>
  18. internal class SessionSetupHelper
  19. {
  20. internal static SMB2Command GetSessionSetupResponse(SessionSetupRequest request, GSSProvider securityProvider, SMB2ConnectionState state)
  21. {
  22. // [MS-SMB2] Windows [..] will also accept raw Kerberos messages and implicit NTLM messages as part of GSS authentication.
  23. SessionSetupResponse response = new SessionSetupResponse();
  24. byte[] outputToken;
  25. NTStatus status = securityProvider.AcceptSecurityContext(ref state.AuthenticationContext, request.SecurityBuffer, out outputToken);
  26. if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.SEC_I_CONTINUE_NEEDED)
  27. {
  28. string userName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string;
  29. string domainName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string;
  30. string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string;
  31. state.LogToServer(Severity.Information, "User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}'), NTStatus: {3}", userName, domainName, machineName, status);
  32. return new ErrorResponse(request.CommandName, status);
  33. }
  34. if (outputToken != null)
  35. {
  36. response.SecurityBuffer = outputToken;
  37. }
  38. // According to [MS-SMB2] 3.3.5.5.3, response.Header.SessionID must be allocated if the server returns STATUS_MORE_PROCESSING_REQUIRED
  39. if (request.Header.SessionID == 0)
  40. {
  41. ulong? sessionID = state.AllocateSessionID();
  42. if (!sessionID.HasValue)
  43. {
  44. return new ErrorResponse(request.CommandName, NTStatus.STATUS_TOO_MANY_SESSIONS);
  45. }
  46. response.Header.SessionID = sessionID.Value;
  47. }
  48. if (status == NTStatus.SEC_I_CONTINUE_NEEDED)
  49. {
  50. response.Header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED;
  51. }
  52. else // status == STATUS_SUCCESS
  53. {
  54. string userName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string;
  55. string domainName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string;
  56. string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string;
  57. byte[] sessionKey = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.SessionKey) as byte[];
  58. object accessToken = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.AccessToken);
  59. bool? isGuest = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.IsGuest) as bool?;
  60. if (!isGuest.HasValue || !isGuest.Value)
  61. {
  62. state.LogToServer(Severity.Information, "User '{0}' authenticated successfully (Domain: '{1}', Workstation: '{2}').", userName, domainName, machineName);
  63. state.CreateSession(request.Header.SessionID, userName, machineName, sessionKey, accessToken);
  64. }
  65. else
  66. {
  67. state.LogToServer(Severity.Information, "User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}'), logged in as guest.", userName, domainName, machineName);
  68. state.CreateSession(request.Header.SessionID, "Guest", machineName, sessionKey, accessToken);
  69. response.SessionFlags = SessionFlags.IsGuest;
  70. }
  71. }
  72. return response;
  73. }
  74. }
  75. }