1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*
17 * testssl: Simple APR SSL sockets test.
18 */
19
20#include "apr.h"
21#include "apr_general.h"
22#include "apr_pools.h"
23#include "apr_errno.h"
24#include "apr_getopt.h"
25#include "apr_time.h"
26#define APR_WANT_STRFUNC
27#include "apr_want.h"
28
29#include "apr_ssl.h"
30#include "apr_network_io.h"
31
32#if APR_HAVE_STDIO_H
33#include <stdio.h>
34#endif
35#if APR_HAVE_UNISTD_H
36#include <unistd.h>
37#endif
38#include <stdlib.h>     /* for atexit(), malloc() */
39#include <string.h>
40
41struct sslTestCase {
42    char *host;
43    int port;
44    const char *request;
45    int result;
46} tests[] = {
47    { "svn.apache.org", 443, "GET / HTTP/1.0\n\n", 1 },
48    { NULL }
49};
50
51static apr_ssl_socket_t *createSocket(apr_ssl_factory_t *asf,
52                                      apr_pollset_t *pollset,
53                                      apr_pool_t *pool, int blocking)
54{
55    apr_ssl_socket_t *sock;
56    apr_status_t rv;
57    printf("::Creating SSL socket\n");
58    rv = apr_ssl_socket_create(&sock, AF_INET, SOCK_STREAM, 0, asf, NULL);
59    if (rv != APR_SUCCESS) {
60        printf("\tFailed to create socket\n");
61        return NULL;
62    }
63    rv = apr_pollset_add_ssl_socket(pollset, sock);
64    if (rv != APR_SUCCESS) {
65        printf("\tFailed to add to pollset\n");
66        return NULL;
67    }
68    printf("\tOK\n");
69    return sock;
70}
71
72static apr_status_t connectSocket(apr_ssl_socket_t *sock,
73                                  const char *host, int port,
74                                  apr_pool_t *pool)
75{
76    apr_status_t rv;
77    apr_sockaddr_t *remoteSA;
78
79    printf("::Connecting socket\n");
80    rv = apr_sockaddr_info_get(&remoteSA, host, APR_UNSPEC, port, 0, pool);
81    if (rv != APR_SUCCESS) {
82        printf("\tFailed to get address for '%s', port %d\n", host, port);
83        return rv;
84    }
85    rv = apr_ssl_socket_connect(sock, remoteSA);
86    if (rv != APR_SUCCESS) {
87        printf("\tFailed to connect to '%s' port %d\n", host, port);
88        return rv;
89    }
90    printf("\tOK\n");
91    return rv;
92}
93
94static apr_status_t socketRead(apr_ssl_socket_t *sock,
95                               apr_pollset_t *pollset,
96                               char *buf, apr_size_t *len)
97{
98    int lrv;
99    const apr_pollfd_t *descs = NULL;
100    apr_status_t rv;
101
102    printf("::Reading from socket\n");
103    rv = apr_ssl_socket_set_poll_events(sock, APR_POLLIN);
104    if (rv != APR_SUCCESS) {
105        printf("\tUnable to change socket poll events!\n");
106        return rv;
107    }
108
109    rv = apr_pollset_poll(pollset, 30 * APR_USEC_PER_SEC, &lrv, &descs);
110    if (APR_STATUS_IS_TIMEUP(rv)) {
111        printf("\tTime up!\n");
112        return rv;
113    }
114
115    if (lrv != 1) {
116        printf("\tIncorrect return count, %d\n", lrv);
117        return rv;
118    }
119    if (descs[0].client_data != sock) {
120        printf("\tWrong socket returned?!\n");
121        return rv;
122    }
123    if ((descs[0].rtnevents & APR_POLLIN) == 0) {
124        printf("\tSocket wasn't ready? huh? req [%08x] vs rtn [%08x]\n",
125               descs[0].reqevents, descs[0].rtnevents);
126        return rv;
127    }
128    rv = apr_ssl_socket_recv(sock, buf, len);
129    if (rv == APR_SUCCESS)
130        printf("\tOK, read %d bytes\n", *len);
131    else
132        printf("\tFailed\n");
133    return rv;
134}
135
136static apr_status_t socketWrite(apr_ssl_socket_t *sock,
137                                apr_pollset_t *pollset,
138                                const char *buf, apr_size_t *len)
139{
140    int lrv;
141    const apr_pollfd_t *descs = NULL;
142    apr_status_t rv;
143
144    printf("::Writing to socket\n");
145    rv = apr_ssl_socket_set_poll_events(sock, APR_POLLOUT);
146    if (rv != APR_SUCCESS) {
147        printf("\tUnable to change socket poll events!\n");
148        return rv;
149    }
150
151    rv = apr_pollset_poll(pollset, 30 * APR_USEC_PER_SEC, &lrv, &descs);
152    if (APR_STATUS_IS_TIMEUP(rv)) {
153        printf("\tTime up!\n");
154        return rv;
155    }
156    if (lrv != 1) {
157        printf("\tIncorrect return count, %d\n", lrv);
158        return rv;
159    }
160    if (descs[0].client_data != sock) {
161        printf("\tWrong socket returned?!\n");
162        return rv;
163    }
164    if ((descs[0].rtnevents & APR_POLLOUT) == 0) {
165        printf("\tSocket wasn't ready? huh?\n");
166        return rv;
167    }
168    rv = apr_ssl_socket_send(sock, buf, len);
169    if (rv == APR_SUCCESS)
170        printf("\tOK, wrote %d bytes\n", *len);
171    else
172        printf("\tFailed\n");
173    return rv;
174}
175
176apr_status_t socketClose(apr_ssl_socket_t *sock, apr_pollset_t *pollset)
177{
178    apr_status_t rv;
179    printf("::Closing socket\n");
180    rv = apr_pollset_remove_ssl_socket(sock);
181    if (rv != APR_SUCCESS)
182        printf("\tUnable to remove socket from pollset?\n");
183    rv = apr_ssl_socket_close(sock);
184    if (rv != APR_SUCCESS)
185        printf("\tFailed to close SSL socket\n");
186    else
187        printf("\tOK\n");
188    return rv;
189}
190
191
192int main(int argc, const char * const * argv)
193{
194    apr_pool_t *pool;
195    apr_ssl_factory_t *asf = NULL;
196    apr_status_t rv;
197    apr_pollset_t *pollset;
198
199    (void) apr_initialize();
200    apr_pool_create(&pool, NULL);
201    atexit(apr_terminate);
202
203    printf("SSL Library: %s\n", apr_ssl_library_name());
204
205    if (apr_pollset_create(&pollset, 1, pool, 0) != APR_SUCCESS) {
206        printf("Failed to create pollset!\n");
207        exit(1);
208    }
209
210    if (apr_ssl_factory_create(&asf, NULL, NULL, NULL,
211                               APR_SSL_FACTORY_CLIENT, pool) != APR_SUCCESS) {
212        fprintf(stderr, "Unable to create client factory\n");
213    } else {
214        int i;
215        for(i = 0; tests[i].host; i++) {
216            apr_ssl_socket_t *sslSock = createSocket(asf, pollset, pool, 0);
217            if (!sslSock)
218                continue;
219
220            rv = connectSocket(sslSock, tests[i].host, tests[i].port, pool);
221            if (rv == APR_SUCCESS) {
222                apr_size_t len = strlen(tests[i].request);
223                rv = socketWrite(sslSock, pollset, tests[i].request, &len);
224                if (rv == APR_SUCCESS) {
225                    char buffer[4096];
226                    len = 4096;
227                    rv = socketRead(sslSock, pollset, buffer, &len);
228                }
229            }
230            socketClose(sslSock, pollset);
231        }
232    }
233
234    apr_pollset_destroy(pollset);
235    apr_pool_destroy(pool);
236
237    return 0;
238}
239
240
241