summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/tests/unit/tlsserver/cmd/DelegatedCredentialsServer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'security/manager/ssl/tests/unit/tlsserver/cmd/DelegatedCredentialsServer.cpp')
-rw-r--r--security/manager/ssl/tests/unit/tlsserver/cmd/DelegatedCredentialsServer.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/security/manager/ssl/tests/unit/tlsserver/cmd/DelegatedCredentialsServer.cpp b/security/manager/ssl/tests/unit/tlsserver/cmd/DelegatedCredentialsServer.cpp
new file mode 100644
index 0000000000..5f12756425
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/DelegatedCredentialsServer.cpp
@@ -0,0 +1,142 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This is a standalone server used to test Delegated Credentials
+// (see: https://tools.ietf.org/html/draft-ietf-tls-subcerts-03).
+//
+// The client is expected to connect, initiate an SSL handshake (with SNI
+// to indicate which "server" to connect to), and verify the certificate.
+// If all is good, the client then sends one encrypted byte and receives that
+// same byte back.
+// This server also has the ability to "call back" another process waiting on
+// it. That is, when the server is all set up and ready to receive connections,
+// it will connect to a specified port and issue a simple HTTP request.
+
+#include <iostream>
+
+#include "TLSServer.h"
+
+#include "sslexp.h"
+
+using namespace mozilla;
+using namespace mozilla::test;
+
+struct DelegatedCertHost {
+ const char* mHostName;
+ const char* mCertName;
+ const char* mDCKeyNick;
+ bool mEnableDelegatedCredentials;
+};
+
+const PRUint32 kDCValidFor = 60 * 60 * 24 * 7 /* 1 week (seconds) */;
+
+// {host, eeCert, dcCert, enableDC}
+const DelegatedCertHost sDelegatedCertHosts[] = {
+ {"delegated-enabled.example.com", "delegated-ee", "delegated.key", true},
+ {"standard-enabled.example.com", "default-ee", "delegated.key", true},
+ {"delegated-disabled.example.com", "delegated-ee",
+ /* anything non-null */ "delegated.key", false},
+ {nullptr, nullptr, nullptr, false}};
+
+int32_t DoSNISocketConfig(PRFileDesc* aFd, const SECItem* aSrvNameArr,
+ uint32_t aSrvNameArrSize, void* aArg) {
+ const DelegatedCertHost* host =
+ GetHostForSNI(aSrvNameArr, aSrvNameArrSize, sDelegatedCertHosts);
+ if (!host) {
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ if (gDebugLevel >= DEBUG_VERBOSE) {
+ std::cerr << "Identified host " << host->mHostName << std::endl;
+ }
+
+ UniqueCERTCertificate delegatorCert(
+ PK11_FindCertFromNickname(host->mCertName, nullptr));
+ if (!delegatorCert) {
+ PrintPRError("PK11_FindCertFromNickname failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
+ if (!slot) {
+ PrintPRError("PK11_GetInternalKeySlot failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ SSLExtraServerCertData extra_data = {ssl_auth_null,
+ /* Filled in by callee */ nullptr,
+ nullptr,
+ nullptr,
+ /* DC */ nullptr,
+ /* DC PrivKey */ nullptr};
+
+ UniqueSECKEYPrivateKey delegatorPriv(
+ PK11_FindKeyByDERCert(slot.get(), delegatorCert.get(), nullptr));
+ if (!delegatorPriv) {
+ PrintPRError("PK11_FindKeyByDERCert failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ // Find the DC keypair by the file (nick) name.
+ ScopedAutoSECItem dc;
+ UniqueSECKEYPrivateKey dcPriv;
+ if (host->mEnableDelegatedCredentials) {
+ if (gDebugLevel >= DEBUG_VERBOSE) {
+ std::cerr << "Enabling a delegated credential for host "
+ << host->mHostName << std::endl;
+ }
+
+ if (PK11_NeedLogin(slot.get())) {
+ SECStatus rv = PK11_Authenticate(slot.get(), PR_TRUE, nullptr);
+ if (rv != SECSuccess) {
+ PrintPRError("PK11_Authenticate failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+ }
+ UniqueSECKEYPrivateKeyList list(PK11_ListPrivKeysInSlot(
+ slot.get(), const_cast<char*>(host->mDCKeyNick), nullptr));
+ if (!list) {
+ PrintPRError("PK11_ListPrivKeysInSlot failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+ SECKEYPrivateKeyListNode* node = PRIVKEY_LIST_HEAD(list);
+
+ dcPriv.reset(SECKEY_CopyPrivateKey(node->key));
+ if (!dcPriv) {
+ PrintPRError("PK11_ListPrivKeysInSlot could not find dcPriv");
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ UniqueSECKEYPublicKey dcPub(SECKEY_ConvertToPublicKey(dcPriv.get()));
+ if (!dcPub) {
+ PrintPRError("SECKEY_ConvertToPublicKey failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ // Create and set the DC.
+ if (SSL_DelegateCredential(delegatorCert.get(), delegatorPriv.get(),
+ dcPub.get(), ssl_sig_ecdsa_secp384r1_sha384,
+ kDCValidFor, PR_Now(), &dc) != SECSuccess) {
+ PrintPRError("SSL_DelegateCredential failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+ extra_data.delegCred = &dc;
+ extra_data.delegCredPrivKey = dcPriv.get();
+
+ // The list should only have a single key.
+ PORT_Assert(PRIVKEY_LIST_END(PRIVKEY_LIST_NEXT(node), list));
+ }
+
+ if (ConfigSecureServerWithNamedCert(aFd, host->mCertName, nullptr, nullptr,
+ &extra_data) != SECSuccess) {
+ PrintPRError("ConfigSecureServerWithNamedCert failed");
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[]) {
+ return StartServer(argc, argv, DoSNISocketConfig, nullptr);
+}