SimpleProtectedNegotiationToken.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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 System.Text;
  10. using Utilities;
  11. namespace SMBLibrary.Authentication.GSSAPI
  12. {
  13. public abstract class SimpleProtectedNegotiationToken
  14. {
  15. public const byte ApplicationTag = 0x60;
  16. public static readonly byte[] SPNEGOIdentifier = new byte[] { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02 };
  17. public abstract byte[] GetBytes();
  18. /// <param name="includeHeader">Prepend the generic GSSAPI header. Required for negTokenInit, optional for negTokenResp.</param>
  19. public byte[] GetBytes(bool includeHeader)
  20. {
  21. byte[] tokenBytes = this.GetBytes();
  22. if (includeHeader)
  23. {
  24. int objectIdentifierFieldSize = DerEncodingHelper.GetLengthFieldSize(SPNEGOIdentifier.Length);
  25. int tokenLength = 1 + objectIdentifierFieldSize + SPNEGOIdentifier.Length + tokenBytes.Length;
  26. int tokenLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(tokenLength);
  27. int headerLength = 1 + tokenLengthFieldSize + 1 + objectIdentifierFieldSize + SPNEGOIdentifier.Length;
  28. byte[] buffer = new byte[headerLength + tokenBytes.Length];
  29. int offset = 0;
  30. ByteWriter.WriteByte(buffer, ref offset, ApplicationTag);
  31. DerEncodingHelper.WriteLength(buffer, ref offset, tokenLength);
  32. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ObjectIdentifier);
  33. DerEncodingHelper.WriteLength(buffer, ref offset, SPNEGOIdentifier.Length);
  34. ByteWriter.WriteBytes(buffer, ref offset, SPNEGOIdentifier);
  35. ByteWriter.WriteBytes(buffer, ref offset, tokenBytes);
  36. return buffer;
  37. }
  38. else
  39. {
  40. return tokenBytes;
  41. }
  42. }
  43. /// <summary>
  44. /// https://tools.ietf.org/html/rfc2743
  45. /// </summary>
  46. /// <exception cref="System.IO.InvalidDataException"></exception>
  47. public static SimpleProtectedNegotiationToken ReadToken(byte[] tokenBytes, int offset)
  48. {
  49. byte tag = ByteReader.ReadByte(tokenBytes, ref offset);
  50. if (tag == ApplicationTag)
  51. {
  52. // https://msdn.microsoft.com/en-us/library/ms995330.aspx
  53. // when an InitToken is sent, it is prepended by an Application Constructed Object specifier (0x60),
  54. // and the OID for SPNEGO. This is the generic GSSAPI header.
  55. // [RFC 2743] The use of the Mechanism-Independent Token Format is required for initial context
  56. // establishment tokens, use in non-initial tokens is optional.
  57. int tokenLength = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
  58. tag = ByteReader.ReadByte(tokenBytes, ref offset);
  59. if (tag == (byte)DerEncodingTag.ObjectIdentifier)
  60. {
  61. int objectIdentifierLength = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
  62. byte[] objectIdentifier = ByteReader.ReadBytes(tokenBytes, ref offset, objectIdentifierLength);
  63. if (ByteUtils.AreByteArraysEqual(objectIdentifier, SPNEGOIdentifier))
  64. {
  65. tag = ByteReader.ReadByte(tokenBytes, ref offset);
  66. if (tag == SimpleProtectedNegotiationTokenInit.NegTokenInitTag)
  67. {
  68. return new SimpleProtectedNegotiationTokenInit(tokenBytes, offset);
  69. }
  70. else if (tag == SimpleProtectedNegotiationTokenResponse.NegTokenRespTag)
  71. {
  72. return new SimpleProtectedNegotiationTokenResponse(tokenBytes, offset);
  73. }
  74. }
  75. }
  76. }
  77. else if (tag == SimpleProtectedNegotiationTokenResponse.NegTokenRespTag)
  78. {
  79. return new SimpleProtectedNegotiationTokenResponse(tokenBytes, offset);
  80. }
  81. return null;
  82. }
  83. }
  84. }