Typically, this scenario is addressed by sending a certificate request anyway and allowing for an empty certificate message (sent by the client) when the certificate is not needed. This is is what
SSLVerifyClient optional does (also the difference between need and want authentication in Java). This is the establish way of dealing with servers for which not all clients may need to present a certificate, and clearly allowed within the TLS specification (Section 7.4.6):
This is the first message the client can send after receiving a server
hello done message. This message is only sent if the server requests
a certificate. If no suitable certificate is available, the client
SHOULD send a certificate message containing no certificates. That
is, the certificate_list structure has a length of zero. If client
authentication is required by the server for the handshake to
continue, it may respond with a fatal handshake failure alert.
You might be able to give an hint using the Client Certificate URLs extension, although I don't think this is the intent of this extension (that would be a bit of a trick). I'm not aware of this extension being widely supported, which would certainly cause practical problems if you want to run this on a production system.
If you really don't want the client to be prompted for a certificate in certain cases, what you may be able to do is to use the Server Name Indication (SNI) extension, which is increasingly supported, thereby offering two distinct server configurations depending on which server name the client is requesting. I haven't tried, but I presume that if you configure two distinct virtual hosts with Apache Httpd using SNI, and only one of them is configured to request a client-certificate, you may be able to achieve your goal.
The downside is that you would need to set up two host names for the same server, but that's not as big a deal as other solutions that may require some programming.
For example, even if you assumed that the source IP address was a sufficient discriminator between your two use cases, in Java, you would probably have to implement the server as listening to a plain
ServerSocket (not an
SSLServerSocket), check from which IP address it's coming from, convert the accepted socket into an
SSLSocket in server mode and configure it at the stage (before the handshake has taken place) to request a client certificate or not, and only then trigger the handshake. (I haven't tried any of this, but that would seem a reasonable way to handle such a case.) This would certainly be more complex than creating an
SSLServerSocket and accepting pre-configured
SSLSockets from it directly. I would imagine that other SSL/TLS stacks (in C or others) wouldn't handle such a case very cleanly either.