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