SimpleProtectedNegotiationToken.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. /// <summary>
  19. /// https://tools.ietf.org/html/rfc2743
  20. /// </summary>
  21. /// <exception cref="System.IO.InvalidDataException"></exception>
  22. public static SimpleProtectedNegotiationToken ReadToken(byte[] tokenBytes, int offset)
  23. {
  24. byte tag = ByteReader.ReadByte(tokenBytes, ref offset);
  25. if (tag == ApplicationTag)
  26. {
  27. // when an InitToken is sent, it is prepended by an Application Constructed Object specifier (0x60),
  28. // and the OID for SPNEGO (see value in OID table above). This is the generic GSSAPI header.
  29. int tokenLength = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
  30. tag = ByteReader.ReadByte(tokenBytes, ref offset);
  31. if (tag == (byte)DerEncodingTag.ObjectIdentifier)
  32. {
  33. int objectIdentifierLength = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
  34. byte[] objectIdentifier = ByteReader.ReadBytes(tokenBytes, ref offset, objectIdentifierLength);
  35. if (ByteUtils.AreByteArraysEqual(objectIdentifier, SPNEGOIdentifier))
  36. {
  37. tag = ByteReader.ReadByte(tokenBytes, ref offset);
  38. if (tag == SimpleProtectedNegotiationTokenInit.NegTokenInitTag)
  39. {
  40. return new SimpleProtectedNegotiationTokenInit(tokenBytes, offset);
  41. }
  42. }
  43. }
  44. }
  45. else if (tag == SimpleProtectedNegotiationTokenResponse.NegTokenRespTag)
  46. {
  47. return new SimpleProtectedNegotiationTokenResponse(tokenBytes, offset);
  48. }
  49. return null;
  50. }
  51. /// <summary>
  52. /// Will append the generic GSSAPI header.
  53. /// </summary>
  54. public static byte[] GetTokenBytes(SimpleProtectedNegotiationToken token)
  55. {
  56. if (token is SimpleProtectedNegotiationTokenInit)
  57. {
  58. byte[] tokenBytes = token.GetBytes();
  59. int objectIdentifierFieldSize = DerEncodingHelper.GetLengthFieldSize(SPNEGOIdentifier.Length);
  60. int tokenLength = 1 + objectIdentifierFieldSize + SPNEGOIdentifier.Length + tokenBytes.Length;
  61. int tokenLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(tokenLength);
  62. int headerLength = 1 + tokenLengthFieldSize + 1 + objectIdentifierFieldSize + SPNEGOIdentifier.Length;
  63. byte[] buffer = new byte[headerLength + tokenBytes.Length];
  64. int offset = 0;
  65. ByteWriter.WriteByte(buffer, ref offset, ApplicationTag);
  66. DerEncodingHelper.WriteLength(buffer, ref offset, tokenLength);
  67. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ObjectIdentifier);
  68. DerEncodingHelper.WriteLength(buffer, ref offset, SPNEGOIdentifier.Length);
  69. ByteWriter.WriteBytes(buffer, ref offset, SPNEGOIdentifier);
  70. ByteWriter.WriteBytes(buffer, ref offset, tokenBytes);
  71. return buffer;
  72. }
  73. else
  74. {
  75. return token.GetBytes();
  76. }
  77. }
  78. }
  79. }