SimpleProtectedNegotiationToken.cs 3.9 KB

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