diff options
Diffstat (limited to 'test/server')
-rw-r--r-- | test/server/serfcacert.pem | 50 | ||||
-rw-r--r-- | test/server/serfrootcacert.pem | 60 | ||||
-rw-r--r-- | test/server/serfservercert.pem | 50 | ||||
-rw-r--r-- | test/server/serfserverkey.pem | 18 | ||||
-rw-r--r-- | test/server/test_server.c | 171 | ||||
-rw-r--r-- | test/server/test_server.h | 94 | ||||
-rw-r--r-- | test/server/test_sslserver.c | 252 |
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 |