2014-06-26 18:26:42 +01:00
|
|
|
/* Copyright (c) 2014, Google Inc.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-10-02 23:35:35 +01:00
|
|
|
#if !defined(_POSIX_C_SOURCE)
|
2014-10-02 21:58:19 +01:00
|
|
|
#define _POSIX_C_SOURCE 201410L
|
2014-10-02 23:35:35 +01:00
|
|
|
#endif
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-10-01 01:51:57 +01:00
|
|
|
#include <openssl/base.h>
|
|
|
|
|
|
|
|
#if !defined(OPENSSL_WINDOWS)
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <netinet/in.h>
|
2014-08-04 20:06:28 +01:00
|
|
|
#include <string.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <unistd.h>
|
2014-10-01 01:51:57 +01:00
|
|
|
#else
|
|
|
|
#include <io.h>
|
|
|
|
#include <WinSock2.h>
|
|
|
|
#include <WS2tcpip.h>
|
|
|
|
#endif
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
#include <openssl/bio.h>
|
2014-09-12 00:11:15 +01:00
|
|
|
#include <openssl/crypto.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <openssl/err.h>
|
|
|
|
|
|
|
|
|
2014-10-01 01:51:57 +01:00
|
|
|
#if !defined(OPENSSL_WINDOWS)
|
|
|
|
static int closesocket(int sock) {
|
|
|
|
return close(sock);
|
|
|
|
}
|
2014-10-01 17:57:25 +01:00
|
|
|
|
|
|
|
static void print_socket_error(const char *func) {
|
|
|
|
perror(func);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static void print_socket_error(const char *func) {
|
|
|
|
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
|
|
|
|
}
|
2014-10-01 01:51:57 +01:00
|
|
|
#endif
|
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
static int test_socket_connect(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
int sock;
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
socklen_t sockaddr_len = sizeof(sin);
|
|
|
|
static const char kTestMessage[] = "test";
|
|
|
|
char hostname[80], buf[5];
|
|
|
|
BIO *bio;
|
|
|
|
|
|
|
|
memset(&sin, 0, sizeof(sin));
|
|
|
|
sin.sin_family = AF_INET;
|
2014-10-01 01:51:57 +01:00
|
|
|
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
|
2014-10-01 17:57:25 +01:00
|
|
|
print_socket_error("inet_pton");
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
|
2014-10-01 17:57:25 +01:00
|
|
|
print_socket_error("bind");
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listen(listening_sock, 1)) {
|
2014-10-01 17:57:25 +01:00
|
|
|
print_socket_error("listen");
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
|
|
|
|
sockaddr_len != sizeof(sin)) {
|
2014-10-01 17:57:25 +01:00
|
|
|
print_socket_error("getsockname");
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-01 01:51:57 +01:00
|
|
|
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
|
|
|
|
ntohs(sin.sin_port));
|
2014-06-20 20:00:00 +01:00
|
|
|
bio = BIO_new_connect(hostname);
|
|
|
|
if (!bio) {
|
|
|
|
fprintf(stderr, "BIO_new_connect failed.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BIO_write(bio, kTestMessage, sizeof(kTestMessage)) !=
|
|
|
|
sizeof(kTestMessage)) {
|
|
|
|
fprintf(stderr, "BIO_write failed.\n");
|
|
|
|
BIO_print_errors_fp(stderr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
|
|
|
|
if (sock < 0) {
|
2014-10-01 17:57:25 +01:00
|
|
|
print_socket_error("accept");
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-01 17:57:25 +01:00
|
|
|
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
|
|
|
|
print_socket_error("read");
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-01 01:51:57 +01:00
|
|
|
closesocket(sock);
|
|
|
|
closesocket(listening_sock);
|
2014-06-20 20:00:00 +01:00
|
|
|
BIO_free(bio);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
static int test_printf(void) {
|
2014-08-04 20:06:28 +01:00
|
|
|
/* Test a short output, a very long one, and various sizes around
|
|
|
|
* 256 (the size of the buffer) to ensure edge cases are correct. */
|
|
|
|
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
|
|
|
|
BIO *bio;
|
|
|
|
char string[1024];
|
|
|
|
int ret;
|
|
|
|
const uint8_t *contents;
|
2014-08-04 23:24:41 +01:00
|
|
|
size_t i, len;
|
2014-08-04 20:06:28 +01:00
|
|
|
|
|
|
|
bio = BIO_new(BIO_s_mem());
|
|
|
|
if (!bio) {
|
|
|
|
fprintf(stderr, "BIO_new failed\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-04 23:24:41 +01:00
|
|
|
for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
|
2014-08-04 20:06:28 +01:00
|
|
|
if (kLengths[i] >= sizeof(string)) {
|
|
|
|
fprintf(stderr, "Bad test string length\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memset(string, 'a', sizeof(string));
|
|
|
|
string[kLengths[i]] = '\0';
|
|
|
|
|
|
|
|
ret = BIO_printf(bio, "test %s", string);
|
|
|
|
if (ret != 5 + kLengths[i]) {
|
2014-10-01 17:57:25 +01:00
|
|
|
fprintf(stderr, "BIO_printf failed: %d\n", ret);
|
2014-08-04 20:06:28 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!BIO_mem_contents(bio, &contents, &len)) {
|
|
|
|
fprintf(stderr, "BIO_mem_contents failed\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (len != 5 + kLengths[i] ||
|
|
|
|
strncmp((const char *)contents, "test ", 5) != 0 ||
|
|
|
|
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
|
|
|
|
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!BIO_reset(bio)) {
|
|
|
|
fprintf(stderr, "BIO_reset failed\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BIO_free(bio);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
int main(void) {
|
2014-10-01 17:57:25 +01:00
|
|
|
#if defined(OPENSSL_WINDOWS)
|
|
|
|
WSADATA wsa_data;
|
|
|
|
WORD wsa_version;
|
|
|
|
int wsa_err;
|
|
|
|
#endif
|
|
|
|
|
2014-09-12 00:11:15 +01:00
|
|
|
CRYPTO_library_init();
|
2014-06-20 20:00:00 +01:00
|
|
|
ERR_load_crypto_strings();
|
|
|
|
|
2014-10-01 17:57:25 +01:00
|
|
|
#if defined(OPENSSL_WINDOWS)
|
|
|
|
/* Initialize Winsock. */
|
|
|
|
wsa_version = MAKEWORD(2, 2);
|
|
|
|
wsa_err = WSAStartup(wsa_version, &wsa_data);
|
|
|
|
if (wsa_err != 0) {
|
|
|
|
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (wsa_data.wVersion != wsa_version) {
|
|
|
|
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
if (!test_socket_connect()) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-08-04 20:06:28 +01:00
|
|
|
if (!test_printf()) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
printf("PASS\n");
|
|
|
|
return 0;
|
|
|
|
}
|