/// <summary> /// Create an instance. /// </summary> public KpasswordResponse() : base() { ap_rep = new KerberosApResponse(); krb_priv = new KRB_PRIV(); priv_enc_part = new EncKrbPrivPart(); }
/// <summary> /// Decode GSSAPI token to AP-REP /// </summary> /// <param name="token">GSSAPI token</param> /// <returns></returns> private KerberosApResponse GetApResponseFromToken(byte[] token, KerberosConstValue.GSSToken gssToken = KerberosConstValue.GSSToken.GSSSPNG) { if (gssToken == KerberosConstValue.GSSToken.GSSSPNG) { token = KerberosUtility.DecodeNegotiationToken(token); } if (token[0] == KerberosConstValue.KERBEROS_TAG) { byte[] apData = KerberosUtility.VerifyGssApiTokenHeader(token, this.client.OidPkt); // Check if it has a two-byte tok_id if (null == apData || apData.Length <= sizeof(TOK_ID)) { throw new FormatException( "Data length is shorter than a valid AP Response data length."); } // verify TOK_ID byte[] tokenID = ArrayUtility.SubArray <byte>(apData, 0, sizeof(TOK_ID)); Array.Reverse(tokenID); TOK_ID id = (TOK_ID)BitConverter.ToUInt16(tokenID, 0); if (!id.Equals(TOK_ID.KRB_AP_REP)) { throw new Exception("ApResponse Token ID should be KRB_AP_REP"); } // Get apBody token = ArrayUtility.SubArray(apData, sizeof(TOK_ID)); } KerberosApResponse apRep = new KerberosApResponse(); apRep.FromBytes(token); // Get the current encryption type, cipher data EncryptionType encryptType = (EncryptionType)apRep.Response.enc_part.etype.Value; byte[] cipherData = apRep.Response.enc_part.cipher.ByteArrayValue; byte[] sessionKey = this.Context.ApSessionKey.keyvalue.ByteArrayValue; // decrypt enc_part to clear text byte[] clearText = KerberosUtility.Decrypt(encryptType, sessionKey, cipherData, (int)KeyUsageNumber.AP_REP_EncAPRepPart); // decode enc_part Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(clearText); apRep.ApEncPart = new EncAPRepPart(); apRep.ApEncPart.BerDecode(decodeBuffer); this.client.UpdateContext(apRep); return(apRep); }
/// <summary> /// Client initialize with server token /// </summary> /// <param name="serverToken">Server token</param> private void ClientInitialize(byte[] serverToken) { KerberosApResponse apRep = this.GetApResponseFromToken(serverToken, KerberosConstValue.GSSToken.GSSAPI); this.VerifyApResponse(apRep); token = null; if ((contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle) { KerberosApResponse apResponse = this.CreateApResponse(null); var apBerBuffer = new Asn1BerEncodingBuffer(); if (apResponse.ApEncPart != null) { // Encode enc_part apResponse.ApEncPart.BerEncode(apBerBuffer, true); EncryptionKey key = this.Context.ApSessionKey; if (key == null || key.keytype == null || key.keyvalue == null || key.keyvalue.Value == null) { throw new ArgumentException("Ap session key is not valid"); } // Encrypt enc_part EncryptionType eType = (EncryptionType)key.keytype.Value; byte[] cipherData = KerberosUtility.Encrypt( eType, key.keyvalue.ByteArrayValue, apBerBuffer.Data, (int)KeyUsageNumber.AP_REP_EncAPRepPart); apResponse.Response.enc_part = new EncryptedData(new KerbInt32((int)eType), null, new Asn1OctetString(cipherData)); } // Encode AP Response apResponse.Response.BerEncode(apBerBuffer, true); if ((this.Context.ChecksumFlag & ChecksumFlags.GSS_C_DCE_STYLE) == ChecksumFlags.GSS_C_DCE_STYLE) { // In DCE mode, the AP-REP message MUST NOT have GSS-API wrapping. // It is sent as is without encapsulating it in a header ([RFC2743] section 3.1). this.token = apBerBuffer.Data; } else { this.token = KerberosUtility.AddGssApiTokenHeader(ArrayUtility.ConcatenateArrays( BitConverter.GetBytes(KerberosUtility.ConvertEndian((ushort)TOK_ID.KRB_AP_REP)), apBerBuffer.Data)); } } this.needContinueProcessing = false; // SEC_E_OK; }
private void UpdateContext(KerberosApResponse response) { if (response.ApEncPart != null) { if (response.ApEncPart.seq_number != null) { this.Context.CurrentRemoteSequenceNumber = (uint)response.ApEncPart.seq_number.Value; } if (response.ApEncPart.subkey != null) { this.Context.AcceptorSubKey = response.ApEncPart.subkey; this.Context.SessionKey = response.ApEncPart.subkey; } } }
/// <summary> /// Updated context based on Kerberos pdu /// </summary> /// <param name="pdu">Kerberos pdu</param> public override void UpdateContext(KerberosPdu pdu) { if (pdu is KerberosAsRequest) { KerberosAsRequest request = (KerberosAsRequest)pdu; UpdateContext(request); } if (pdu is KerberosKrbError) { KerberosKrbError error = (KerberosKrbError)pdu; UpdateContext(error); } if (pdu is KerberosAsResponse) { KerberosAsResponse response = (KerberosAsResponse)pdu; UpdateContext(response); } if (pdu is KerberosTgsRequest) { KerberosTgsRequest request = pdu as KerberosTgsRequest; UpdateContext(request); } if (pdu is KerberosTgsResponse) { KerberosTgsResponse response = pdu as KerberosTgsResponse; UpdateContext(response); } if (pdu is KerberosApRequest) { KerberosApRequest request = pdu as KerberosApRequest; UpdateContext(request); } if (pdu is KerberosApResponse) { KerberosApResponse response = pdu as KerberosApResponse; UpdateContext(response); } this.expectedPduType = null; }
public KerberosApResponse CreateApResponse(EncryptionKey subkey) { var response = new KerberosApResponse(); response.Response.msg_type = new Asn1Integer((int)MsgType.KRB_AP_RESP); response.Response.pvno = new Asn1Integer(KerberosConstValue.KERBEROSV5); // Set EncAPRepPart var apEncPart = new EncAPRepPart(); apEncPart.ctime = Context.Time; apEncPart.cusec = Context.Cusec; apEncPart.subkey = null; apEncPart.seq_number = new KerbUInt32((long)Context.currentRemoteSequenceNumber); response.ApEncPart = apEncPart; this.client.UpdateContext(response); return(response); }
private void VerifyApResponse(KerberosApResponse apRep) { apRep.Decrypt(this.Context.ApSessionKey.keyvalue.ByteArrayValue); if (apRep.ApEncPart != null) { if (apRep.ApEncPart.ctime.Value != this.ApRequestAuthenticator.ctime.Value) { throw new NotSupportedException("ctime is not match with KRB_AP_REQ ctime"); } if (apRep.ApEncPart.cusec.Value != this.ApRequestAuthenticator.cusec.Value) { throw new NotSupportedException("cusec is not match with KRB_AP_REQ cusec"); } if (apRep.ApEncPart.seq_number.Value == null || apRep.ApEncPart.seq_number.Value <= 0) { throw new NotSupportedException("seq_number should be a valid value"); } } else { throw new NotSupportedException("KRB_AP_REP decrypt failed"); } }
/// <summary> /// Decode GSSAPI token to AP-REP /// </summary> /// <param name="token">GSSAPI token</param> /// <returns></returns> public KerberosApResponse GetApResponseFromToken(byte[] token, KerberosConstValue.GSSToken gssToken = KerberosConstValue.GSSToken.GSSSPNG) { if (gssToken == KerberosConstValue.GSSToken.GSSSPNG) token = KerberosUtility.DecodeNegotiationToken(token); if (token[0] == KerberosConstValue.KERBEROS_TAG) { byte[] apData = KerberosUtility.VerifyGssApiTokenHeader(token, this.oidPkt); // Check if it has a two-byte tok_id if (null == apData || apData.Length <= sizeof(TOK_ID)) { throw new FormatException( "Data length is shorter than a valid AP Response data length."); } // verify TOK_ID byte[] tokenID = ArrayUtility.SubArray<byte>(apData, 0, sizeof(TOK_ID)); Array.Reverse(tokenID); TOK_ID id = (TOK_ID)BitConverter.ToUInt16(tokenID, 0); this.testSite.Assert.AreEqual(TOK_ID.KRB_AP_REP, id, "The Token ID should be KRB_AP_REP"); // Get apBody token = ArrayUtility.SubArray(apData, sizeof(TOK_ID)); } KerberosApResponse response = new KerberosApResponse(); response.FromBytes(token); return response; }