/// <summary> /// Encrypts Message. User decides what SecBuffers are used. /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">The security buffers to encrypt.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static void Encrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers) { byte[] message = SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Data); byte[] token = SspiUtility.ConcatenateSecurityBuffers(securityBuffers, SecurityBufferType.Token); if (token.Length == 0) { throw new ArgumentException("Token buffer is not valid."); } SGN_ALG sgnAlg = GetSgnAlg(kileRole); KilePdu pdu = kileRole.GssWrap(true, sgnAlg, message); byte[] cipherData = null; if (pdu.GetType() == typeof(Token4121)) { cipherData = pdu.ToBytes(); } else { byte[] allData = pdu.ToBytes(); byte[] paddingData = ((Token1964_4757)pdu).paddingData; cipherData = ArrayUtility.SubArray(allData, 0, allData.Length - paddingData.Length); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, paddingData); } SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Data, ArrayUtility.SubArray(cipherData, cipherData.Length - message.Length)); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, ArrayUtility.SubArray(cipherData, 0, cipherData.Length - message.Length)); }
/// <summary> /// This takes the given byte array, decrypts it, and returns /// the original, unencrypted byte array. /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">The security buffers to decrypt.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static bool Decrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers) { KilePdu pdu = kileRole.GssUnWrapEx(securityBuffers); byte[] decryptedMessage = null; if (pdu.GetType() == typeof(Token4121)) { decryptedMessage = ((Token4121)pdu).Data; } else if (pdu.GetType() == typeof(Token1964_4757)) { Token1964_4757 tokenData = (Token1964_4757)pdu; decryptedMessage = tokenData.Data; SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, tokenData.paddingData); } // else do nothing return(true); }
/// <summary> /// Update the context. /// </summary> /// <param name="pdu">The PDU to update the context.</param> internal override void UpdateContext(KilePdu pdu) { if (pdu == null) { return; } lock (contextLock) { Type pduType = pdu.GetType(); if (pduType == typeof(KileAsRequest)) { KileAsRequest request = (KileAsRequest)pdu; if (request.Request != null && request.Request.req_body != null) { cName = request.Request.req_body.cname; cRealm = request.Request.req_body.realm; eType = request.Request.req_body.etype; } } else if (pduType == typeof(KileAsResponse)) { KileAsResponse response = (KileAsResponse)pdu; if (response.EncPart != null) { tgsSessionKey = response.EncPart.key; } if (response.Response != null) { tgsTicket = response.Response.ticket; if (tgsTicket != null && tgsTicket.sname != null && tgsTicket.sname.name_string != null && tgsTicket.sname.name_string.Elements != null && tgsTicket.sname.name_string.Elements.Length > 1) { int count = tgsTicket.sname.name_string.Elements.Length; cRealm = new Realm(tgsTicket.sname.name_string.Elements[count - 1].Value); } if (response.Response.padata != null && response.Response.padata.Elements != null) { foreach (PA_DATA paData in response.Response.padata.Elements) { if (paData.padata_type != null && paData.padata_type.Value == (long)PaDataType.PA_ETYPE_INFO2) { Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(paData.padata_value.ByteArrayValue); ETYPE_INFO2 eTypeInfo2 = new ETYPE_INFO2(); eTypeInfo2.BerDecode(buffer); if (eTypeInfo2.Elements != null && eTypeInfo2.Elements.Length > 0) { // the salt is received from KDC salt = eTypeInfo2.Elements[0].salt.Value; return; } } } } } } else if (pduType == typeof(KileTgsResponse)) { KileTgsResponse response = (KileTgsResponse)pdu; if (response.Response != null) { apTicket = response.Response.ticket; if (apTicket != null && apTicket.sname != null && apTicket.sname.name_string != null && apTicket.sname.name_string.Elements != null && apTicket.sname.name_string.Elements.Length > 1) { int count = apTicket.sname.name_string.Elements.Length; cRealm = new Realm(apTicket.sname.name_string.Elements[count - 1].Value); } } if (response.EncPart != null) { apSessionKey = response.EncPart.key; } } else if (pduType == typeof(KileApRequest)) { KileApRequest request = (KileApRequest)pdu; if (request.Authenticator != null) { apSubKey = request.Authenticator.subkey; apRequestCtime = request.Authenticator.ctime; apRequestCusec = request.Authenticator.cusec; if (request.Authenticator.cksum != null && request.Authenticator.cksum.cksumtype.Value == (int)ChecksumType.ap_authenticator_8003 && request.Authenticator.cksum.checksum != null && request.Authenticator.cksum.checksum.Value != null && request.Authenticator.cksum.checksum.Value.Length == ConstValue.AUTH_CHECKSUM_SIZE) { int flag = BitConverter.ToInt32(request.Authenticator.cksum.checksum.ByteArrayValue, ConstValue.AUTHENTICATOR_CHECKSUM_LENGTH + sizeof(int)); checksumFlag = (ChecksumFlags)flag; } if (request.Authenticator.seq_number != null) { currentLocalSequenceNumber = (ulong)request.Authenticator.seq_number.Value; currentRemoteSequenceNumber = currentLocalSequenceNumber; } } } else if (pduType == typeof(KileApResponse)) { KileApResponse response = (KileApResponse)pdu; if (response.ApEncPart != null) { if (response.ApEncPart.seq_number != null) { currentRemoteSequenceNumber = (ulong)response.ApEncPart.seq_number.Value; } if (response.ApEncPart.subkey != null) { acceptorSubKey = response.ApEncPart.subkey; } } } // else do nothing } }
/// <summary> /// Update the context. /// </summary> /// <param name="pdu">The Pdu to update the context.</param> internal override void UpdateContext(KilePdu pdu) { if (pdu != null) { Type pduType = pdu.GetType(); if (pduType == typeof(KileAsRequest)) { KileAsRequest request = (KileAsRequest)pdu; if (request.Request != null && request.Request.req_body != null) { cName = request.Request.req_body.cname; cRealm = request.Request.req_body.realm; sName = request.Request.req_body.sname; encryptType = request.Request.req_body.etype; addresses = request.Request.req_body.addresses; nonce = request.Request.req_body.nonce; endTime = request.Request.req_body.till; rtime = request.Request.req_body.rtime; } } else if (pduType == typeof(KileAsResponse)) { KileAsResponse response = (KileAsResponse)pdu; tgsSessionKey = response.EncPart.key; } else if (pduType == typeof(KileTgsRequest)) { KileTgsRequest request = (KileTgsRequest)pdu; encryptType = request.Request.req_body.etype; nonce = request.Request.req_body.nonce; tgsTicket = request.tgtTicket; sName = request.Request.req_body.sname; if (request.authenticator != null) { tgsSubSessionKey = request.authenticator.subkey; } } else if (pduType == typeof(KileTgsResponse)) { KileTgsResponse response = (KileTgsResponse)pdu; apSessionKey = response.EncPart.key; } else if (pduType == typeof(KileApRequest)) { KileApRequest request = (KileApRequest)pdu; apRequestCtime = request.Authenticator.ctime; apRequestCusec = request.Authenticator.cusec; if (request.Authenticator.cksum != null) { int flag = BitConverter.ToInt32(request.Authenticator.cksum.checksum.mValue, ConstValue.AUTHENTICATOR_CHECKSUM_LENGTH + sizeof(ChecksumFlags)); checksumFlag = (ChecksumFlags)flag; } apSubKey = request.Authenticator.subkey; if (request.Authenticator.seq_number != null) { currentRemoteSequenceNumber = (ulong)request.Authenticator.seq_number.mValue; currentLocalSequenceNumber = currentRemoteSequenceNumber; } } else if (pduType == typeof(KileApResponse)) { KileApResponse response = (KileApResponse)pdu; if (response.ApEncPart.subkey != null) { acceptorSubKey = response.ApEncPart.subkey; } } else { // Do nothing. } } }
/// <summary> /// Initialize the context from a token. /// </summary> /// <param name="inToken">The token used to initialize.</param> /// <exception cref="System.NotSupportedException">Thrown when the ContextAttribute contains a flag that not be /// supported.</exception> /// <exception cref="System.InvalidOperationException">Thrown when an error is returned.</exception> public override void Initialize(byte[] inToken) { if (inToken == null || inToken.Length == 0) { KilePdu response = null; string sname = ConstValue.KERBEROS_SNAME; KileAsRequest asRequest; EncryptionKey subkey = null; // Create and send AS request for pre-authentication KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.RENEWABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLEOK; KDCOptions flags = new KDCOptions(KerberosUtility.ConvertInt2Flags((int)options)); // Create and send AS request for pre-authentication asRequest = client.CreateAsRequest(sname, flags, null, this.GetClientSupportedEtype()); client.SendPdu(asRequest); response = client.ExpectPdu(ConstValue.TIMEOUT_DEFAULT); KileKrbError preAuthError = response as KileKrbError; if ((preAuthError == null) || (!preAuthError.ErrorCode.Equals(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED))) { throw new InvalidOperationException("The Error code should be KDC_ERR_PREAUTH_REQUIRED"); } // Create and send AS request for TGT var defualtEncryptType = (client.ClientContext.TgsSessionKey == null) ? EncryptionType.RC4_HMAC : (EncryptionType)client.ClientContext.TgsSessionKey.keytype.Value; PaEncTimeStamp timestamp = client.ConstructPaEncTimeStamp(defualtEncryptType); PaPacRequest pacRequest = client.ConstructPaPacRequest(true); Asn1SequenceOf <PA_DATA> paData = client.ConstructPaData(timestamp, pacRequest); if ((contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle) { asRequest = client.CreateAsRequest(sname, flags, paData, this.GetClientSupportedEtype()); //subkey = new EncryptionKey((int)EncryptionType.AES256_CTS_HMAC_SHA1_96, // KileUtility.GenerateRandomBytes(ConstValue.AES_KEY_LENGTH)); var key = KeyGenerator.MakeKey(EncryptionType.AES256_CTS_HMAC_SHA1_96, client.ClientContext.Password, client.ClientContext.Salt); subkey = new EncryptionKey(new KerbInt32((long)EncryptionType.AES256_CTS_HMAC_SHA1_96), new Asn1OctetString(key)); } else { asRequest = client.CreateAsRequest(sname, flags, paData, this.GetClientSupportedEtype()); } client.SendPdu(asRequest); response = client.ExpectPdu(ConstValue.TIMEOUT_DEFAULT); if (response.GetType() == typeof(KileKrbError)) { throw new InvalidOperationException("Received Kerberos Error response: " + ((KileKrbError)response).ErrorCode); } KileAsResponse asResponse = (KileAsResponse)response; // Create and send TGS request // for example: "KERB.COMldapsut02.kerb.com" client.ClientContext.Salt = domain.ToUpper(); string[] nameList = userLogonName.Split('/'); foreach (string name in nameList) { client.ClientContext.Salt += name; } KileTgsRequest tgsRequest = client.CreateTgsRequest(this.serverName, flags, null, ChecksumType.hmac_md5_string, null, null); client.SendPdu(tgsRequest); response = client.ExpectPdu(ConstValue.TIMEOUT_DEFAULT); if (response.GetType() == typeof(KileKrbError)) { throw new InvalidOperationException("Received Kerberos Error response: " + ((KileKrbError)response).ErrorCode); } KileTgsResponse tgsResponse = (KileTgsResponse)response; ApOptions apOption; ChecksumFlags checksumFlag; GetFlagsByContextAttribute(out apOption, out checksumFlag); KerbAuthDataTokenRestrictions adRestriction = client.ConstructKerbAuthDataTokenRestrictions(0, (uint)LSAP_TOKEN_INFO_INTEGRITY_Flags.FULL_TOKEN, (uint)LSAP_TOKEN_INFO_INTEGRITY_TokenIL.Medium, new Guid().ToString()); AdAuthDataApOptions adApOptions = client.ConstructAdAuthDataApOptions(ConstValue.KERB_AP_OPTIONS_CBT); AuthorizationData authData = client.ConstructAuthorizationData(adRestriction, adApOptions); KileApRequest apRequest = client.CreateApRequest(apOption, ChecksumType.ap_authenticator_8003, ConstValue.SEQUENCE_NUMBER_DEFAULT, checksumFlag, subkey, authData); token = apRequest.ToBytes(); bool isMutualAuth = (contextAttribute & ClientSecurityContextAttribute.MutualAuth) == ClientSecurityContextAttribute.MutualAuth; bool isDceStyle = (contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle; if (isMutualAuth || isDceStyle) { continueProcess = true; // SEC_I_CONTINUE_NEEDED; } else { continueProcess = false; // SEC_E_OK; } } else // mutual authentication { KileApResponse apResponse = client.ParseApResponse(inToken); token = null; if ((contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle) { KileApResponse apResponseSend = client.CreateApResponse(null); token = apResponseSend.ToBytes(); } this.continueProcess = false; // SEC_E_OK; } }