none
How to: SSL passthrough from BigIP?

    Question

  • We have a BigIP that proxies SSL handling for all of our servers. Our service however is using:

    <security mode="TransportWithMessageCredential">

    How can I configure WCF to understand that SSL is being proxied by the BigIP?

    Thanks,
    Drew

    Monday, September 18, 2006 7:24 PM

Answers

  • Hello:

    The main idea behind the proposed solution is to define a derivative of HttpTransportBindingElement that has a protection level of "EncryptAndSign" and use this element instead of a HttpsTransportBindingElement.
    Notice however that the security level reported by the transport element is NOT provided by the transport but assumed to be provided by other means (the F5 box in the concrete example)

    1) Create a class derived from HttpTransportBindingElement such as the following.
    Notice that the GetProperty is overrided to return an instance of MySecurityCapabilities.
    Notice also that this implementation of ISecurityCapabilities returns a protection level of "EncryptAndSign"

    class MyPseudoHttpsTransportBindingElement : HttpTransportBindingElement {
        public override T GetProperty<T>(BindingContext context)
        {
            if(typeof(T) == typeof(ISecurityCapabilities)){
                return (T) (object) new MySecurityCapabilities();
            }
            return base.GetProperty<T>(context);
        }

        // do not forget the clone!!!!
        public override BindingElement Clone(){
            return new MyPseudoHttpsTransportBindingElement();
        }
    }

    public class MySecurityCapabilities : ISecurityCapabilities {
            public System.Net.Security.ProtectionLevel SupportedRequestProtectionLevel
            {
                get { return System.Net.Security.ProtectionLevel.EncryptAndSign; }
            }

            public System.Net.Security.ProtectionLevel SupportedResponseProtectionLevel
            {
                get { return System.Net.Security.ProtectionLevel.EncryptAndSign; }
            }

            public bool SupportsClientAuthentication
            {
                get { return false; }
            }

            public bool SupportsClientWindowsIdentity
            {
                get { return false; }
            }

            public bool SupportsServerAuthentication
            {
                get { return true; }
            }
    }

    2) Create a WSHttpBinding with a security mode equal to TransportWithMessageCredential

    3) Create a CustomBinding with the binding elements of the created WSHttpBinding and replace the HttpsTransportBindingElement with the MyPseudoHttpsTransportBindingElement

    4) Use this CustomBinding

    I've tried and it seems to work.

    There is however one problem: there is an error when the ServiceHost tries to generate the WSDL (the first time there is a HTTP GET to it).
    This is so, because the security binding element requires the transport element to implement the ITransportTokenAssertionProvider. The HTTPS binding element implements this interface but the HTTP element doesn't.
    There are two solutions to this problem:
        S1) Don't use the generated WSDL. If you need a WSDL description use the one generated with the original setting (using HTTPS transport)

        S2) The custom transport element must implement ITransportTokenAssertionProvider and IPolicyExportExtension. In this case the WSDL policy will be correct but the port address will be HTTP and not HTTPS.

    I would appreciate your comments
    Best regards

    Pedro Felix

    Tuesday, September 26, 2006 4:09 PM
  • So I communicated with Pedro a little offline. He suggested a solution involving extending the HttpTransportBindingElement, overriding GetProperty<T> and returning my own custom ISecurityCapabilities which basically "lie" about the encryption. It seems to work flawlessly. I have pure HTTP only communication with username credentials flowing from client to server. I'll let Pedro follow up with the details since it is his solution and he deserves full credit for it. Thanks a ton Pedro!

    I would love to hear from Microsoft what they think about the solution. Obviously it is dangerous because the credentials could be passed insecurely, but I've obviously made a real choice here by going an implementing this myself... so I know what the risk is. I can understand Microsoft not wanting to support this out of the box, but it really might be worthwhile to add some additional support to HttpTransportBindingElement which enable supporthing this scenario. I was thinking something like:

    Add a property like "EnableSslPassthrough" and require specifying an HTTP header that can be checked via a a pair of properties like "SslPassthroughHttpHeaderName" and "SslPassthroughHttpHeaderValue". This would allow for stringent validation that the service is indeed being hit through SSL because the F5 box (or whatever you have "in front") would have to add the header into the request.

     

    Cheers,
    Drew

    Tuesday, September 26, 2006 3:58 PM

