I noticed that SSL.handshake supports certificate authentication. That's actually rather nice, however, I've got a problem with the way it's controlled. If the settings are in handshake, there's no way to change them when using sslport, or any other function that uses sslfile directly. Would it make more sense to move those settings to the context object? Would anyone be terribly put out if I did that (or at least added the option)? Any thoughts?
Bill
I think that is an area of Pike that is somewhat lacking in caring maintenance, even though the Roxen people of course still tend to the parts they use themselves. IMO, it would be nice of you to improve and extend (and perhaps even document some :-) the API:s there, with extra credit for backwards compatibility.
/ Johan Sundström (Achtung Liebe!)
Previous text:
2004-01-13 22:56: Subject: SSL part two
I noticed that SSL.handshake supports certificate authentication. That's actually rather nice, however, I've got a problem with the way it's controlled. If the settings are in handshake, there's no way to change them when using sslport, or any other function that uses sslfile directly. Would it make more sense to move those settings to the context object? Would anyone be terribly put out if I did that (or at least added the option)? Any thoughts?
Bill
/ Brevbäraren
Well, I'll try to help out where possible, though I get nervous when fiddling with something someone has perhaps done for a specific reason. In the case of the sslfile problem, it's not at all clear to me why the code is what it is. It's entirely possible I'm missing something that's completely over my head.
As a show of my hopefully good intentions, I've fixed the context and handshake to look in the context for client certificate settings first. I've also added some convenience functions to Standards.PKCS.Certificates for making it easier to get the right value for the certificate authorities field in context.
Now it appears that the certificate is requested, and sent back to the server, which is a big step in the right direction.
Bill
On Wed, 14 Jan 2004, Johan Sundstr�m (Achtung Liebe!) @ Pike (-) developers forum wrote:
I think that is an area of Pike that is somewhat lacking in caring maintenance, even though the Roxen people of course still tend to the parts they use themselves. IMO, it would be nice of you to improve and extend (and perhaps even document some :-) the API:s there, with extra credit for backwards compatibility.
/ Johan Sundstr�m (Achtung Liebe!)
Nice work. Some comments after a quick read'n'grep of the code:
I think the authorities and auth_level should be removed from handshake.pike. Having the same variables in handshake.pike and context.pike is confusing and invites bugs.
I don't see where the certificates are used for verifiction. Is that done at all? The steps needed are, for both client and server verification:
1. Check that root of the certificate chain is trusted. First issuer should be the subject and issuer of a certificate in the authorites list (those are "self-signed", i.e. subject = issuer).
2. Check that the chain is valid, i.e. that subject of one certificate is the issuer of the next, and that certificates have the proper flags set (thus is unfortunately more hairy than it should. Peter Gutmanns x509 guide is required reading).
3. Dig out the public key from the certificates, and use that to verify the signature that the peer sends. The point is that we must ensure that the peer has access to the private key corresponding to the certificate.
4. On the client side, verify that the Common Name attribute of the server's certificate matches the hostname (this perhaps best left to Protocols.HTTPS, or other users of SSL, since it's https specific).
5. On the server side, match the distinguished name of the clients certificate against some database or rules about who should get access. Again, perhaps all the SSL module should do is to present the common name of the client and of the root issuer to the user of the application using SSL.
I tried to find the code doing 3. THere is some code under the case STATE_server_wait_for_verify, HANDSHAKE_certificate_verify, which seems to boil down to a call of rsa_verify via session->cipher_spec->verify. However, that seems broken, because it uses an rsa key stored in the context, which should be our *own* key, not the peer's.
I think the received certificate chain, as well issuer/subject and other information we dig out from it, should be saved in the session object.
/ Niels Möller (vässar rödpennan)
Previous text:
2004-01-14 23:21: Subject: Re: SSL part two
Well, I'll try to help out where possible, though I get nervous when fiddling with something someone has perhaps done for a specific reason. In the case of the sslfile problem, it's not at all clear to me why the code is what it is. It's entirely possible I'm missing something that's completely over my head.
As a show of my hopefully good intentions, I've fixed the context and handshake to look in the context for client certificate settings first. I've also added some convenience functions to Standards.PKCS.Certificates for making it easier to get the right value for the certificate authorities field in context.
Now it appears that the certificate is requested, and sent back to the server, which is a big step in the right direction.
Bill
On Wed, 14 Jan 2004, Johan Sundström (Achtung Liebe!) @ Pike (-) developers forum wrote:
I think that is an area of Pike that is somewhat lacking in caring maintenance, even though the Roxen people of course still tend to the parts they use themselves. IMO, it would be nice of you to improve and extend (and perhaps even document some :-) the API:s there, with extra credit for backwards compatibility.
/ Johan Sundström (Achtung Liebe!)
/ Brevbäraren
I think the authorities and auth_level should be removed from handshake.pike. Having the same variables in handshake.pike and context.pike is confusing and invites bugs.
I thought the same, but didn't want to delete it on the chance someone else is counting on it being there. I will remove the duplicate copy.
I don't see where the certificates are used for verifiction. Is that done at all?
I don't believe that they're currently looked at for validity (it seems that it might be possible to send gibberish and have pikessl accept it.
I think the received certificate chain, as well issuer/subject and other information we dig out from it, should be saved in the session object.
That sounds like a good place to me. One thing that might be worth noting is that the sslfile class (if i remember correctly) sets the connection as static, which means that you can't access the session from outside sslfile. It was for this reason that I started adding accessors. Would it be better to have the connection/session not be static?
Bil
That sounds like a good place to me. One thing that might be worth noting is that the sslfile class (if i remember correctly) sets the connection as static, which means that you can't access the session from outside sslfile. It was for this reason that I started adding accessors. Would it be better to have the connection/session not be static?
It's hard to say what's right without a few application to look at. It definitely should be possible to get access to some or all of the certificate chain from an sslfile. One simple way is to just add a method
sslfile->get_peer_cert_chain() { return session->peer_cert_chain; }
but perhaps one should also have some more friendlier functions to be used by clients that do https-style server authentications.
/ Niels Möller (vässar rödpennan)
Previous text:
2004-01-15 21:26: Subject: Re: SSL part two
I think the authorities and auth_level should be removed from handshake.pike. Having the same variables in handshake.pike and context.pike is confusing and invites bugs.
I thought the same, but didn't want to delete it on the chance someone else is counting on it being there. I will remove the duplicate copy.
I don't see where the certificates are used for verifiction. Is that done at all?
I don't believe that they're currently looked at for validity (it seems that it might be possible to send gibberish and have pikessl accept it.
I think the received certificate chain, as well issuer/subject and other information we dig out from it, should be saved in the session object.
That sounds like a good place to me. One thing that might be worth noting is that the sslfile class (if i remember correctly) sets the connection as static, which means that you can't access the session from outside sslfile. It was for this reason that I started adding accessors. Would it be better to have the connection/session not be static?
Bil
/ Brevbäraren
I think the authorities and auth_level should be removed from handshake.pike. Having the same variables in handshake.pike and context.pike is confusing and invites bugs.
Good idea, this is done.
- Check that root of the certificate chain is trusted. First issuer should be the subject and issuer of a certificate in the authorites list (those are "self-signed", i.e. subject = issuer).
I'm not sure this is correct, as you could have a second tier authority, in which case your "root authority" isn't self signed. Either way, coding this would just enforce our view of what a valid certificate was based on a very narrow usage scenario. Perhaps it would be better to pass the certificate or issuer to a callback, which would then give a thumbs up or down on the presented certificate (strictly from a "name on the front door sort of way, no validity checks made).
I'm thinking I might be getting in a little too deep, so comments are welcome.
Bill
- Check that root of the certificate chain is trusted. First issuer should be the subject and issuer of a certificate in the authorites list (those are "self-signed", i.e. subject = issuer).
I'm not sure this is correct, as you could have a second tier authority, in which case your "root authority" isn't self signed.
It's years since I read the SSL spec, but I wouldn't be surprised if it says that the first cert in the list has to be a root "self-signed" cert.
But it doesn't really matter, if you (as a verifier) provide a list of "trusted" root certs to the SSL module, then it could accept the chain if the first cert is either equal to one of the trusted certs, or issued by one of the trusted certs. As far a I can see, there's no difference from a security point of view.
Perhaps it would be better to pass the certificate or issuer to a callback, which would then give a thumbs up or down on the presented certificate
That's a nice option to have, but I don't think it should be the default behaviour, as it makes it unnecessarily difficult to get the security right.
An SSL client must to examine the certificate anyway, to compare the URL hostname to the certified "Common Name". I can't say if that should be a callback, or some attribute that can be examined after a successful connect. And that's all about server certs. What rules people want to apply to client certificates I don't know, but it might make some sense with an ACL where each entry is a trusted root cert and a specification of a subtree in the x.500 directory..
/ Niels Möller (vässar rödpennan)
Previous text:
2004-01-23 21:06: Subject: Re: SSL part two
I think the authorities and auth_level should be removed from handshake.pike. Having the same variables in handshake.pike and context.pike is confusing and invites bugs.
Good idea, this is done.
- Check that root of the certificate chain is trusted. First issuer should be the subject and issuer of a certificate in the authorites list (those are "self-signed", i.e. subject = issuer).
I'm not sure this is correct, as you could have a second tier authority, in which case your "root authority" isn't self signed. Either way, coding this would just enforce our view of what a valid certificate was based on a very narrow usage scenario. Perhaps it would be better to pass the certificate or issuer to a callback, which would then give a thumbs up or down on the presented certificate (strictly from a "name on the front door sort of way, no validity checks made).
I'm thinking I might be getting in a little too deep, so comments are welcome.
Bill
/ Brevbäraren
It's years since I read the SSL spec, but I wouldn't be surprised if it says that the first cert in the list has to be a root "self-signed" cert.
Well, I think maybe there are two matters here: 1) the list of "authorities", which is basically a list of certificate signers that we're willing to accept as client authentication. These, of themselves, wouldn't be chains, but rather just a single cert signed by a "known" authority, the chain of which would presumably be specified elsewhere.
The second issue is that of how to verify what is provided by the client, which might or might not be a full chain leading to a self signed certificate.
Either way, you are correct, the root of the chain has to be self signed (otherwise it wouldn't be the root, would it? :)) Currently, there is no infrastructure at all for keeping a list of certificate authorities, so that will need to be added.
Once the infrastructure is present, and has some methods for examining and testing the relevent parts of certificates, it should be simple for us to have a default behavior as well as a callback that provides alternate behaviors (necessary for more complex applications).
Bill
I've added some peer certificate verification code. It makes sure the chain is unbroken, that the signatures are correct, and that the root of the certificate chain provided is trusted.
I haven't yet added code to check the dates on the certificates, but should get to that soon. I also haven't done anything with the flags (anyone up for that???).
I was thinking about adding an optional callback that would be called in the event of a problem with one of the certificates (wrong flags, untrusted, etc) so that an application could make a decision about whether to override the verification failure. Any thoughts?
Bill
Nice.
I don't think it makes much sense with per-certificate callbacks. I think it should be enough to report the kind of problem to the application (certificate chain broken, root cert not trusted, signatures that aren't valid, some certificate in the chain has expired). And then give the application the option of accepting the peer anyway.
As for flags, Peter Gutmanns style guide should give some guidance. I don't remember much of the details. Guess one should start with the flags of the "critical" kind, and refuse to accept certificates with unknown or unimplemented critical flags.
One important part (although perhaps not very exciting) is testcases that exersize all the failure modes listed above.
/ Niels Möller (vässar rödpennan)
Previous text:
2004-02-02 22:15: Subject: Re: SSL part two
I've added some peer certificate verification code. It makes sure the chain is unbroken, that the signatures are correct, and that the root of the certificate chain provided is trusted.
I haven't yet added code to check the dates on the certificates, but should get to that soon. I also haven't done anything with the flags (anyone up for that???).
I was thinking about adding an optional callback that would be called in the event of a problem with one of the certificates (wrong flags, untrusted, etc) so that an application could make a decision about whether to override the verification failure. Any thoughts?
Bill
/ Brevbäraren
I don't think it makes much sense with per-certificate callbacks. I think it should be enough to report the kind of problem to the application (certificate chain broken, root cert not trusted, signatures that aren't valid, some certificate in the chain has expired). And then give the application the option of accepting the peer anyway.
I was thinking of one callback at the end of verification. It would have to provide information about all failures, though, not just the first, as it would be possible to have a really messed up chain with bad flags, exirations and more.
The reason I say callback, is because you'd have to get an answer to override before the result of the verification were passed back to ssl.handshake, otherwise the connection would be broken immediately. It is possible that I'm missing an obvious technique.
As for flags, Peter Gutmanns style guide should give some guidance. I don't remember much of the details. Guess one should start with the flags of the "critical" kind, and refuse to accept certificates with unknown or unimplemented critical flags.
One thing I've noticed is that at least for some of the OpenSSL created certificates I've run across, the BasicConstraint extension is invalid. It should contain both a boolean and a constraint, which is present in the comodo certs I've looked at, but the openssl certs seem to be missing the boolean. Does this indicate a bug in the certificate, or is it ok to violate syntax (perhaps that's what the DEFAULT means in the definition) like this?
One important part (although perhaps not very exciting) is testcases that exersize all the failure modes listed above.
Yes, I figured they'd need to be done at somepoint. Any thoughts on the best way to do this (generate our own certs, provide some "bogus" certs to test agains, etc)?
Bill
Yes, I figured they'd need to be done at somepoint. Any thoughts on the best way to do this (generate our own certs, provide some "bogus" certs to test agains, etc)?
I think it's easiest to construct one's own certs, and build valid and invalid test chains from that. (To create a cert with an invalid signature, easiest way is to create a valid cert, and then change one byte either in the subject name or in the signature string (these two ways may lead to different failure modes).
/ Niels Möller (vässar rödpennan)
Previous text:
2004-02-05 19:31: Subject: Re: SSL part two
I don't think it makes much sense with per-certificate callbacks. I think it should be enough to report the kind of problem to the application (certificate chain broken, root cert not trusted, signatures that aren't valid, some certificate in the chain has expired). And then give the application the option of accepting the peer anyway.
I was thinking of one callback at the end of verification. It would have to provide information about all failures, though, not just the first, as it would be possible to have a really messed up chain with bad flags, exirations and more.
The reason I say callback, is because you'd have to get an answer to override before the result of the verification were passed back to ssl.handshake, otherwise the connection would be broken immediately. It is possible that I'm missing an obvious technique.
As for flags, Peter Gutmanns style guide should give some guidance. I don't remember much of the details. Guess one should start with the flags of the "critical" kind, and refuse to accept certificates with unknown or unimplemented critical flags.
One thing I've noticed is that at least for some of the OpenSSL created certificates I've run across, the BasicConstraint extension is invalid. It should contain both a boolean and a constraint, which is present in the comodo certs I've looked at, but the openssl certs seem to be missing the boolean. Does this indicate a bug in the certificate, or is it ok to violate syntax (perhaps that's what the DEFAULT means in the definition) like this?
One important part (although perhaps not very exciting) is testcases that exersize all the failure modes listed above.
Yes, I figured they'd need to be done at somepoint. Any thoughts on the best way to do this (generate our own certs, provide some "bogus" certs to test agains, etc)?
Bill
/ Brevbäraren
I think your right.
All ssl configuration belongs in the context object. If that's not the case for information related to client certificates, that's a bug that should be fixed.
/ Niels Möller (vässar rödpennan)
Previous text:
2004-01-13 22:56: Subject: SSL part two
I noticed that SSL.handshake supports certificate authentication. That's actually rather nice, however, I've got a problem with the way it's controlled. If the settings are in handshake, there's no way to change them when using sslport, or any other function that uses sslfile directly. Would it make more sense to move those settings to the context object? Would anyone be terribly put out if I did that (or at least added the option)? Any thoughts?
Bill
/ Brevbäraren
pike-devel@lists.lysator.liu.se