summaryrefslogtreecommitdiff
path: root/test/server
diff options
context:
space:
mode:
Diffstat (limited to 'test/server')
-rw-r--r--test/server/serfcacert.pem50
-rw-r--r--test/server/serfrootcacert.pem60
-rw-r--r--test/server/serfservercert.pem50
-rw-r--r--test/server/serfserverkey.pem18
-rw-r--r--test/server/test_server.c171
-rw-r--r--test/server/test_server.h94
-rw-r--r--test/server/test_sslserver.c252
7 files changed, 618 insertions, 77 deletions
diff --git a/test/server/serfcacert.pem b/test/server/serfcacert.pem
new file mode 100644
index 0000000..f8324cd
--- /dev/null
+++ b/test/server/serfcacert.pem
@@ -0,0 +1,50 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 1048578 (0x100002)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Root CA, CN=Serf Root CA/emailAddress=serfrootca@example.com
+ Validity
+ Not Before: Apr 13 11:28:06 2013 GMT
+ Not After : Apr 13 11:28:06 2014 GMT
+ Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite CA, CN=Serf CA/emailAddress=serfca@example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:ab:10:e4:6c:e6:31:23:9f:f3:5d:a9:22:12:81:
+ 9a:b5:8d:7b:4d:8e:b7:8c:1f:2e:14:81:03:bb:44:
+ 50:79:d0:42:8c:f4:0f:86:f1:00:76:03:87:ac:a0:
+ a2:3a:6f:ab:b5:17:81:ce:86:d4:35:70:4c:a1:cb:
+ 2c:67:17:9b:06:b3:4f:1e:18:ce:9b:5d:15:8e:10:
+ 24:a5:9c:73:43:fe:b4:68:a8:65:50:58:31:3b:df:
+ b7:f8:33:d0:5d:af:c6:b1:ec:ed:73:09:cd:3e:42:
+ 6a:95:13:d0:bd:b8:9d:5a:23:24:fc:34:4f:b0:72:
+ 4b:15:e5:b4:13:4b:bc:24:85
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 46:db:5f:de:b5:66:f8:9b:04:da:3c:f5:1a:99:98:c8:1f:57:
+ f8:1e:7a:f9:b4:1e:7e:21:97:11:70:64:2c:58:90:00:28:09:
+ 12:10:81:fb:27:01:37:4b:22:9a:56:95:42:e2:eb:4b:b5:8b:
+ bd:9f:09:4b:34:15:2f:ce:1e:dd:71:8c:40:0c:8a:6a:fe:a6:
+ 12:f1:68:b7:f3:be:e4:69:fb:b6:3b:c8:c4:13:9c:ae:09:d1:
+ dc:51:b9:77:90:14:2b:65:83:30:12:76:ef:33:24:65:99:63:
+ 2e:62:d7:21:db:e5:d9:a6:2d:05:17:a1:5e:ef:6f:26:f6:2f:
+ 96:b4
+-----BEGIN CERTIFICATE-----
+MIICwTCCAioCAxAAAjANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UEBhMCQkUxEDAO
+BgNVBAgMB0FudHdlcnAxETAPBgNVBAcMCE1lY2hlbGVuMR8wHQYDVQQKDBZJbiBT
+ZXJmIHdlIHRydXN0LCBJbmMuMRswGQYDVQQLDBJUZXN0IFN1aXRlIFJvb3QgQ0Ex
+FTATBgNVBAMMDFNlcmYgUm9vdCBDQTElMCMGCSqGSIb3DQEJARYWc2VyZnJvb3Rj
+YUBleGFtcGxlLmNvbTAeFw0xMzA0MTMxMTI4MDZaFw0xNDA0MTMxMTI4MDZaMIGg
+MQswCQYDVQQGEwJCRTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVs
+ZW4xHzAdBgNVBAoMFkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xFjAUBgNVBAsMDVRl
+c3QgU3VpdGUgQ0ExEDAOBgNVBAMMB1NlcmYgQ0ExITAfBgkqhkiG9w0BCQEWEnNl
+cmZjYUBleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxDk
+bOYxI5/zXakiEoGatY17TY63jB8uFIEDu0RQedBCjPQPhvEAdgOHrKCiOm+rtReB
+zobUNXBMocssZxebBrNPHhjOm10VjhAkpZxzQ/60aKhlUFgxO9+3+DPQXa/Gsezt
+cwnNPkJqlRPQvbidWiMk/DRPsHJLFeW0E0u8JIUCAwEAATANBgkqhkiG9w0BAQUF
+AAOBgQBG21/etWb4mwTaPPUamZjIH1f4Hnr5tB5+IZcRcGQsWJAAKAkSEIH7JwE3
+SyKaVpVC4utLtYu9nwlLNBUvzh7dcYxADIpq/qYS8Wi3877kafu2O8jEE5yuCdHc
+Ubl3kBQrZYMwEnbvMyRlmWMuYtch2+XZpi0FF6Fe728m9i+WtA==
+-----END CERTIFICATE-----
diff --git a/test/server/serfrootcacert.pem b/test/server/serfrootcacert.pem
new file mode 100644
index 0000000..440f39f
--- /dev/null
+++ b/test/server/serfrootcacert.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 14060582211199810902 (0xc321390661bdbd56)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Root CA, CN=Serf Root CA/emailAddress=serfrootca@example.com
+ Validity
+ Not Before: Apr 13 11:19:14 2013 GMT
+ Not After : Apr 11 11:19:14 2023 GMT
+ Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Root CA, CN=Serf Root CA/emailAddress=serfrootca@example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:e1:dd:69:ea:ac:fd:f2:73:81:ec:ed:b6:b1:0e:
+ 70:23:8c:01:6d:ab:f3:43:ab:0f:fc:8a:6a:23:eb:
+ 6c:48:37:c9:c0:8f:29:61:00:7e:89:1f:00:d1:68:
+ dd:70:de:bd:34:32:0e:41:ac:f9:ea:c1:a6:0d:b5:
+ 65:be:5c:9e:f1:b4:27:54:c1:79:61:63:d4:2d:06:
+ 11:5f:cc:4c:d9:d3:ef:4e:da:9f:a4:26:16:cb:3f:
+ 86:f8:21:7d:c5:3a:32:34:c8:cb:85:ad:c4:3f:e4:
+ b3:ad:8e:a7:67:9e:0c:3b:5a:58:29:5f:ce:96:3b:
+ e3:f5:ca:42:eb:7b:44:d5:75
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ B2:3E:19:35:C1:C4:4F:23:79:ED:BF:E8:DC:5C:31:03:F0:2F:15:77
+ X509v3 Authority Key Identifier:
+ keyid:B2:3E:19:35:C1:C4:4F:23:79:ED:BF:E8:DC:5C:31:03:F0:2F:15:77
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ c3:ec:1f:3e:b1:87:d0:80:10:f9:bf:73:1b:38:d4:b1:b7:80:
+ 4d:ea:20:c1:79:7d:f5:58:42:11:13:28:ab:b1:b4:0a:88:9c:
+ 20:4d:9c:b5:5a:41:28:5e:f6:69:5e:55:bb:e2:1a:b9:c6:62:
+ 38:86:32:7b:93:28:ca:9e:af:d1:06:f9:93:c2:5d:92:c0:25:
+ 68:6a:e1:fe:85:2a:19:a7:6b:17:4d:23:9a:72:d6:d0:c1:80:
+ ff:74:10:8b:62:7a:11:c3:9a:87:2a:e4:7d:d1:8c:72:a6:bf:
+ c1:3b:d8:b8:33:c0:ff:b0:f7:d6:0e:a3:dd:36:fe:8a:41:a0:
+ 98:cc
+-----BEGIN CERTIFICATE-----
+MIIDLDCCApWgAwIBAgIJAMMhOQZhvb1WMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD
+VQQGEwJCRTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVsZW4xHzAd
+BgNVBAoMFkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xGzAZBgNVBAsMElRlc3QgU3Vp
+dGUgUm9vdCBDQTEVMBMGA1UEAwwMU2VyZiBSb290IENBMSUwIwYJKoZIhvcNAQkB
+FhZzZXJmcm9vdGNhQGV4YW1wbGUuY29tMB4XDTEzMDQxMzExMTkxNFoXDTIzMDQx
+MTExMTkxNFowga4xCzAJBgNVBAYTAkJFMRAwDgYDVQQIDAdBbnR3ZXJwMREwDwYD
+VQQHDAhNZWNoZWxlbjEfMB0GA1UECgwWSW4gU2VyZiB3ZSB0cnVzdCwgSW5jLjEb
+MBkGA1UECwwSVGVzdCBTdWl0ZSBSb290IENBMRUwEwYDVQQDDAxTZXJmIFJvb3Qg
+Q0ExJTAjBgkqhkiG9w0BCQEWFnNlcmZyb290Y2FAZXhhbXBsZS5jb20wgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAOHdaeqs/fJzgezttrEOcCOMAW2r80OrD/yK
+aiPrbEg3ycCPKWEAfokfANFo3XDevTQyDkGs+erBpg21Zb5cnvG0J1TBeWFj1C0G
+EV/MTNnT707an6QmFss/hvghfcU6MjTIy4WtxD/ks62Op2eeDDtaWClfzpY74/XK
+Qut7RNV1AgMBAAGjUDBOMB0GA1UdDgQWBBSyPhk1wcRPI3ntv+jcXDED8C8VdzAf
+BgNVHSMEGDAWgBSyPhk1wcRPI3ntv+jcXDED8C8VdzAMBgNVHRMEBTADAQH/MA0G
+CSqGSIb3DQEBBQUAA4GBAMPsHz6xh9CAEPm/cxs41LG3gE3qIMF5ffVYQhETKKux
+tAqInCBNnLVaQShe9mleVbviGrnGYjiGMnuTKMqer9EG+ZPCXZLAJWhq4f6FKhmn
+axdNI5py1tDBgP90EItiehHDmocq5H3RjHKmv8E72LgzwP+w99YOo902/opBoJjM
+-----END CERTIFICATE-----
diff --git a/test/server/serfservercert.pem b/test/server/serfservercert.pem
new file mode 100644
index 0000000..086e0e5
--- /dev/null
+++ b/test/server/serfservercert.pem
@@ -0,0 +1,50 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 1048579 (0x100003)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite CA, CN=Serf CA/emailAddress=serfca@example.com
+ Validity
+ Not Before: Apr 13 11:41:01 2013 GMT
+ Not After : Apr 13 11:41:01 2014 GMT
+ Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Server, CN=Serf Server/emailAddress=serfserver@example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:aa:8d:56:e7:0d:99:03:9b:3f:b3:c0:2a:63:33:
+ 51:65:4b:e7:d2:6c:60:d2:52:d7:8a:6d:c9:8b:93:
+ 3d:4c:1a:eb:29:26:9c:19:dc:a5:a6:70:3f:0b:a7:
+ 69:4d:8b:35:00:b6:8f:f2:4f:b6:38:43:b9:a7:c8:
+ 2d:51:7f:f2:f7:00:28:48:b8:f7:9a:7d:a5:7d:5c:
+ 17:f7:d0:14:54:86:39:88:43:1d:5c:d8:d4:56:9f:
+ 88:a8:3c:47:7f:65:cf:94:56:b0:d8:b6:dd:25:66:
+ 34:ba:cb:43:cd:df:93:ce:27:1b:57:7f:8a:50:f5:
+ 5a:33:d3:55:52:ff:9e:f7:4f
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 82:02:80:89:ec:c2:56:51:1f:d1:f6:2f:8c:d9:50:49:c2:7f:
+ 00:76:53:65:15:96:bb:0f:7e:b3:5b:06:c2:9c:44:77:34:e9:
+ 64:41:ca:cd:aa:41:4a:6f:b0:95:cb:41:11:1b:75:0e:5e:d6:
+ 34:80:8f:22:a9:e4:ce:cd:9a:b6:0c:96:7e:e6:2a:f0:ce:eb:
+ 86:7a:2b:df:b8:13:3a:c8:b5:9d:5b:71:9c:40:61:56:c6:f9:
+ 90:b8:4f:1d:14:88:b2:ad:40:08:f5:88:ab:10:5d:74:6d:a6:
+ 29:3d:1b:01:68:9f:29:48:24:d9:3d:52:47:ca:bf:22:af:fd:
+ 7b:df
+-----BEGIN CERTIFICATE-----
+MIICvzCCAigCAxAAAzANBgkqhkiG9w0BAQUFADCBoDELMAkGA1UEBhMCQkUxEDAO
+BgNVBAgMB0FudHdlcnAxETAPBgNVBAcMCE1lY2hlbGVuMR8wHQYDVQQKDBZJbiBT
+ZXJmIHdlIHRydXN0LCBJbmMuMRYwFAYDVQQLDA1UZXN0IFN1aXRlIENBMRAwDgYD
+VQQDDAdTZXJmIENBMSEwHwYJKoZIhvcNAQkBFhJzZXJmY2FAZXhhbXBsZS5jb20w
+HhcNMTMwNDEzMTE0MTAxWhcNMTQwNDEzMTE0MTAxWjCBrDELMAkGA1UEBhMCQkUx
+EDAOBgNVBAgMB0FudHdlcnAxETAPBgNVBAcMCE1lY2hlbGVuMR8wHQYDVQQKDBZJ
+biBTZXJmIHdlIHRydXN0LCBJbmMuMRowGAYDVQQLDBFUZXN0IFN1aXRlIFNlcnZl
+cjEUMBIGA1UEAwwLU2VyZiBTZXJ2ZXIxJTAjBgkqhkiG9w0BCQEWFnNlcmZzZXJ2
+ZXJAZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKqNVucN
+mQObP7PAKmMzUWVL59JsYNJS14ptyYuTPUwa6ykmnBncpaZwPwunaU2LNQC2j/JP
+tjhDuafILVF/8vcAKEi495p9pX1cF/fQFFSGOYhDHVzY1FafiKg8R39lz5RWsNi2
+3SVmNLrLQ83fk84nG1d/ilD1WjPTVVL/nvdPAgMBAAEwDQYJKoZIhvcNAQEFBQAD
+gYEAggKAiezCVlEf0fYvjNlQScJ/AHZTZRWWuw9+s1sGwpxEdzTpZEHKzapBSm+w
+lctBERt1Dl7WNICPIqnkzs2atgyWfuYq8M7rhnor37gTOsi1nVtxnEBhVsb5kLhP
+HRSIsq1ACPWIqxBddG2mKT0bAWifKUgk2T1SR8q/Iq/9e98=
+-----END CERTIFICATE-----
diff --git a/test/server/serfserverkey.pem b/test/server/serfserverkey.pem
new file mode 100644
index 0000000..ed461a2
--- /dev/null
+++ b/test/server/serfserverkey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8412FEAB72C5064F
+
+7hX15avmcrhdzHcirFHRc3clpNSnln+QFAsqXZjVc0TGWSKkrpQco783LDfIzLF1
+SWQUseIsIfELrxuFRV32kEwI75pwP27X82M5sDhp2Bw3Dxv++ZeMNRoCX1a3+fkO
+2I9QC6KFbvqdMeQXDAcwJXrR9ASCHtVoQbrdoMpoBo6n4NwRrF9loaPHtHgSnF64
+dQjmT0s7QU99qW/PbODjzfzpY+rqrtyu3lXx+XVkFTWrDTU+DpFXfOyUF3iqSd5U
+pEW1pimvRPF5geG8xxhAeOEfb8XZJINsfs1OI/5zpPyeXmBnwVNdgEW368pZ2ePp
+1MUd6Te6OwXoZXkCYghWm4iQSv2zSulCUq6pa55Rgb5+Zl8d74+vJ9N4Gt+g+0w6
+PkhkhizZiExYFV1GYmmTRx9BjzXgmo9qMDDtr9xENYB5KWgvSm1KmmUxKFZJZcPu
+zkv7vvlwrCPsUlsEOySanA0h6IME+ktPaQkBBG1aa28uorZD4Nbl81XYVt7jNifC
+hz9IHFxRjf51xA9WHQxDorztg74I0ZcOK1hcpCo40ivrI2Oruq3Zo/15eJNnorW2
+4cru/LaU29CZs1EaYLoANh7RFhTaQb+MkeYluwU7O6mF2DBaWvO+8lu61dLhLtEM
+SkJ3O1rOH5JzUf/bLat9L9fwGNJzPYcA1/3S6r+5q3tVdgR2s47v6WBOhXFFuR7K
+f5DC83PjOYSeWcgCoFP/Z1kW15pnJua4ORqo1NSvqFTh/jaeZHLDaX08f0GkR8s4
+c26JsBsKf6QWqQmISaWYQK2YgeEeAxM/tEnAUH2AouTJnu+6XzsL4w==
+-----END RSA PRIVATE KEY-----
diff --git a/test/server/test_server.c b/test/server/test_server.c
index 1ad2c9e..6130d6e 100644
--- a/test/server/test_server.c
+++ b/test/server/test_server.c
@@ -23,44 +23,6 @@
#include "test_server.h"
-struct serv_ctx_t {
- /* Pool for resource allocation. */
- apr_pool_t *pool;
-
- apr_int32_t options;
-
- /* Array of actions which server will replay when client connected. */
- test_server_action_t *action_list;
- /* Size of action_list array. */
- apr_size_t action_count;
- /* Index of current action. */
- apr_size_t cur_action;
-
- /* Array of messages the server will receive from the client. */
- test_server_message_t *message_list;
- /* Size of message_list array. */
- apr_size_t message_count;
- /* Index of current message. */
- apr_size_t cur_message;
-
- /* Number of messages received that the server didn't respond to yet. */
- apr_size_t outstanding_responses;
-
- /* Position in message buffer (incoming messages being read). */
- apr_size_t message_buf_pos;
-
- /* Position in action buffer. (outgoing messages being sent). */
- apr_size_t action_buf_pos;
-
- /* Address for server binding. */
- apr_sockaddr_t *serv_addr;
- apr_socket_t *serv_sock;
-
- /* Accepted client socket. NULL if there is no client socket. */
- apr_socket_t *client_sock;
-
-};
-
/* Replay support functions */
static void next_message(serv_ctx_t *servctx)
{
@@ -73,6 +35,20 @@ static void next_action(serv_ctx_t *servctx)
servctx->action_buf_pos = 0;
}
+static apr_status_t
+socket_write(serv_ctx_t *serv_ctx, const char *data,
+ apr_size_t *len)
+{
+ return apr_socket_send(serv_ctx->client_sock, data, len);
+}
+
+static apr_status_t
+socket_read(serv_ctx_t *serv_ctx, char *data,
+ apr_size_t *len)
+{
+ return apr_socket_recv(serv_ctx->client_sock, data, len);
+}
+
/* Verify received requests and take the necessary actions
(return a response, kill the connection ...) */
static apr_status_t replay(serv_ctx_t *servctx,
@@ -94,7 +70,7 @@ static apr_status_t replay(serv_ctx_t *servctx,
char buf[128];
apr_size_t len = sizeof(buf);
- status = apr_socket_recv(servctx->client_sock, buf, &len);
+ status = servctx->read(servctx, buf, &len);
if (! APR_STATUS_IS_EAGAIN(status)) {
/* we're out of actions! */
printf("Received more requests than expected.\n");
@@ -110,7 +86,7 @@ static apr_status_t replay(serv_ctx_t *servctx,
char buf[128];
apr_size_t len = sizeof(buf);
- status = apr_socket_recv(servctx->client_sock, buf, &len);
+ status = servctx->read(servctx, buf, &len);
if (status == APR_EOF) {
apr_socket_close(servctx->client_sock);
@@ -135,7 +111,7 @@ static apr_status_t replay(serv_ctx_t *servctx,
if (len > sizeof(buf))
len = sizeof(buf);
- status = apr_socket_recv(servctx->client_sock, buf, &len);
+ status = servctx->read(servctx, buf, &len);
if (status != APR_SUCCESS)
return status;
@@ -176,8 +152,9 @@ static apr_status_t replay(serv_ctx_t *servctx,
msg_len = strlen(action->text);
len = msg_len - servctx->action_buf_pos;
- status = apr_socket_send(servctx->client_sock,
- action->text + servctx->action_buf_pos, &len);
+ status = servctx->send(servctx,
+ action->text + servctx->action_buf_pos,
+ &len);
if (status != APR_SUCCESS)
return status;
@@ -219,7 +196,13 @@ apr_status_t test_server_run(serv_ctx_t *servctx,
const apr_pollfd_t *desc;
/* create a new pollset */
+#ifdef BROKEN_WSAPOLL
+ status = apr_pollset_create_ex(&pollset, 32, pool, 0,
+ APR_POLLSET_SELECT);
+#else
status = apr_pollset_create(&pollset, 32, pool, 0);
+#endif
+
if (status != APR_SUCCESS)
return status;
@@ -261,6 +244,13 @@ apr_status_t test_server_run(serv_ctx_t *servctx,
}
if (desc->desc.s == servctx->client_sock) {
+ if (servctx->handshake) {
+ status = servctx->handshake(servctx);
+ }
+
+ if (status)
+ goto cleanup;
+
/* Replay data to socket. */
status = replay(servctx, desc->rtnevents, pool);
@@ -286,20 +276,20 @@ cleanup:
return status;
}
-/* Start a TCP server on port SERV_PORT in thread THREAD. srv_replay is a array
- of action to replay when connection started. replay_count is count of
- actions in srv_replay. */
-apr_status_t test_start_server(serv_ctx_t **servctx_p,
- apr_sockaddr_t *address,
- test_server_message_t *message_list,
- apr_size_t message_count,
- test_server_action_t *action_list,
- apr_size_t action_count,
- apr_int32_t options,
- apr_pool_t *pool)
+
+/* Setup the context needed to start a TCP server on adress.
+ message_list is a list of expected requests.
+ action_list is the list of responses to be returned in order.
+ */
+void test_setup_server(serv_ctx_t **servctx_p,
+ apr_sockaddr_t *address,
+ test_server_message_t *message_list,
+ apr_size_t message_count,
+ test_server_action_t *action_list,
+ apr_size_t action_count,
+ apr_int32_t options,
+ apr_pool_t *pool)
{
- apr_status_t status;
- apr_socket_t *serv_sock;
serv_ctx_t *servctx;
servctx = apr_pcalloc(pool, sizeof(*servctx));
@@ -313,12 +303,58 @@ apr_status_t test_start_server(serv_ctx_t **servctx_p,
servctx->action_list = action_list;
servctx->action_count = action_count;
+ /* Start replay from first action. */
+ servctx->cur_action = 0;
+ servctx->action_buf_pos = 0;
+ servctx->outstanding_responses = 0;
+
+ servctx->read = socket_read;
+ servctx->send = socket_write;
+
+ *servctx_p = servctx;
+}
+
+void test_setup_https_server(serv_ctx_t **servctx_p,
+ apr_sockaddr_t *address,
+ test_server_message_t *message_list,
+ apr_size_t message_count,
+ test_server_action_t *action_list,
+ apr_size_t action_count,
+ apr_int32_t options,
+ const char *keyfile,
+ const char *certfile,
+ apr_pool_t *pool)
+{
+ serv_ctx_t *servctx;
+
+ test_setup_server(servctx_p, address, message_list,
+ message_count, action_list, action_count,
+ options, pool);
+
+ servctx = *servctx_p;
+
+ servctx->handshake = ssl_handshake;
+ /* Override with SSL encrypt/decrypt functions */
+ servctx->read = ssl_socket_read;
+ servctx->send = ssl_socket_write;
+
+ init_ssl_context(servctx, keyfile, certfile);
+}
+
+apr_status_t test_start_server(serv_ctx_t *servctx)
+{
+ apr_status_t status;
+ apr_socket_t *serv_sock;
+
/* create server socket */
#if APR_VERSION_AT_LEAST(1, 0, 0)
- status = apr_socket_create(&serv_sock, address->family, SOCK_STREAM, 0,
- pool);
+ status = apr_socket_create(&serv_sock, servctx->serv_addr->family,
+ SOCK_STREAM, 0,
+ servctx->pool);
#else
- status = apr_socket_create(&serv_sock, address->family, SOCK_STREAM, pool);
+ status = apr_socket_create(&serv_sock, servctx->serv_addr->family,
+ SOCK_STREAM,
+ servctx->pool);
#endif
if (status != APR_SUCCESS)
@@ -332,28 +368,29 @@ apr_status_t test_start_server(serv_ctx_t **servctx_p,
if (status != APR_SUCCESS)
return status;
- /* Start replay from first action. */
- servctx->cur_action = 0;
- servctx->action_buf_pos = 0;
- servctx->outstanding_responses = 0;
-
/* listen for clients */
- apr_socket_listen(serv_sock, SOMAXCONN);
+ status = apr_socket_listen(serv_sock, SOMAXCONN);
if (status != APR_SUCCESS)
return status;
servctx->serv_sock = serv_sock;
servctx->client_sock = NULL;
+
return APR_SUCCESS;
}
apr_status_t test_server_destroy(serv_ctx_t *servctx, apr_pool_t *pool)
{
- apr_socket_close(servctx->serv_sock);
+ apr_status_t status;
+
+ status = apr_socket_close(servctx->serv_sock);
if (servctx->client_sock) {
apr_socket_close(servctx->client_sock);
}
- return APR_SUCCESS;
+ if (servctx->ssl_ctx)
+ cleanup_ssl_context(servctx);
+
+ return status;
}
diff --git a/test/server/test_server.h b/test/server/test_server.h
index 9e8b0e2..65a61e6 100644
--- a/test/server/test_server.h
+++ b/test/server/test_server.h
@@ -16,8 +16,6 @@
#ifndef TEST_SERVER_H
#define TEST_SERVER_H
-typedef struct serv_ctx_t serv_ctx_t;
-
#define TEST_SERVER_DUMP 1
/* Default port for our test server. */
@@ -26,6 +24,15 @@ typedef struct serv_ctx_t serv_ctx_t;
#define PROXY_PORT 23456
+typedef struct serv_ctx_t serv_ctx_t;
+
+typedef apr_status_t (*send_func_t)(serv_ctx_t *serv_ctx, const char *data,
+ apr_size_t *len);
+typedef apr_status_t (*receive_func_t)(serv_ctx_t *serv_ctx, char *data,
+ apr_size_t *len);
+
+typedef apr_status_t (*handshake_func_t)(serv_ctx_t *serv_ctx);
+
typedef struct
{
enum {
@@ -44,14 +51,70 @@ typedef struct
const char *text;
} test_server_message_t;
-apr_status_t test_start_server(serv_ctx_t **servctx_p,
- apr_sockaddr_t *address,
- test_server_message_t *message_list,
- apr_size_t message_count,
- test_server_action_t *action_list,
- apr_size_t action_count,
- apr_int32_t options,
- apr_pool_t *pool);
+struct serv_ctx_t {
+ /* Pool for resource allocation. */
+ apr_pool_t *pool;
+
+ apr_int32_t options;
+
+ /* Array of actions which server will replay when client connected. */
+ test_server_action_t *action_list;
+ /* Size of action_list array. */
+ apr_size_t action_count;
+ /* Index of current action. */
+ apr_size_t cur_action;
+
+ /* Array of messages the server will receive from the client. */
+ test_server_message_t *message_list;
+ /* Size of message_list array. */
+ apr_size_t message_count;
+ /* Index of current message. */
+ apr_size_t cur_message;
+
+ /* Number of messages received that the server didn't respond to yet. */
+ apr_size_t outstanding_responses;
+
+ /* Position in message buffer (incoming messages being read). */
+ apr_size_t message_buf_pos;
+
+ /* Position in action buffer. (outgoing messages being sent). */
+ apr_size_t action_buf_pos;
+
+ /* Address for server binding. */
+ apr_sockaddr_t *serv_addr;
+ apr_socket_t *serv_sock;
+
+ /* Accepted client socket. NULL if there is no client socket. */
+ apr_socket_t *client_sock;
+
+ send_func_t send;
+ receive_func_t read;
+
+ handshake_func_t handshake;
+ void *ssl_ctx;
+};
+
+void test_setup_server(serv_ctx_t **servctx_p,
+ apr_sockaddr_t *address,
+ test_server_message_t *message_list,
+ apr_size_t message_count,
+ test_server_action_t *action_list,
+ apr_size_t action_count,
+ apr_int32_t options,
+ apr_pool_t *pool);
+
+void test_setup_https_server(serv_ctx_t **servctx_p,
+ apr_sockaddr_t *address,
+ test_server_message_t *message_list,
+ apr_size_t message_count,
+ test_server_action_t *action_list,
+ apr_size_t action_count,
+ apr_int32_t options,
+ const char *keyfile,
+ const char *certfile,
+ apr_pool_t *pool);
+
+apr_status_t test_start_server(serv_ctx_t *serv_ctx);
apr_status_t test_server_run(serv_ctx_t *servctx,
apr_short_interval_time_t duration,
@@ -59,6 +122,16 @@ apr_status_t test_server_run(serv_ctx_t *servctx,
apr_status_t test_server_destroy(serv_ctx_t *servctx, apr_pool_t *pool);
+apr_status_t init_ssl_context(serv_ctx_t *serv_ctx,
+ const char *keyfile,
+ const char *certfile);
+apr_status_t ssl_handshake(serv_ctx_t *servctx);
+apr_status_t ssl_socket_write(serv_ctx_t *serv_ctx, const char *data,
+ apr_size_t *len);
+apr_status_t ssl_socket_read(serv_ctx_t *serv_ctx, char *data, apr_size_t *len);
+void cleanup_ssl_context(serv_ctx_t *serv_ctx);
+
+
#ifndef APR_VERSION_AT_LEAST /* Introduced in APR 1.3.0 */
#define APR_VERSION_AT_LEAST(major,minor,patch) \
(((major) < APR_MAJOR_VERSION) \
@@ -67,4 +140,5 @@ apr_status_t test_server_destroy(serv_ctx_t *servctx, apr_pool_t *pool);
(patch) <= APR_PATCH_VERSION))
#endif /* APR_VERSION_AT_LEAST */
+
#endif /* TEST_SERVER_H */
diff --git a/test/server/test_sslserver.c b/test/server/test_sslserver.c
new file mode 100644
index 0000000..74492ec
--- /dev/null
+++ b/test/server/test_sslserver.c
@@ -0,0 +1,252 @@
+/* Copyright 2013 Justin Erenkrantz and Greg Stein
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "serf.h"
+#include "test_server.h"
+
+#include "serf_private.h"
+
+//#ifdef SERF_HAVE_OPENSSL
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#define TEST_VERBOSE 0
+
+static int init_done = 0;
+
+typedef struct ssl_context_t {
+ int handshake_done;
+
+ SSL_CTX* ctx;
+ SSL* ssl;
+ BIO *bio;
+
+} ssl_context_t;
+
+int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata)
+{
+ strncpy(buf, "serftest", size);
+ buf[size - 1] = '\0';
+ return strlen(buf);
+}
+
+static int bio_apr_socket_create(BIO *bio)
+{
+ bio->shutdown = 1;
+ bio->init = 1;
+ bio->num = -1;
+ bio->ptr = NULL;
+
+ return 1;
+}
+
+static int bio_apr_socket_destroy(BIO *bio)
+{
+ /* Did we already free this? */
+ if (bio == NULL) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static long bio_apr_socket_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ long ret = 1;
+
+ switch (cmd) {
+ default:
+ /* abort(); */
+ break;
+ case BIO_CTRL_FLUSH:
+ /* At this point we can't force a flush. */
+ break;
+ case BIO_CTRL_PUSH:
+ case BIO_CTRL_POP:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+/* Returns the amount read. */
+static int bio_apr_socket_read(BIO *bio, char *in, int inlen)
+{
+ apr_size_t len = inlen;
+ serv_ctx_t *serv_ctx = bio->ptr;
+ apr_status_t status;
+
+ BIO_clear_retry_flags(bio);
+
+ status = apr_socket_recv(serv_ctx->client_sock, in, &len);
+ if (status == APR_EAGAIN) {
+ BIO_set_retry_read(bio);
+ if (len == 0)
+ return -1;
+
+ }
+
+ if (SERF_BUCKET_READ_ERROR(status))
+ return -1;
+
+ serf__log(TEST_VERBOSE, __FILE__, "Read %d bytes from socket with status %d.\n",
+ len, status);
+
+ return len;
+}
+
+/* Returns the amount written. */
+static int bio_apr_socket_write(BIO *bio, const char *in, int inlen)
+{
+ apr_size_t len = inlen;
+ serv_ctx_t *serv_ctx = bio->ptr;
+
+ apr_status_t status = apr_socket_send(serv_ctx->client_sock, in, &len);
+
+ if (SERF_BUCKET_READ_ERROR(status))
+ return -1;
+
+ serf__log(TEST_VERBOSE, __FILE__, "Wrote %d of %d bytes to socket.\n",
+ len, inlen);
+
+ return len;
+}
+
+
+static BIO_METHOD bio_apr_socket_method = {
+ BIO_TYPE_SOCKET,
+ "APR sockets",
+ bio_apr_socket_write,
+ bio_apr_socket_read,
+ NULL, /* Is this called? */
+ NULL, /* Is this called? */
+ bio_apr_socket_ctrl,
+ bio_apr_socket_create,
+ bio_apr_socket_destroy,
+#ifdef OPENSSL_VERSION_NUMBER
+ NULL /* sslc does not have the callback_ctrl field */
+#endif
+};
+
+apr_status_t init_ssl_context(serv_ctx_t *serv_ctx,
+ const char *keyfile,
+ const char *certfile)
+{
+ ssl_context_t *ssl_ctx = apr_pcalloc(serv_ctx->pool, sizeof(*ssl_ctx));
+ serv_ctx->ssl_ctx = ssl_ctx;
+
+ /* Init OpenSSL globally */
+ if (!init_done)
+ {
+ CRYPTO_malloc_init();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ init_done = 1;
+ }
+
+ /* Init this connection */
+ if (!ssl_ctx->ctx) {
+ ssl_ctx->ctx = SSL_CTX_new(SSLv23_server_method());
+ SSL_CTX_set_cipher_list(ssl_ctx->ctx, "ALL");
+ SSL_CTX_set_default_passwd_cb(ssl_ctx->ctx, pem_passwd_cb);
+
+ ssl_ctx->ssl = SSL_new(ssl_ctx->ctx);
+ SSL_use_PrivateKey_file(ssl_ctx->ssl, keyfile, SSL_FILETYPE_PEM);
+ SSL_use_certificate_file(ssl_ctx->ssl, certfile, SSL_FILETYPE_PEM);
+
+
+ ssl_ctx->bio = BIO_new(&bio_apr_socket_method);
+ ssl_ctx->bio->ptr = serv_ctx;
+ SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio);
+ }
+
+ return APR_SUCCESS;
+}
+
+apr_status_t ssl_handshake(serv_ctx_t *serv_ctx)
+{
+ ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx;
+ int result;
+
+ if (ssl_ctx->handshake_done)
+ return APR_SUCCESS;
+
+ /* SSL handshake */
+ result = SSL_accept(ssl_ctx->ssl);
+ if (result == 1) {
+ serf__log(TEST_VERBOSE, __FILE__, "Handshake successful.\n");
+ ssl_ctx->handshake_done = 1;
+ }
+ else {
+ int ssl_err;
+
+ ssl_err = SSL_get_error(ssl_ctx->ssl, result);
+ switch (ssl_err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ return APR_EAGAIN;
+ default:
+ serf__log(TEST_VERBOSE, __FILE__, "SSL Error %d: ", ssl_err);
+ ERR_print_errors_fp(stderr);
+ serf__log_nopref(TEST_VERBOSE, "\n");
+ return APR_EGENERAL;
+ }
+ }
+
+ return APR_EAGAIN;
+}
+
+apr_status_t
+ssl_socket_write(serv_ctx_t *serv_ctx, const char *data,
+ apr_size_t *len)
+{
+ ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx;
+
+ int result = SSL_write(ssl_ctx->ssl, data, *len);
+ if (result > 0) {
+ *len = result;
+ return APR_SUCCESS;
+ }
+
+ return APR_EGENERAL;
+}
+
+apr_status_t
+ssl_socket_read(serv_ctx_t *serv_ctx, char *data,
+ apr_size_t *len)
+{
+ ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx;
+
+ int result = SSL_read(ssl_ctx->ssl, data, *len);
+ if (result > 0) {
+ *len = result;
+ return APR_SUCCESS;
+ }
+
+ return APR_EGENERAL;
+}
+
+void cleanup_ssl_context(serv_ctx_t *serv_ctx)
+{
+ ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx;
+
+ SSL_clear(ssl_ctx->ssl);
+ SSL_CTX_free(ssl_ctx->ctx);
+}
+//#endif /* SERF_HAVE_OPENSSL */ \ No newline at end of file