Your question is rather unclear because every TLS connection is, by nature, bidirectional: it allows bytes to flow in both directions. I suppose that you mean connections where both the client and the server show a certificate.
On the client side, the server's certificate is accepted if all of the following hold:
- The server's certificate can be validated, i.e. put at the end of a chain of certificates, that begins with a trusted root, and all the names, signatures and various extensions match along the chain.
- The revocation status of all these certificates can be ascertained to be "not revoked" with fresh enough information (obtained from CRL and/or OCSP responses).
- The expected server name, i.e. the name which appears in the URL that the client uses, appears in the server's certificate (in the
Subject Alt Name extension, as per RFC 2818).
By default, the .NET client code will rely on the set of trusted roots valid for the account under which the client code runs; this is a fusion of the "Root" certificate stores for the "current user", "local machine" and "enterprise".
On the server side, the client's certificate can be validated by IIS. In that case, IIS has two modes:
clientCertificateMappingAuthentication: the client certificate is validated against the set of trusted roots of the server; the issuing CA (the one which immediately signed the client certificate) must be part of the enterprise NTAuth store; and then the UPN is extracted from the client certificate and looked up in the local Active Directory server. The part about the "NTAuth" store is where you can restrict client certificates.
iisClientCertificateMappingAuthentication: IIS does the job, not the AD server (i.e. that's what you do if the server is not part of a domain). After validation against trusted roots, IIS can do a "one-to-one mapping" in which a client certificate will be accepted only if it is bit-to-bit identical to a certificate registered into IIS, and then mapped to a specific identity.
There are many configuration options. And you can programmatically override most parts of the process. For instance, see this page for how to configure on the server a custom class for validating client certificates; with such a class, you can do everything you wish to do (but beware, you can also do some very weak things, such as trusting the certificate on face value without any validation).