/// <summary> /// Marshal the PDU struct to a byte array. /// </summary> /// <returns>A byte array contains PDU data.</returns> public override byte[] ToBytes() { int size = GetSize(); FieldInfo fieldInfo = GetType().GetField("stub"); if (fieldInfo != null) { byte[] stub = (byte[])fieldInfo.GetValue(this); if (stub != null) { size += stub.Length; } } fieldInfo = GetType().GetField("auth_verifier"); if (fieldInfo != null) { auth_verifier_co_t?authVerifier = (auth_verifier_co_t?)fieldInfo.GetValue(this); size += RpceUtility.AuthVerifierGetSize(authVerifier); } byte[] pduBytes = new byte[size]; using (BinaryWriter binaryWriter = new BinaryWriter(new MemoryStream(pduBytes))) { ToBytes(binaryWriter); } return(pduBytes); }
/// <summary> /// Set length field of PDU. /// </summary> public override void SetLength() { auth_verifier_co_t?authVerifier = null; FieldInfo fieldInfo = this.GetType().GetField("auth_verifier"); if (fieldInfo != null) { authVerifier = (auth_verifier_co_t?)fieldInfo.GetValue(this); } byte[] stub = GetStub(); int stubLength = (stub == null) ? 0 : stub.Length; // stub was already padded in AppendAuthenticationVerifier() auth_length = (authVerifier == null || authVerifier.Value.auth_value == null) ? (ushort)0 : (ushort)authVerifier.Value.auth_value.Length; frag_length = (ushort)(GetSize() + stubLength + RpceUtility.AuthVerifierGetSize(authVerifier)); }
/// <summary> /// Encrypt and sign to get auth_token. /// </summary> /// <param name="authVerifier">auth_verifier, not null.</param> private void EncryptAndSign(ref auth_verifier_co_t authVerifier) { //Request, Response, Fault //Get stub, pad the length to a multiple of 4 bytes. byte[] stub = GetStub(); if (stub == null) { stub = new byte[0]; SetStub(stub); } //Get SecurityBuffers. int stubSecBufIndex; int tokenSecBufIndex; SecurityBufferType readonlyFlag; List <SecurityBuffer> securityBufferList = new List <SecurityBuffer>(); if (context.SupportsHeaderSign) { readonlyFlag = SecurityBufferType.ReadOnlyWithChecksum; } else { readonlyFlag = SecurityBufferType.ReadOnly; } int headerSize = GetSize(); byte[] buf = new byte[ headerSize + stub.Length + RpceUtility.AuthVerifierGetSize(authVerifier)]; using (BinaryWriter binaryWriter = new BinaryWriter(new MemoryStream(buf))) { ToBytes(binaryWriter); } securityBufferList.Add( new SecurityBuffer( SecurityBufferType.Data | readonlyFlag, ArrayUtility.SubArray(buf, 0, headerSize))); stubSecBufIndex = securityBufferList.Count; securityBufferList.Add( new SecurityBuffer( SecurityBufferType.Data, ArrayUtility.ConcatenateArrays(stub, authVerifier.auth_pad))); securityBufferList.Add( new SecurityBuffer( SecurityBufferType.Data | readonlyFlag, ArrayUtility.SubArray( buf, headerSize + stub.Length + authVerifier.auth_pad_length, RpceUtility.AUTH_VERIFIER_SIZE))); //8 == length of auth_verifier tokenSecBufIndex = securityBufferList.Count; securityBufferList.Add( new SecurityBuffer( SecurityBufferType.Token, authVerifier.auth_value)); SecurityBuffer[] securityBuffers = securityBufferList.ToArray(); //encrypt and sign switch (context.AuthenticationLevel) { case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CALL: //Same as RPC_C_AUTHN_LEVEL_PKT case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT: //the field "checksum" is the checksum value returned //by the underlying security service in response to //an integrity protection call context.SecurityContext.Sign(securityBuffers); authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer; break; case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY: //the field "checksum" is the checksum value returned //by the underlying security service in response to //an integrity protection call context.SecurityContext.Sign(securityBuffers); authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer; break; case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_PRIVACY: //This level of service provides strong integrity protection for the //entire PDU, plus privacy protection for the body data only. //Therefore, only the bodies of the request, response and fault PDUs //are encrypted. context.SecurityContext.Encrypt(securityBuffers); authVerifier.auth_pad = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, stub.Length); authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer; stub = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, 0, stub.Length); SetStub(stub); break; //default do nothing. } //A client or a server that (during composing of a PDU) has allocated more space for //the authentication token than the security provider fills in SHOULD<36> fill in //the rest of the allocated space with zero octets. These zero octets are still //considered to belong to the authentication token part of the PDU. int padLength = (int)auth_length - authVerifier.auth_value.Length; if (padLength < 0) { throw new InvalidOperationException("Length of calculated auth_value is incorrect."); } else if (padLength > 0) { authVerifier.auth_value = ArrayUtility.ConcatenateArrays(authVerifier.auth_value, new byte[padLength]); } }