Closed alexcrichton closed 8 years ago
Ah and this includes the refactoring in https://github.com/steffengy/schannel-rs/pull/5 of a MidHandshakeTlsStream
Oh hey looks like @steffengy your suggestion worked! CI is now passing.
So to make sure I understand it, the plan for trust roots is for each person to generate a CA, have it sign a certificate, delete the CA private key, install the CA certificate in the user's trust store, and then use the certificate in tests? That seems okay, though i'm a bit worried about adding to the users's trust root, even if we are disposing of the private key.
A possible alternative is to have each test create an ephemeral CA with an expiry of like 1 minute, install it and then uninstall when the test's done.
I should note that I don't think it's okay to have a git-tracked CA that people are supposed to install.
Also for creating the certificates it might be advisable to just use powershell? Is there any reason, we're not simply doing:
$cert = New-SelfSignedCertificate -DnsName localhost -CertStoreLocation cert:Localmachine\My
Export-Certificate -Cert $cert -FilePath localhost.cer -Type CERT
$pwd = ConvertTo-SecureString -String "foobar" -Force –AsPlainText
Export-PfxCertificate -Cert $cert -FilePath localhost.pfx -Password $pwd
Import-PfxCertificate -FilePath localhost.pfx -CertStoreLocation cert:\LocalMachine\Root -Password $pwd
in combination with these changes (GIST) to the PR?
(That should ofcourse also work for the user's personal store, for appveyor we'll still need the machine store)
@sfackler yeah it was actually my intention to check in all the certificates to git and contributors who wanted to run these tests would add the certificate to their trusted root store. I figured it's not that much of a risk as the private key is deleted immediately for the CA, so it can only ever sign one key (and that's just for localhost).
That being said I wouldn't mind creating ephemeral keys, I just couldn't figure out how to put something into the root trust store. I wouldn't mind trying it out though, means we may not need to check in any keys at all! You wouldn't happen to know the API off-hand to do that though would you?
@steffengy yeah I'd be fine with that although I'd prefer to make API calls directly rather than user power shell itself (just so a vanilla cargo test
works), but it'd all boil down to the same thing I think. Do you not need elevated permissions or dialog clicks to add something to the system certificate store?
@sfackler I've left the debug statements in for now but if you'd prefer I remove them all just wanted to confirm and I'll do so.
@alexcrichton You need elevated permissions (UAC) for the system certificate store and somehow a dialog pops up for the user (Root-) certificate store, as we've seen with the appveyor tests.
Using the API directly should show the same behavior, which might make a vanilla cargo test
difficult to implement that way (Except if you rely on elevated permissions). I'll do some investigating.
@alexcrichton https://github.com/steffengy/schannel-rs/commit/1a0c4edb43494987841f8f09b8ae8ef3e42f795e
With these changes (requires some cleaning up), a vanilla cargo test
works. (elevated)
It works the following way:
The certificate is valid for 5 minutes, which should (currently) be enough to run all tests.
But we probably should land this first, other stuff can be improved later.
I figured it's not that much of a risk as the private key is deleted immediately for the CA, so it can only ever sign one key (and that's just for localhost).
Whatever random person last regenerated the CA claims that they deleted the private key.
If elevated permissions are required to do the ephemeral thing, then a long-lived per-developer CA seems fine for now. I'd ideally like to get rid of the openssl stuff and generate them with native windows APIs (dogfood!) but that's not super necessary.
Thanks for the commit @steffengy! I'll take that strategy and wrap it all up in some APIs as well.
@alexcrichton Since we cannot bypass the elevation, the short validity may be counter-productive.
Probably setting the validity to one year is the best option, should not be a high security risk, since it's all locally generated. 962f7f928beefeb6fb6cf48d6e7d58bebd0498f0 should do that.
This would only require elevation on the first run, and probably is indeed the best option. (@sfackler also seems to prefer this)
Ok, I've pushed an updated using @steffengy's strategy. I opted to have certificates valid for a day as it basically just means that once a day if you run tests you have to click a dialog twice (once to delete, once to add), and it's somewhat less dangerous than a year.
I added an API or two along the way, but we still deal with creating the self-signed certificate in a raw fashion. Outstanding questions are:
CertStore::memory
? I don't think the final version is going to end up using it.CtlContext
for now?Let's leave CtlContext
private until we have a chance to add in signing, yeah, and same with Memory
.
Ok, left both of those private and I just removed the bits in the README
Made the password on pkcs12 optional and added an enum argument to add_cert
Woo!
These are a few commits which lead up to the conclusion of accepting server-side TLS connections. There's a bit more here than I initially anticipated, so a close eye would definitely be appreciated! The highlights are:
AcceptSecurityContext
instead of justInitializeSecurityContextW
to kick off the process of accepting a stream.CertStore
,CertContext
, andCtlContext
were all exposed to expose management of keys and such.The hard part about accepting connections on the server side is that we need the client to trust our custom certificate. Currently the only way I know to do this is to add a certificate to the global trusted root certificate store, so that's what this recommends! I added a script
test/create.sh
to create a custom CA, sign a certificate forlocalhost
, and then delete the CA key. That way those who want to run tests can add the custom CA. Each test should also be able to detect whether our custom CA is in the system store, and also provides the option to opt-out via environment variables.It's my intention that the tests run on AppVeyor, but I haven't tested that much, so I'll probably need some tweaks here and there for that.