/// <summary> /// Add a token header for AP request/response, wrap token or getmic token to make them a complete token. /// </summary> /// <param name="tokenBody">The AP request/response, wrap token or getmic token. /// This argument can be null.</param> /// <returns>The completed token.</returns> public static byte[] AddGssApiTokenHeader(byte[] tokenBody, KerberosConstValue.OidPkt oidPkt = KerberosConstValue.OidPkt.KerberosToken, KerberosConstValue.GSSToken gssToken = KerberosConstValue.GSSToken.GSSSPNG) { List <byte> gssDataList = new List <byte>(); gssDataList.Add(KerberosConstValue.KERBEROS_TAG); // kerberos oid (1.2.840.113554.1.2.2) byte[] oid; oid = KerberosConstValue.GetKerberosOid(); if (tokenBody == null) { tokenBody = new byte[0]; } int length = tokenBody.Length + oid.Length; if (length > 127) { // If the indicated value is 128 or more, it shall be represented in two or more octets, // with bit 8 of the first octet set to "1" and the remaining bits of the first octet // specifying the number of additional octets. The subsequent octets carry the value, // 8 bits per octet, most significant digit first. [rfc 2743] int temp = length; int index = 1; List <byte> lengthList = new List <byte>(); lengthList.Add((byte)(temp & 0xFF)); while ((temp >>= 8) != 0) { index++; lengthList.Add((byte)(temp & 0xFF)); } gssDataList.Add((byte)(0x80 | index)); lengthList.Reverse(); gssDataList.AddRange(lengthList.ToArray()); } else { // If the indicated value is less than 128, it shall be represented in a single octet with bit 8 // (high order) set to "0" and the remaining bits representing the value. [rfc 2743] gssDataList.Add((byte)length); } gssDataList.AddRange(oid); gssDataList.AddRange(tokenBody); if (gssToken == KerberosConstValue.GSSToken.GSSAPI) { return(gssDataList.ToArray()); } else { return(KerberosUtility.EncodeInitialNegToken(gssDataList.ToArray(), oidPkt)); } }
/// <summary> /// Verify and remove a token header from AP request/response, /// wrap token or getmic token. /// </summary> /// <param name="completeToken">The complete token got from application message. /// This argument can be null. If it is null, null will be returned.</param> /// <returns>The token body without the header.</returns> /// <exception cref="System.FormatException">Throw FormatException if the token header is incorrect.</exception> public static byte[] VerifyGssApiTokenHeader(byte[] completeToken, KerberosConstValue.OidPkt oidPkt = KerberosConstValue.OidPkt.KerberosToken) { byte[] oid; oid = KerberosConstValue.GetKerberosOid(); if (completeToken == null || completeToken.Length < KerberosConstValue.GetKerberosOid().Length) { throw new FormatException("The GSS-API token header is incomplete!"); } if (completeToken[0] != KerberosConstValue.KERBEROS_TAG) { throw new FormatException("The GSS-API token header is incorrect!"); } int length = 0; int index = 2; // the tag and length fields // If the length value is 128 or more. if ((completeToken[1] & 0x80) == 0x80) { // If the indicated value is 128 or more, it shall be represented in two or more octets, // with bit 8 of the first octet set to "1" and the remaining bits of the first octet // specifying the number of additional octets. The subsequent octets carry the value, // 8 bits per octet, most significant digit first. int num = completeToken[1] & 0x7F; index += num; if (num < 1 || num > 4) { throw new FormatException("The GSS-API token length is incorrect!"); } for (int i = 0; i < num; ++i) { length = (length << 8) | completeToken[2 + i]; } } else { // If the indicated value is less than 128, it shall be represented in a single octet with bit 8 // (high order) set to "0" and the remaining bits representing the value. [rfc 2743] length = completeToken[1]; } if (!ArrayUtility.CompareArrays(oid, ArrayUtility.SubArray(completeToken, index, oid.Length))) { throw new FormatException("The GSS-API token oid is incorrect!"); } byte[] tokenBody = ArrayUtility.SubArray(completeToken, index + oid.Length); return(tokenBody); }