SessionSetupHelper.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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. string osVersion = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string;
  32. state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), NTStatus: {4}", userName, domainName, machineName, osVersion, status);
  33. return new ErrorResponse(request.CommandName, status);
  34. }
  35. if (outputToken != null)
  36. {
  37. response.SecurityBuffer = outputToken;
  38. }
  39. // According to [MS-SMB2] 3.3.5.5.3, response.Header.SessionID must be allocated if the server returns STATUS_MORE_PROCESSING_REQUIRED
  40. if (request.Header.SessionID == 0)
  41. {
  42. ulong? sessionID = state.AllocateSessionID();
  43. if (!sessionID.HasValue)
  44. {
  45. return new ErrorResponse(request.CommandName, NTStatus.STATUS_TOO_MANY_SESSIONS);
  46. }
  47. response.Header.SessionID = sessionID.Value;
  48. }
  49. if (status == NTStatus.SEC_I_CONTINUE_NEEDED)
  50. {
  51. response.Header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED;
  52. }
  53. else // status == STATUS_SUCCESS
  54. {
  55. string userName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string;
  56. string domainName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string;
  57. string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string;
  58. string osVersion = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string;
  59. byte[] sessionKey = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.SessionKey) as byte[];
  60. object accessToken = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.AccessToken);
  61. bool? isGuest = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.IsGuest) as bool?;
  62. if (!isGuest.HasValue || !isGuest.Value)
  63. {
  64. state.LogToServer(Severity.Information, "Session Setup: User '{0}' authenticated successfully (Domain: '{1}', Workstation: '{2}', OS version: '{3}').", userName, domainName, machineName, osVersion);
  65. state.CreateSession(request.Header.SessionID, userName, machineName, sessionKey, accessToken);
  66. }
  67. else
  68. {
  69. state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), logged in as guest.", userName, domainName, machineName, osVersion);
  70. state.CreateSession(request.Header.SessionID, "Guest", machineName, sessionKey, accessToken);
  71. response.SessionFlags = SessionFlags.IsGuest;
  72. }
  73. }
  74. return response;
  75. }
  76. }
  77. }