/// <summary> /// Bind the RPC transport to an interface. /// </summary> /// <param name="interface_id">The interface ID to bind to.</param> /// <param name="interface_version">The interface version to bind to.</param> /// <param name="transfer_syntax_id">The transfer syntax to use.</param> /// <param name="transfer_syntax_version">The transfer syntax version to use.</param> public void Bind(Guid interface_id, Version interface_version, Guid transfer_syntax_id, Version transfer_syntax_version) { if (transfer_syntax_id != Ndr.NdrNativeUtils.DCE_TransferSyntax || transfer_syntax_version != new Version(2, 0)) { throw new ArgumentException("Only supports DCE transfer syntax"); } PDUBind bind_pdu = new PDUBind(MaxXmitFrag, MaxRecvFrag); bind_pdu.Elements.Add(new ContextElement(interface_id, interface_version, transfer_syntax_id, transfer_syntax_version)); var recv_pdu = SendReceivePDU(bind_pdu); if (recv_pdu is PDUBindAck bind_ack) { if (bind_ack.ResultList.Count != 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance) { throw new RpcTransportException($"Bind to {interface_id}:{interface_version} was rejected."); } _max_recv_fragment = bind_ack.MaxRecvFrag; _max_send_fragment = bind_ack.MaxXmitFrag; } else { throw new RpcTransportException("Unexpected PDU from server."); } }
private void BindNoAuth() { PDUBind bind_pdu = new PDUBind(_max_send_fragment, _max_recv_fragment, 0, false); bind_pdu.Elements.Add(new ContextElement(_interface_id, _interface_version, _transfer_syntax_id, _transfer_syntax_version)); var recv_pdu = SendReceivePDU(++CallId, bind_pdu, new byte[0], true, _current_security_context).Item1; if (recv_pdu is PDUBindAck bind_ack) { if (bind_ack.ResultList.Count != 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance) { throw new RpcTransportException($"Bind to {_interface_id}:{_interface_version} was rejected."); } _max_recv_fragment = bind_ack.MaxRecvFrag; _max_send_fragment = bind_ack.MaxXmitFrag; _assoc_group_id = bind_ack.AssocGroupId; } else if (recv_pdu is PDUBindNack bind_nack) { throw new RpcTransportException($"Bind NACK returned with rejection reason {bind_nack.RejectionReason}"); } else { throw new RpcTransportException($"Unexpected {recv_pdu.PDUType} PDU from server."); } }
private void BindAuth(bool alter_context, RpcTransportSecurityContext security_context) { // 8 should be more than enough legs to complete authentication. int max_legs = security_context.MaxAuthLegs; int call_id = ++CallId; int count = 0; while (count++ < max_legs) { PDUBind bind_pdu = new PDUBind(_max_send_fragment, _max_recv_fragment, 0, alter_context); bind_pdu.Elements.Add(new ContextElement(_interface_id, _interface_version, _transfer_syntax_id, _transfer_syntax_version)); if (!_bind_time_features.HasValue) { _bind_time_features = BindTimeFeatureNegotiation.None; bind_pdu.Elements.Add(new ContextElement(_interface_id, _interface_version, BindTimeFeatureNegotiation.SecurityContextMultiplexingSupported)); } var recv = SendReceivePDU(call_id, bind_pdu, security_context.AuthContext.Token.ToArray(), true, security_context); if (recv.Item1 is PDUBindAck bind_ack) { if (bind_ack.ResultList.Count < 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance) { throw new RpcTransportException($"Bind to {_interface_id}:{_interface_version} was rejected."); } if (bind_ack.ResultList.Count == 2) { _bind_time_features = bind_ack.ResultList[1].BindTimeFeature; } if (!alter_context) { // Only capture values from the BindAck. _max_recv_fragment = bind_ack.MaxRecvFrag; _max_send_fragment = bind_ack.MaxXmitFrag; _assoc_group_id = bind_ack.AssocGroupId; alter_context = true; } if (recv.Item2.Data == null || recv.Item2.Data.Length == 0) { // No auth, assume success. break; } security_context.AuthContext.Continue(new AuthenticationToken(recv.Item2.Data)); if (security_context.AuthContext.Done) { byte[] token = security_context.AuthContext.Token.ToArray(); if (token.Length == 0) { break; } // If we still have an NTLM token to complete then send as an Auth3 PDU. if (security_context.TransportSecurity.AuthenticationType == RpcAuthenticationType.WinNT) { SendReceivePDU(call_id, new PDUAuth3(), token, false, security_context); break; } } } else if (recv.Item1 is PDUBindNack bind_nack) { throw new RpcTransportException($"Bind NACK returned with rejection reason {bind_nack.RejectionReason}"); } else { throw new RpcTransportException($"Unexpected {recv.Item1.PDUType} PDU from server."); } } if (!security_context.AuthContext.Done) { throw new RpcTransportException("Failed to complete the client authentication."); } security_context.SetNegotiatedAuthType(); }
private void BindAuth(Guid interface_id, Version interface_version, Guid transfer_syntax_id, Version transfer_syntax_version) { // 8 should be more than enough legs to complete authentication. int max_legs = _transport_security.AuthenticationType == RpcAuthenticationType.WinNT ? 3 : 8; int call_id = ++CallId; int count = 0; bool alter_context = false; while (count++ < max_legs) { PDUBind bind_pdu = new PDUBind(_max_send_fragment, _max_recv_fragment, alter_context); bind_pdu.Elements.Add(new ContextElement(interface_id, interface_version, transfer_syntax_id, transfer_syntax_version)); var recv = SendReceivePDU(call_id, bind_pdu, _auth_context.Token.ToArray(), true); if (recv.Item1 is PDUBindAck bind_ack) { if (bind_ack.ResultList.Count != 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance) { throw new RpcTransportException($"Bind to {interface_id}:{interface_version} was rejected."); } if (!alter_context) { // Only capture values from the BindAck. _max_recv_fragment = bind_ack.MaxRecvFrag; _max_send_fragment = bind_ack.MaxXmitFrag; alter_context = true; } if (recv.Item2.Data == null || recv.Item2.Data.Length == 0) { // No auth, assume success. break; } _auth_context.Continue(new AuthenticationToken(recv.Item2.Data)); if (_auth_context.Done) { byte[] token = _auth_context.Token.ToArray(); if (token.Length == 0) { break; } // If we still have an NTLM token to complete then send as an Auth3 PDU. if (_transport_security.AuthenticationType == RpcAuthenticationType.WinNT) { SendReceivePDU(call_id, new PDUAuth3(), _auth_context.Token.ToArray(), false); break; } } } else if (recv.Item1 is PDUBindNack bind_nack) { throw new RpcTransportException($"Bind NACK returned with rejection reason {bind_nack.RejectionReason}"); } else { throw new RpcTransportException($"Unexpected {recv.Item1.PDUType} PDU from server."); } } if (!_auth_context.Done) { throw new RpcTransportException("Failed to complete the client authentication."); } if (_transport_security.AuthenticationType == RpcAuthenticationType.Negotiate) { var package_name = _auth_context.PackageName; _negotiated_auth_type = AuthenticationPackage.CheckKerberos(package_name) ? RpcAuthenticationType.Kerberos : RpcAuthenticationType.WinNT; } else { _negotiated_auth_type = _transport_security.AuthenticationType; } }