All replies

  • Could you describe a little more your scenario, namely the usage of the "BigIP"?

    Pedro Felix
    Tuesday, September 19, 2006 11:42 AM
  • Yeah, specifically we use an F5 box that load balances and does a bunch of other stuff for our web server farm (read more about it's capabilities here). One of the things it does is proxy the SSL encryption so that you only need to install a certificate on it as opposed to installing it on your 30 web servers individually. Not only that, but it has hardware SSL encryption/decryption, so you save the load on your webservers. Essentially traffic hits the F5 box as HTTPS, is decrypted and then routed to one of the web servers as plain HTTP for processing. Vice versa for the response. We can tell that the F5 handled the SSL when the request hits the box because, when it does, the F5 injects a header into the HTTP request that we then look for in our application to ensure the user is accessing certain areas only under SSL.

    So, the problem is simple. When the traffic hits the WCF service, it's plain HTTP, but because I'm trying to use TransportWithMessageCredential I'm up the creek without a paddle. There should be some way to configure WCF's http transport to detect such a header and not require it to handle SSL itself.

    Cheers,
    Drew

     

    Tuesday, September 19, 2006 3:14 PM
  • Hello:

    Are you using a UsernameToken credential? Assuming that you are, why don't you just use message level security. The message credentials will be protected by the HTTPS transport between the clients and the F5 box. They will only be in cleartext between the F5 box and the final HTTP server.


    Best regards
    Pedro Felix
    Tuesday, September 19, 2006 9:19 PM
  • WCF will not allow a username token to be passed in the clear.  In this situation, it's not really, but WCF doesn't know that.

    If it is a username/password pair, you could send it in a custom header, although if you did that, you wouldn't be able to do any sort of claims or role checking. 

    You could create a custom token and pass that.   Perhaps a GenericXMLSecurityToken.

    Thanks!

    Scott

    Tuesday, September 19, 2006 9:52 PM
  • Thanks for the correction. I didn't noticed that (important) detail.

    Thanks
    Pedro Felix
    Tuesday, September 19, 2006 10:27 PM
  • So I communicated with Pedro a little offline. He suggested a solution involving extending the HttpTransportBindingElement, overriding GetProperty<T> and returning my own custom ISecurityCapabilities which basically "lie" about the encryption. It seems to work flawlessly. I have pure HTTP only communication with username credentials flowing from client to server. I'll let Pedro follow up with the details since it is his solution and he deserves full credit for it. Thanks a ton Pedro!

    I would love to hear from Microsoft what they think about the solution. Obviously it is dangerous because the credentials could be passed insecurely, but I've obviously made a real choice here by going an implementing this myself... so I know what the risk is. I can understand Microsoft not wanting to support this out of the box, but it really might be worthwhile to add some additional support to HttpTransportBindingElement which enable supporthing this scenario. I was thinking something like:

    Add a property like "EnableSslPassthrough" and require specifying an HTTP header that can be checked via a a pair of properties like "SslPassthroughHttpHeaderName" and "SslPassthroughHttpHeaderValue". This would allow for stringent validation that the service is indeed being hit through SSL because the F5 box (or whatever you have "in front") would have to add the header into the request.

     

    Cheers,
    Drew

    Tuesday, September 26, 2006 3:58 PM
  • Hello:

    The main idea behind the proposed solution is to define a derivative of HttpTransportBindingElement that has a protection level of "EncryptAndSign" and use this element instead of a HttpsTransportBindingElement.
    Notice however that the security level reported by the transport element is NOT provided by the transport but assumed to be provided by other means (the F5 box in the concrete example)

    1) Create a class derived from HttpTransportBindingElement such as the following.
    Notice that the GetProperty is overrided to return an instance of MySecurityCapabilities.
    Notice also that this implementation of ISecurityCapabilities returns a protection level of "EncryptAndSign"

    class MyPseudoHttpsTransportBindingElement : HttpTransportBindingElement {
        public override T GetProperty<T>(BindingContext context)
        {
            if(typeof(T) == typeof(ISecurityCapabilities)){
                return (T) (object) new MySecurityCapabilities();
            }
            return base.GetProperty<T>(context);
        }

        // do not forget the clone!!!!
        public override BindingElement Clone(){
            return new MyPseudoHttpsTransportBindingElement();
        }
    }

    public class MySecurityCapabilities : ISecurityCapabilities {
            public System.Net.Security.ProtectionLevel SupportedRequestProtectionLevel
            {
                get { return System.Net.Security.ProtectionLevel.EncryptAndSign; }
            }

            public System.Net.Security.ProtectionLevel SupportedResponseProtectionLevel
            {
                get { return System.Net.Security.ProtectionLevel.EncryptAndSign; }
            }

            public bool SupportsClientAuthentication
            {
                get { return false; }
            }

            public bool SupportsClientWindowsIdentity
            {
                get { return false; }
            }

            public bool SupportsServerAuthentication
            {
                get { return true; }
            }
    }

    2) Create a WSHttpBinding with a security mode equal to TransportWithMessageCredential

    3) Create a CustomBinding with the binding elements of the created WSHttpBinding and replace the HttpsTransportBindingElement with the MyPseudoHttpsTransportBindingElement

    4) Use this CustomBinding

    I've tried and it seems to work.

    There is however one problem: there is an error when the ServiceHost tries to generate the WSDL (the first time there is a HTTP GET to it).
    This is so, because the security binding element requires the transport element to implement the ITransportTokenAssertionProvider. The HTTPS binding element implements this interface but the HTTP element doesn't.
    There are two solutions to this problem:
        S1) Don't use the generated WSDL. If you need a WSDL description use the one generated with the original setting (using HTTPS transport)

        S2) The custom transport element must implement ITransportTokenAssertionProvider and IPolicyExportExtension. In this case the WSDL policy will be correct but the port address will be HTTP and not HTTPS.

    I would appreciate your comments
    Best regards

    Pedro Felix

    Tuesday, September 26, 2006 4:09 PM
  • So it turns out there's a problem with this when I put it out into the test environment. Basically the username token implementation must have some hardcoded logic in it because it's trying to validate the endpoint address is something other than what is actually configured for the service. I've logged the bug here in Connect. I hope Microsoft is paying attention because I've been providing a bunch of feedback on this stuff and haven't heard anything from them recently on this subject or others.

    This bug is pretty bad and it prevents what would otherwise be a good workaround that solves a real world problem from working without some serious hackery in terms of WS-Addressing.

    -Drew

    Monday, October 02, 2006 6:56 PM
  • Drew,

    I like to gather a bit more info before posting any reccomendation/suggestion.  If there is no privacy concern, could you please log the message that were send from client to F5 and F5 to the web server.  I would like to look specifically at the security header.

    Thanks,

    Thursday, January 11, 2007 8:50 PM
  • Did you ever find a resolution? I'd like to accomplish the exact same thing as Drew, and I'm interested to know if a solution was reached.
    Friday, September 28, 2007 1:56 PM
  • No I never did. They closed out the bug, never said why, the problem still exists for me. User's are forced to send http in the WS-A header even though the endpoint is https. I haven't tried it in 3.5 to see if it's fixed.

     

    -Drew

    Friday, September 28, 2007 2:15 PM
  • Drew,

    How are you hacking the WS-A header? I am at the same point as you and the last thing i want to do is have to get clients to hack the to header just to get this stuff working - so much for standards compliance!! Sad

    Did you get this working using via?  What was your eventual workaround?

    Mark


    For interests sake this is what I can't get past

    The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

    In the WCF trace I can see the acceptance of the inbound message, I can see it call our custom usernamepassword validator but then I get this message.
    Wednesday, April 16, 2008 12:44 PM
  • In answer to my own question even though I had specified TransportWithMessageCredential the client binding was treating it as "TransportWithMessageCredentialAndMessageEncryptionOrSigning" (I couldn't figure out whether it was signing or encryption).  Configuring the Message security portion of the bindings config as so...

                <message clientCredentialType="UserName" establishSecurityContext="false" />

    ie, setting establishSecurityContext to false caused the WCF client to stop trying to establish a WS-Trust relationship with the server.

    In the end though this is all working for me - The only additional thing I had to do was add AddressFilterMode = AddressFilterMode.Any to my servicebehavior attached to the service implementations so the addressing was a bit less strict and the ssl calls work.

    Mark


    Wednesday, April 16, 2008 4:48 PM
  • Hi Mark,

    I had similar situation in my environment.

    I have SSL with Username credential type. My servers are behind load balancer. Currently, It is working with basic authentication. I have username and password authentication requirment. I want to use this solution. I created all the objects as for this post. Can you share your client and server config file samples. I got struct at the point that it uses both wsHttpBinding and customBinding with TransportWithMessageCredential.

     

    Thanks in Advance,

    SudhK

     

    Wednesday, July 09, 2008 4:31 PM
  • Register your extension

    <extensions>
     <bindingElementExtensions>
      <!-- define our Https Offload transport extension -->
      <add name="httpsOffloadTransport" type="MyNamespace.HttpsOffloadTransportElement, MyAssembly" />
     </bindingElementExtensions>
    </extensions>

    Create a custom binding.

    <customBinding>
      <binding name="UserNamePasswordSecured">
         <textMessageEncoding />
         <security authenticationMode="UserNameOverTransport" />
         <httpsOffloadTransport />
      </binding>
    </customBinding>

    then use that binding infor your endpoint.

    M





    Wednesday, July 09, 2008 5:23 PM
  • Mark,

    Thank you for your reply. Here is my server configuration file. When I tried to generate client config file, I am getting error.

     

    Server Web.config file
    --------------------------

    <system.serviceModel>

       <extensions>

    <bindingElementExtensions>
            <add name="httpsViaProxyTransport" type="MyNamespace.HttpsViaProxyTransportElement, MyServices"/>
          </bindingElementExtensions>

    </extensions>

        <services>
       <service behaviorConfiguration="ServiceBehaviour" name="MyNamespace.MyService">
           
          
           
            <endpoint address="https://mywcf.com/testserver/MyService.svc"
                  binding="customBinding"
               bindingConfiguration="ServiceCustomBinding"
               contract="MyNamespace.IMyService" />

          
          </service>
      </services>

       
      <behaviors>
       <serviceBehaviors>
        <behavior name="ServiceBehaviour">
         <serviceDebug includeExceptionDetailInFaults="false"/>
         <serviceMetadata />
         <serviceTimeouts/>
         <serviceCredentials>
         

                  <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyNamespace.CredentialUNPValidator, MyServices" />
          
         </serviceCredentials>
              <serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="false" serviceAuthorizationAuditLevel="None" messageAuthenticationAuditLevel="SuccessOrFailure" />
        </behavior>
       </serviceBehaviors>
      </behaviors>
       
      

        <bindings>
       <wsHttpBinding>
        <binding name="ServiceCustomBinding" receiveTimeout="12:59:59"  >
         <security mode="TransportWithMessageCredential">
          <message clientCredentialType="UserName"/>
         </security>
        </binding>
       </wsHttpBinding>


        <customBinding>
            <binding name="ServiceCustomBinding">
              <textMessageEncoding />
              <security authenticationMode="UserNameOverTransport" />
              <httpsViaProxyTransport authenticationScheme="Anonymous" maxReceivedMessageSize="4096" />
            </binding>
          </customBinding>
        </bindings>
     </system.serviceModel>

     

    I did follow this forum to create all other classes including the HttpsViaProxyTransportElement which creates

    HttpsViaProxyTransportBindingElement by overriding defaultbindingtype and createdefaultbinding methods.

     

    When I try to create the client app.config file, I am getting error service can't be activated.

     

    I appreciate your help.

     

    Thanks

    SudhK

     

     

    Wednesday, July 09, 2008 7:11 PM
  • Mark,

    I did setup as for the forum article and my validate method and also the HttpsViaProxyTransportBindingElement object are getting reached. However, I guess, I am making some mistake in my client configuration file and getting this error.

    ex = {"An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail."} - InnerException = {"An error occurred when verifying security for the message."}

     

    I am using IIS for hosting the service. I have Loadbalancer before IIS and SSL installed on it. No SSL installed on IIS box. Only service is hosted.

     

    Here is my web.config again:

    Server Web.config file
    --------------------------

    <system.serviceModel>

       <extensions>

    <bindingElementExtensions>
            <add name="httpsViaProxyTransport" type="MyNamespace.HttpsViaProxyTransportElement, MyServices"/>
          </bindingElementExtensions>

    </extensions>

    <services>
       <service behaviorConfiguration="ServiceBehaviour" name="MyNamespace.MyService">
            <endpoint address="http://mywcf.com/testserver/MyService.svc"
                  binding="customBinding"
               bindingConfiguration="ServiceCustomBinding"
               contract="MyNamespace.IMyService" />

          </service>
     </services>

       
      <behaviors>
       <serviceBehaviors>
        <behavior name="ServiceBehaviour">
         <serviceDebug includeExceptionDetailInFaults="false"/>
         <serviceMetadata />
         <serviceTimeouts/>
         <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyNamespace.CredentialUNPValidator, MyServices" />
         
         </serviceCredentials>
              <serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="false" serviceAuthorizationAuditLevel="None" messageAuthenticationAuditLevel="SuccessOrFailure" />
        </behavior>
       </serviceBehaviors>
      </behaviors>
       
    <bindings>
      
        <customBinding>
            <binding name="ServiceCustomBinding">
              <textMessageEncoding />
              <security authenticationMode="UserNameOverTransport" />
              <httpsViaProxyTransport authenticationScheme="Anonymous" maxReceivedMessageSize="23454096" />
            </binding>
          </customBinding>
        </bindings>
     </system.serviceModel>

    Here is the client - App.Config

     

    <bindings>

    <wsHttpBinding>

    <binding name="ServiceCustomBinding" receiveTimeout="12:59:59" >

    <reliableSession ordered="false" inactivityTimeout="12:58:59"/>

    <security mode="TransportWithMessageCredential">

    <message clientCredentialType="UserName" negotiateServiceCredential="true"/>

    <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>

    </security>

    </binding>

    </wsHttpBinding>

    <!--<customBinding>

    <binding name="ServiceCustomBinding">

    <textMessageEncoding />

    <security authenticationMode="UserNameOverTransport" />

    <httpsTransport/>

    </binding>

    </customBinding>-->

    </bindings>

    <client>

     

    <endpoint address=https://mywcf.com/TestServer/MyService.svc

    binding="wsHttpBinding" bindingConfiguration="ServiceCustomBinding"

    contract="proxyService.IMyService" name="ServiceCustomBinding" />

     

    </client>

    </system.serviceModel>

     

    Please give me your input. Thanks

    SudhK

    Wednesday, July 09, 2008 8:59 PM
  • Thanks for the solution Pedro.

     

    We are facing the same the issue & tried to implement the solution given here, but still we not successfull in this. we are getting the same error. Still we are not able call the server with http.

     

    Since Load balancer try to call our service at port 80 (i.e http) it thorws 404 error.

     

    Our Prod release is on this Friday, it will be really heplful if you can help on this.

     

    Regards,

    -Srini

    Wednesday, August 13, 2008 6:27 AM
  • Hi.

    I'm not following this thread for a long time. Could you be more specific about your problem, namely?

     - What is your network topology: load balancer, F5, HTTP server?

     - Where are the requests arriving?

     

    Pedro

     

    Wednesday, August 13, 2008 1:36 PM
  • Hi Pedro,

    We are using WCF .Net 3.5 for our web service & each request sends username / password to our service over https. We are using IIS 6, windows 2003 server with SSL enabled.

     

    On our production environment we have F5 Load balance sits between client & server. So https is decrypted by LB & LB make http request to our servers with username / password. So the request come through LB fails. We tried to implement the solution suggested by you, but still we are not sucessfull. still we are facing the same issue.

     

    Pls let me know if have any working solution for this.

     

    Thanks,

    -Srini

     

    Thursday, August 14, 2008 12:46 PM
  • Hello:

     

    1) Is the request arriving at the F5?

    If not, check the protocol, address and port being used by the client, namely ensure that the protocol is HTTPS and not HTTP.

     

    2) Is the request arriving at the service?

    If yes, enable tracing at the service-side (all info) and search for all thrown exceptions. Post these exceptions (including inner exceptions) so that I can try to help you.

    If not, try to see in the F5 logs (which I'm not familiar) why the request isn't being forwarded.

     

    Pedro

     

     

     

    Thursday, August 14, 2008 1:57 PM
  •  

    Hi Pedro,

     

    Requesting is reaching F5 & SSL is get decripted here & forward the request as HTTP to the application server.

     

    So Application server gets HTTP requested & thorws the exception as Username & password cannot be send over HTTP. This after implementing the solution suggested by you in your previous messages.

     

    Thanks,

    -Srini

    Thursday, August 21, 2008 5:41 AM
  •  

    Hi Everyone. We're actually having the same issue here.

     

    I found this post from Drew's blog, and we are in the same circumstances. We have our IIS6 farm behind a BigIP F5 load balancer that is performing SSL in hardware and passing all requests to IIS as port 80 http. WCF fails any authentication call if it is not sent over https even with Pedro's workaround.

     

    Can anyone give any insight as to if Microsoft is aware of this limitation currently? At this point we're going to need to run a separate web farm just for our WCF services so that we can go https directly to the server, which is less than optimal.

     

    Thanks

     

    Monday, August 25, 2008 4:22 PM
  • Hi,

     

    Thanks for the post Pedro. I was trying out the ways you pointed out to solve a similar issue where in one of our client website connects to a service sitting on our web server but is guarded by the hardware SSL. I still run into an error and the exact message goes as :
    Error occured. Could not establish trust relationship for the SSL/TLS secure channel with authority...

    The service uses the custom binding that was created as your post suggested but dont know where exactly the problem is.
    Could you show the sample config files for the server and the client with the bindings. Dont know where I am going wrong.

    Could you please help me with the config settings for the bindings. Appreciate your help.

     

    Thanks,

    Sachin

    Thursday, September 25, 2008 5:56 AM
  • In your custom client binding make sure, in your security section

    <security mode="TransportWithMessageCredential">
    <transport clientCredentialType="None" />
    <message clientCredentialType="Certificate|Username" establishSecurityContext="false" />
    </security>

    The bold being the important bit, this stops WCF attempting to establish a WS-Trust relationship.
    Thursday, September 25, 2008 8:23 AM
  • Hi Sachin:

     

    Could you enable the trace log (client and service) and post the exception info that is present there (including the inner exceptions)?

     

    Regards

    Pedro Félix

    Thursday, September 25, 2008 1:14 PM
  • We were able to create the custom binding described in this post, but ran into issues with the WSDL generation issue.

    Does anyone have a reference on the details of implementing solution 2?

    >>(S2) The custom transport element must implement ITransportTokenAssertionProvider and IPolicyExportExtension

    Tuesday, December 09, 2008 10:16 PM
  • I'll add my voice to the chorus...having the same problems.  I implemented the custom binding, and my self-hosted services spin up fine.  There is an F5 between the servers and the client, HTTPS is terminated and load balanced across port 8000 on the servers.  My client talks on HTTPS port 443.  If I use the custom binding on the client, I get an error before any message is sent:

    The provided URI scheme 'https' is invalid; expected 'http'. Parameter name: via.

    I presume this is because the custom binding element is subclassing HttpTransportBindingElement, which expects an endpoint URI with the http scheme.  The same idea that lets this binding work on the server is stopping it from working on the client.  The error seems to be happening when the endpoint URI is validated.  Is there some way to intercept that process?

    I also tried using a WsHttpBinding on the client side, with TransportWithMessageCredential security.  When those messages reach the server, I get this error:

    The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).: at System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message)

    I'm not sure why this security negotiation is taking place since I chose TransportWithMessageCredential security...ideas?  It feels odd to be using a mismatched binding...what binding are we supposed to use on the client side? 

    Thanks.
    -Rob

    Monday, December 29, 2008 9:20 PM
  • Following up on this...

    While troubleshooting this issue, a colleague pointed out that I forgot to set establishSecurityContext=false in my binding configuration.  I had inadvertently removed it during the course of troubleshooting.  After restoring it, and adjusting my client-side logic accordingly, I am happy to say that everything is working.  For those interested, the custom binding is only used in the server-side WCF configuration.  My client-side bindings remain WsHttpBindings.

    -Rob

    Tuesday, December 30, 2008 3:18 PM
  • I'm trying to get this to work using silverlight, which only supports basicHttpBinding.

    Let me see if I understand the solution correctly -

    1) Client uses wsHttpBinding and configures it like this:

    <security mode="TransportWithMessageCredential">
    <transport clientCredentialType="None" />
    <message clientCredentialType="Certificate|Username" establishSecurityContext="false" />
    </security>


    2) Server uses only a customBinding with the pseudohttpstransport. So I don't have any wsHttpBindings set up on my server.


    Well, since I'm using silverlight, this is all I can do for the client:

    EndpointAddress ep = new EndpointAddress(address);
    BasicHttpBinding bind = new BasicHttpBinding();
    bind.Security.Mode =
    BasicHttpSecurityMode.Transport;
    //CustomBinding cust = new CustomBinding(bind);
    _ws = new AnnotationService.AnnotationClient(bind, ep);

    Then I get this error in my server log:

    <ExceptionString>System.ServiceModel.Security.MessageSecurityException: Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties.   This can occur if the service is configured for security and the client is not using security.</ExceptionString>

    Server customBinding looks like this:

    <customBinding>
            <binding name="BasicHttpBinding_Annotation_Secure" maxBufferSize="2147483647"
           maxReceivedMessageSize="2147483647">
               <textMessageEncoding messageVersion="Soap11">
                 <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                    maxArrayLength="2147483647" maxBytesPerRead="2147483647"
                    maxNameTableCharCount="2147483647" />
               </textMessageEncoding>
               <security authenticationMode="UserNameOverTransport" />
               <PseudoHttpsTransport authenticationScheme="Anonymous"/>
            </binding>
          </customBinding>

    Tuesday, January 20, 2009 4:50 PM
  • You might also try to use this binding which allows username over http:


    http://webservices20.blogspot.com/
    WCF Security, Performance And Testing Blog
    Tuesday, January 20, 2009 5:09 PM
  • unfortunately this is not possible in silverlight. In my clientconfig I get this error: "The element system.serviceModel has invalid child element 'extensions'. List of possible elements expected 'bindings, client'.
    Wednesday, January 21, 2009 7:08 PM
  •  

    Ok, I think I figured this out with help from microsoft tech support.

     I have an unusual load balancer setup that was changing my endpoint. So on each of my servers I had to change my endpoint address to be "http://servername..."

    I was told that a normal load balancer wouldn't do that and in that case I might have to have something like this:

     <endpoint address=" https://..."

    listenUri="http://..."

    Thursday, January 22, 2009 12:20 AM
  • Hi all,

    I haven't read all of the messages in this thread so I am not sure of the various levels of success or otherwise everyone has had, but I wanted to send a pointer to Michele Bustamante's latest article (january 09) in aspnet pro which deals exactly with this situation. I have had this scenario in the past and the article would have been a life saver for me then :) the link is

    http://www.aspnetpro.com/PDF/asp_PDF_3Mags.asp

    Cheers

    Dan

    Friday, January 23, 2009 1:57 PM
  • Thank you to all for the above posts as it helped me immensely in getting a similar scenario to work for me on short notice.  I too had an SSL passthrough load balancer set-up in my production environment and encountered many of the same issues.  Using this post and one from hackedbrain (http://blog.hackedbrain.com/archive/2006/09/26/5281.aspx) I was able to get very close to getting my service running.  An issue I ran into that did not come up here, but thought I would add, was one regarding a 'mismatch' with AddressFilterMode.  Specifically, the error was: 

    The message with To 'http://<servicename.svc>' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses

    By adding the following service decoration to my service, It finally worked.

    [ServiceBehavior(AddressFilterModeAddressFilterMode = AddressFilterMode.Any)] 


    Thanks again!
    Marc
    Sunday, February 15, 2009 9:40 PM
  • I have got this error while I’m working with .net remoting over F5 BigIp.

     

     

     

    And this is my scenario:

    1-I’ve developed a .net 2.0 remoting application.

    2-I’m using four Windows Services to host my remoting objects.

    3-I’m using TCP Channel and SAO activation.

    4-This is the Windows Services .app config

     

      <!-- CONFIGURACION SERVICIOS REMOTOS -->

          < system.runtime.remoting >

                < customErrors mode = " off " />

                < application >

                      < channels >

                            < channel ref = " tcp "   port = " 23501 "

                                     socketCacheTimeout = " 0 "

                                         socketCachePolicy = " absoluteTimeout " >

                                 < serverProviders >

                                       < formatter ref = " binary " typeFilterLevel = " Full " />

                                 </ serverProviders >

                            </ channel >

                      </ channels >

                      < service >

     < wellknown mode = " SingleCall " type = " SAFI_NET.Negocios.Operaciones.Ordenes, SAFINET.Negocios.Operaciones " objectUri = " Ordenes " />

     

    5- This is the Client Activation:

     

    CType (Activator.GetObject( GetType (Interfaces.Operaciones.ICierresDiarios), Aplicacion.TraerURLOperaciones & "/CierresDiarios" ), Interfaces.Operaciones.ICierresDiarios)

     

    6-I have a Middleware farm (F5 BIGIP) address (192.168.162.162). This farm has two nodes (192.168.162.50, 192.168.162.51).This nodes has the same hardware and software specification. Both of them have installed my Windows Services.

     

    7-When I try to connect trough the farm , I get this error  “An  active connection was forcibly closed by remote host” or even :

     

    System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond Server stack trace: at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) at System.Net.Sockets.Socket.Connect(EndPoint remoteEP) at System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket(EndPoint ipEndPoint) at System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket() at System.Runtime.Remoting.Channels.SocketCache.GetSocket(String machinePortAndSid, Boolean openNew) at System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.SendRequestWithRetry(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream) at System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, ITransportHeaders& responseHeaders, Stream& responseStream) at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at

     

    8- I try to connect to a single node 192.168.162.50 OR 192.168.162.51 and I don’t get any error.

     

     

    Thanks for your help!

     

    Friday, April 03, 2009 2:58 PM
  • Using all of the above works fine for us as well... except it seems that the client infers wsHttpBinding to the customBinding endpoint in the service in the client config.  However, we prefer to use basicHttpBinding only, based on the kind of clients potentially consuming the service.

    For example, when generating the proxy off the wsdl (using either svcutil or web service software factory's deploymenthost in VS2008), client binds to wsHttpBinding automatically.   Changing the binding on client manually to basicHttp results in the obvious "can't find endpoint" exception.

    Any ideas?

    Wednesday, May 20, 2009 7:34 PM
  • Would be quite appropriate for WCF to support this out of the box.
    Friday, May 29, 2009 11:22 AM
  • I am using your (Pedro's) solution as elaborated upon in Drew Marsh's blog entry: How To: SSL Passthrough with WCF --or-- TransportWithMessageCredential over plain HTTP

    With the solution as-is, even though I had the maxReceivedMessageSize property set to the max of 2147483647 in my web.config I was receiving the dreaded Error Message:

    The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

    In addition to altering the AddressFilterMode of my Services via an attribute [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)], and reconfiguring my client to establishSecurityContext="false" as indicated in other comments on this page.  I also had to modify the Clone method of my custom transport binding element so that it returned an actual clone based on settings in my configuration file rather than a default instance which contains default settings regardless of what is set in the configuration file.  It is fine as-is if the default settings serve your purposes.  However, I needed to be able to set the maxReceivedMessageSize property.

    My corrected custom binding element class is:

        public class HttpsViaProxyTransportBindingElement : HttpTransportBindingElement, ITransportTokenAssertionProvider {

            public HttpsViaProxyTransportBindingElement() : base() { }
            internal HttpsViaProxyTransportBindingElement(HttpsViaProxyTransportBindingElement elementToBeCloned) : base(elementToBeCloned) { }

            public override T GetProperty<T>(BindingContext context) {
                if (typeof(T) == typeof(ISecurityCapabilities))
                    return (T)(ISecurityCapabilities)new AutoSecuredHttpSecurityCapabilities();

                return base.GetProperty<T>(context);
            }

            public override BindingElement Clone() {
                return new HttpsViaProxyTransportBindingElement(this );
            }

            public System.Xml.XmlElement GetTransportTokenAssertion() {
                return null;
            }
        }

    Hope this helps someone...


    Regards,
    Vercellone
    Thursday, July 09, 2009 6:35 PM
  • In .Net 4.0 we have added a new switch to SecurityBindingElement named "AllowInsecureTransport". This will let users configure a Mixed-Mode security binding with just HTTP as the transport.

    However, please understand the security risk involved in enabling this knob. WCF does not encrypt the Username/Password tokens on the wire while using Mixed-Mode security. When this is sent over HTTP the UserName/Password will appear on the clear. The recommended place to turn this switch on will be in a controlled environment where the traffic between the client and service cannot be spoofed.

    Note, a QFE for 3.5 SP1 is also available for this fix.
    http://blogs.msdn.com/govindr
    Friday, July 10, 2009 2:36 AM

  • Note, a QFE for 3.5 SP1 is also available for this fix.
    http://blogs.msdn.com/govindr


    Do you have a link to this hotfix to expose the new AllowInsecureTransport?
    I too am experiencing this issue and rather then hacking the WCF channel stack, I'd rather have an approved solution from Microsoft.

    Thanks
    Tuesday, August 04, 2009 7:14 AM
  • Update on this thread.

    So I was able to get everything working from the service to WSDL using Pedro's sample.
    I also managed to get the hotfix for this new security mode and have tried it out in great anticipation, however I am unable to get it to work.
    You can find the hotfix details here http://support.microsoft.com/kb/971493


    I am not entirely sure the hotfix addresses the issue with SSL termination beyond the WCF service.

    I am using the TransportWithMessageCredential security mode on the ws2007 binding however the SSL terminates at the perimeter firewall so by the time it reaches my WCF service host it is in plaintext and on the HTTP scheme.

    So on the WCF host service I use the same ws2007 binding with the TransportWithMessageCredential security mode. This dictates that the end point be HTTPS which is the issue I was experiencing. With this hotfix, it exposes an attribute named enableUnsecuredResponse which I am lead to believe should solve my issue.

    So I create the custom binding that mimics the client side binding and also sets this enableUnsecuredResponse to true,  thinking then I can set my end point listen uri to a HTTP scheme, therefore satisfy the requirement of receiving the credentials over non SSL. However the service host refuses to start up as the binding configuration mandates HTTPS still.
    Friday, August 07, 2009 1:32 AM
  • Jimmy Q:

    How did you get the WSDL to 'work'? I am assuming that what you mean is that requesting the WSDL through http generated the proper UsernameToken WS-Security policy. I can't seem to figure out how to make that work.

    I want to implement Pedro's suggestion:
        S2) The custom transport element must implement ITransportTokenAssertionProvider and IPolicyExportExtension. In this case the WSDL policy will be correct but the port address will be HTTP and not HTTPS.

    The WCF HttpsTransportBindingElement implements the ITransportTokenAssertionProvider.GetTrasportTokenAssertion() method by simply returning null. However, it is less clear how to implement IPolicyExportExtension.ExportPolicy() because the HttpsTransportBindingElement uses the HttpTransportBindingElement's implementation which in turn calls an internal OnExportPolicy() method which the HttpsTransportBindingElement overrides and then that calls the internal SecurityBindingElement.ExportPolicy() method. A whole lot of internal to WCF plumbing, in other words.

    The bottom line is that it is not obvious to me how to implement Pedro's suggestion, but I was hoping that you could share how you got the WSDL to work...

    Thanks!
    Thursday, August 13, 2009 7:06 PM
  • Pedro,

    I appreciate the guidance you have provided here.  I have tried to implement your solution and have gotten the error with the ITransportTokenAssertionProvider.  I am relatively new to .Net and am wondering if you could provide sample code for implementing the ITransportTokenAssertionProvider and IPolicyExportExtension interfaces.

    Thanks,

    Larry Wilson

    Tuesday, December 15, 2009 4:49 PM
  • The hotfix from MS for the new security binding element is aavailable
    http://support.microsoft.com/kb/971831

    I have yet to give it a go but it sounds like it will fix the issues
    Thursday, December 17, 2009 6:57 AM
  • This is a hurdle that I am running into recently as well because I too have a BigIP I am trying to communicate through.  I think I followed all of your suggestions correctly, but I get the following error when I try to CreateChannel on the CustomBinding:  The provided URI scheme 'http' is invalid; expected 'https'

    I kinda expect that error since my URI is definitely an HTTPS address because that is what I need to use to access the WCF service.  Am I creating my channel incorrectly?

    EndpointAddress e = new EndpointAddress("https://mycompany.com/MyWCF.svc");

    WSHttpBinding b = new WSHttpBinding();
    b.ReaderQuotas.MaxStringContentLength = 1000000;
    b.ReaderQuotas.MaxArrayLength = 1000000;
    b.MaxReceivedMessageSize = 1000000;
    b.Security.Mode = SecurityMode.Transport;

    CustomBinding cb = new CustomBinding(b);
    cb.Elements.Remove<HttpsTransportBindingElement>();
    cb.Elements.Add(new HttpsViaProxyTransportBindingElement());

    IMyServicesWCF oMyServicesWCF = ChannelFactory<IMyServicesWCF>.CreateChannel(cb, e);

    If I try to change to use http://mycompany.com, there is a firewall setup to prevent that traffic, so I get the following error message: Could not connect to http://mycompany.com/MyWCF.svc.  TCP error code 10061: No connection could be made because the target machine actively refused it x.x.x.x:80.

    Maybe I am overlooking something.

     

    Wednesday, October 13, 2010 3:12 PM
  • It looks like I was over estimating something.  Even though we are going through a BigIP, we are not using any credentialing.  So, I am only using Transport security.  Therefore, I didn't need any of this code.  I just had to include the AddressFilterMode = AddresFilterMode.Any as a WCF ServiceBehavior on my host server.  Everything works!
    Thursday, October 14, 2010 11:58 PM
  • How do I get this same functionality using WCF RIA services?
    Tuesday, November 30, 2010 9:49 PM
  • Hi Vercellone,

    I am having this exact same problem. I tried what you did, but it just does not work for me. 

    Did you need to do anything special in order for this to work, I mean other then modifying the Clone method?

     

    I still keep getting: 

    The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. 

    No matter what values I change, I keep getting the above error.

     

    Thanks,

    Ray

    Thursday, May 26, 2011 1:19 PM
  • Drew,

    Back in 2009, I was able to get this solution to work for our web service.  We use SSL to the load balancer and then plain HTTP between the load balancer and the server.  The solutions worked great until recently.  Up to this point those consuming our service were using .Net-based clients.  Now we have users that are attempting to create Java or PHP clients.  Before I had to create this proxy binding, I had two endpoints: WSHTTPBinding and BasicHTTPBinding.  This handled both .Net and Java clients.  Now that I have the proxy binding, I can't get Java clients to work.  They keep getting a (400) Bad Request error.  Is there a variartion of this custom binding that I can create that will allow Java clients to connect?

     

    Thanks,

    Larry


    Friday, June 03, 2011 7:49 PM
  • did you update the client app.config file.. u need to change the number there too..
    Tuesday, June 21, 2011 10:02 PM
  • The hotfix from MS for the new security binding element is aavailable
    http://support.microsoft.com/kb/971831

    I have yet to give it a go but it sounds like it will fix the issues


    I have tried the hotfix/.net 4.0 and it works. I did have to do a few config permutations combinations before it worked. I have put together the details here http://www.suneet.net/FrmBlogViewer.aspx?blogid=65

    Cheers.


    MCTS BTS 2006
    Wednesday, September 28, 2011 3:14 PM
  • Solution name: PeterVargayServer (Console application)

    Project name: PeterVargayServer (Console application)

    File name: Program.cs

    using System;
    using System.ServiceModel;
    using System.IdentityModel.Selectors;
    
    namespace Namespace_PeterVargayServer
    {
        class Validator : UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                int i = 1;
            }
        }
    
        [ServiceContract]
        public interface ServiceClassInterface_PeterVargayServer
        {
            [OperationContract]
            string Echo(string input);
    
            [OperationContract]
            string[] BigEcho(string[] input);
        }
    
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
        public class ServiceClass_PeterVargayServer : ServiceClassInterface_PeterVargayServer
        {
            public string Echo(string input)
            {
                var userIdStr = ServiceSecurityContext.Current.PrimaryIdentity.Name;
                Console.WriteLine("\n\tServer Echo(string input) called:", input);
                Console.WriteLine("\tClient message:\t{0}\n", input);
                return input + " " + input;
            }
    
            public string[] BigEcho(string[] input)
            {
                var userIdStr = ServiceSecurityContext.Current.PrimaryIdentity.Name;
                Console.WriteLine("\n\tServer BigEcho(string[] input) called:", input);
                Console.WriteLine("\t{0} client messages", input.Length);
                return input;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                using (ServiceHost PeterVargayServer = new ServiceHost(typeof(ServiceClass_PeterVargayServer)))
                {
                    PeterVargayServer.Open();
                    Console.WriteLine("\nPress Enter key to Exit.");
                    Console.ReadLine();
                    PeterVargayServer.Close();
                }
            }
        }
    }
    

    Same solution, same project, File name: App.config

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <services>
          <service behaviorConfiguration="ServiceBehavior_PeterVargayServer" name="Namespace_PeterVargayServer.ServiceClass_PeterVargayServer">
            <endpoint address="net.tcp://localhost:9000/Endpoint_PeterVargayServer" binding="customBinding" bindingConfiguration="Binding_PeterVargayServer" contract="Namespace_PeterVargayServer.ServiceClassInterface_PeterVargayServer" />
          </service>
        </services>
        <bindings>
          <customBinding>
            <binding name="Binding_PeterVargayServer">
              <binaryMessageEncoding>
                <readerQuotas maxArrayLength="1000000"/>
              </binaryMessageEncoding>
              <security authenticationMode="UserNameOverTransport" />
              <PeterVargayTransport/>
            </binding>
          </customBinding>
        </bindings>
        <extensions>
          <bindingElementExtensions>
            <add name="PeterVargayTransport" type="Namespace_PeterVargayTransport.PeterVargayTransportElement, PeterVargayTransportLibrary"/>
          </bindingElementExtensions>
        </extensions>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehavior_PeterVargayServer">
              <serviceCredentials>
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Namespace_PeterVargayServer.Validator, NewTransportServer" />
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>
    

    Same solution, Project name: PeterVargayTransportLibrary (Class library)

    File name: PeterVargayTransportInstall.cs

    using System;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Configuration;
    using System.Net.Security;
    
    namespace Namespace_PeterVargayTransport
    {
        public class PeterVargayTransportElement : BindingElementExtensionElement
        {
            public override Type BindingElementType
            {
                get { return typeof(PeterVargayTransportElement); }
            }
    
            protected override BindingElement CreateBindingElement()
            {
                PeterVargayTransportBindingElement createdBindingElement = new PeterVargayTransportBindingElement();
                createdBindingElement.MaxReceivedMessageSize = 1000000;
                return createdBindingElement;
            }
        }
    
        public sealed class PeterVargayTransportBindingElement : TcpTransportBindingElement
        {
            public override BindingElement Clone()
            {
                PeterVargayTransportBindingElement createdBindingElement = new PeterVargayTransportBindingElement();
                createdBindingElement.MaxReceivedMessageSize = MaxReceivedMessageSize;
                return createdBindingElement;
            }
    
            public override T GetProperty<T>(BindingContext context)
            {
                if (typeof(T) == typeof(ISecurityCapabilities)) return (T)(object)new PeterVargaySecurityCapabilities();
                else return base.GetProperty<T>(context);
            }
        }
    
        public class PeterVargaySecurityCapabilities : ISecurityCapabilities
        {
            public ProtectionLevel SupportedRequestProtectionLevel
            {
                get { return ProtectionLevel.EncryptAndSign; }
            }
    
            public ProtectionLevel SupportedResponseProtectionLevel
            {
                get { return ProtectionLevel.EncryptAndSign; }
            }
    
            public bool SupportsClientAuthentication
            {
                get { return false; }
            }
    
            public bool SupportsClientWindowsIdentity
            {
                get { return false; }
            }
    
            public bool SupportsServerAuthentication
            {
                get { return true; }
            }
        }
    }
    

    Solution name: PeterVargayClient (Console application)

    Project name: PeterVargayClient (Console application)

    File name: Program.cs

    using System;
    
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName = "ServiceClassInterface_PeterVargayServer")]
    public interface ServiceClassInterface_PeterVargayClient
    {
        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/ServiceClassInterface_PeterVargayServer/Echo", ReplyAction = "http://tempuri.org/ServiceClassInterface_PeterVargayServer/EchoResponse")]
        string Echo(string input);
    
        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/ServiceClassInterface_PeterVargayServer/BigEcho", ReplyAction = "http://tempuri.org/ServiceClassInterface_PeterVargayServer/BigEchoResponse")]
        string[] BigEcho(string[] input);
    }
    
    public partial class ServiceClass_PeterVargayClient : System.ServiceModel.ClientBase<ServiceClassInterface_PeterVargayClient>, ServiceClassInterface_PeterVargayClient
    {
        public string Echo(string input)
        {
            return base.Channel.Echo(input);
        }
    
        public string[] BigEcho(string[] input)
        {
            return base.Channel.BigEcho(input);
        }
    }
    
    namespace Namespace_PeterVargayClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                ServiceClass_PeterVargayClient PeterVargayClient = new ServiceClass_PeterVargayClient();
    
                PeterVargayClient.ClientCredentials.UserName.UserName = "Peter Vargay";
                PeterVargayClient.ClientCredentials.UserName.Password = "this is my password";
    
                Console.WriteLine();
                Console.WriteLine("Calling Echo(string):");
                Console.WriteLine("Server responds: {0}", PeterVargayClient.Echo("Simple hello"));
    
                Console.WriteLine();
                Console.WriteLine("Calling BigEcho(string[]):");
                string[] messages = new string[64];
                for (int i = 0; i < 64; i++)
                {
                    messages[i] = "Hello " + i;
                }
    
                Console.WriteLine("Server responds: {0}", PeterVargayClient.BigEcho(messages));
    
                //Closing the client gracefully closes the connection and cleans up resources
                PeterVargayClient.Close();
    
                Console.WriteLine();
                Console.WriteLine("Press <ENTER> to terminate client.");
                Console.ReadLine();
            }
        }
    }
    

    Same solution, same project, File name: App.config

    <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint address="net.tcp://localhost:9000/Endpoint_PeterVargayServer" binding="customBinding" bindingConfiguration="Binding_PeterVargayClient" contract="ServiceClassInterface_PeterVargayServer"/> </client> <bindings> <customBinding> <binding name="Binding_PeterVargayClient"> <binaryMessageEncoding> <readerQuotas maxArrayLength="1000000"/> </binaryMessageEncoding> <security authenticationMode="UserNameOverTransport" /> <PeterVargayTransport/> </binding> </customBinding> </bindings> <extensions> <bindingElementExtensions> <add name="PeterVargayTransport" type="Namespace_PeterVargayTransport.PeterVargayTransportElement, PeterVargayTransportLibrary"/> </bindingElementExtensions> </extensions> </system.serviceModel> </configuration>

    Same solution, Project name: PeterVargayTransportLibrary (Class library) (same as at the server side)

    File name: PeterVargayTransportInstall.cs (same as at the server side)

    using System;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Configuration;
    using System.Net.Security;
    
    namespace Namespace_PeterVargayTransport
    {
        public class PeterVargayTransportElement : BindingElementExtensionElement
        {
            public override Type BindingElementType
            {
                get { return typeof(PeterVargayTransportElement); }
            }
    
            protected override BindingElement CreateBindingElement()
            {
                PeterVargayTransportBindingElement createdBindingElement = new PeterVargayTransportBindingElement();
                createdBindingElement.MaxReceivedMessageSize = 1000000;
                return createdBindingElement;
            }
        }
    
        public sealed class PeterVargayTransportBindingElement : TcpTransportBindingElement
        {
            public override BindingElement Clone()
            {
                PeterVargayTransportBindingElement createdBindingElement = new PeterVargayTransportBindingElement();
                createdBindingElement.MaxReceivedMessageSize = MaxReceivedMessageSize;
                return createdBindingElement;
            }
    
            public override T GetProperty<T>(BindingContext context)
            {
                if (typeof(T) == typeof(ISecurityCapabilities)) return (T)(object)new PeterVargaySecurityCapabilities();
                else return base.GetProperty<T>(context);
            }
        }
    
        public class PeterVargaySecurityCapabilities : ISecurityCapabilities
        {
            public ProtectionLevel SupportedRequestProtectionLevel
            {
                get { return ProtectionLevel.EncryptAndSign; }
            }
    
            public ProtectionLevel SupportedResponseProtectionLevel
            {
                get { return ProtectionLevel.EncryptAndSign; }
            }
    
            public bool SupportsClientAuthentication
            {
                get { return false; }
            }
    
            public bool SupportsClientWindowsIdentity
            {
                get { return false; }
            }
    
            public bool SupportsServerAuthentication
            {
                get { return true; }
            }
        }
    }
    

    Sunday, January 27, 2013 5:35 PM